0 min left
Listmonk SMTP Server Setup for Large Lists

Listmonk SMTP Server Setup for Large Lists

BulkEmailSetup
BulkEmailSetup Team
October 15, 2026
10 min read

Listmonk is a single Go binary and a PostgreSQL database, it costs nothing, and on a 4 vCPU box it will push a 500,000-subscriber campaign in about 83 minutes at 100 messages a second. The setup that matters is not the install, it is four numbers in Settings: max connections, message rate, retries and batch size. Get those wrong and you either crawl at 200 emails an hour or hammer your own MTA until receivers defer you. Here is the config I run for large lists, and the box underneath it.

What listmonk is, and what it is not

Listmonk is a list manager and campaign sender. That is the whole product, and the narrowness is the point.

CapabilityListmonkMauticMailWizz
List and subscriber managementYesYesYes
SQL-based segmentationYes, raw SQL queriesFilter builderFilter builder
One-off and scheduled campaignsYesYesYes
Visual automation flow builderNoYesLimited
Behavioural triggers, lead scoringNoYesNo
Landing pages, forms beyond opt-inNoYesBasic
Multi-tenant customer accountsNoNoYes
Licence cost$0, AGPLv3$0~$100 one-time
RuntimeOne Go binaryPHP plus MySQL plus cronPHP plus MySQL plus cron

Want drip sequences that fire on behaviour? Wrong tool, read the Mautic SMTP configuration guide. Want per-client separation to resell sending? See MailWizz SMTP setup.

What you get for the missing features is speed and almost no operational surface. No cron jobs, no PHP-FPM, no worker daemon. The binary is the app and the queue, pulling subscribers from Postgres in batches and pushing them over a pooled set of SMTP connections.

The SMTP settings that actually matter

Settings then SMTP in the admin UI. You can define several SMTP blocks and toggle each.

SettingSane value for a dedicated serverWhy
Hostmail.yourdomain.comThe MTA you control
Port587STARTTLS. Use 465 only if the server offers implicit TLS
Auth protocolPLAIN (or LOGIN)Use cram only if the MTA insists
TLSSTARTTLS, skip verify OFFNever disable cert verification on a live sender
Max connections10Concurrent sockets held open for the campaign
Idle timeout15sFrees sockets between campaigns
Message rate10 per second per connection10 x 10 = 100/sec total throughput
Retries2A silent re-send over a different pooled connection

The pair that matters is max connections and message rate, because listmonk multiplies them. Ten connections at 10 per second is 100 emails a second, or 360,000 an hour. Far more than a freshly warmed IP should be doing.

Retries needs a note. The listmonk configuration docs define it as the number of times a message failing at the moment of sending is retried silently over a different pooled connection. Transport retry, not delivery retry. A hard 5xx will not become a delivery on a second socket, so 2 is plenty.

Batch size sits under Settings then Performance and sets how many subscribers get pulled from Postgres per cycle, roughly every 5 seconds. Default 1,000 is fine. Raise it to 5,000 only if database round trips are demonstrably the bottleneck, which at 500K they usually are not.

Sizing the box and tuning Postgres

Listmonk itself barely registers, sitting at 150 to 400 MB of RSS even mid-campaign because the Go binary streams rather than buffering the whole list. PostgreSQL is what you actually pay for.

List sizevCPURAMshared_buffersDisk
Up to 100K24 GB1 GB40 GB NVMe
100K to 500K48 GB2 GB80 GB NVMe
500K to 2M816 GB4 GB200 GB NVMe

Two Postgres settings do most of the work: shared_buffers at roughly 25% of RAM, and work_mem at 32MB to 64MB so the segmentation queries do not spill to disk. Set them and restart:

shared_buffers = 2GB
work_mem = 64MB
maintenance_work_mem = 512MB
effective_cache_size = 6GB

The thing that bites at month six is table bloat. Every campaign writes view and click rows, and every subscriber update leaves a dead tuple. The listmonk docs are explicit about running VACUUM ANALYZE on a schedule, so cron it weekly:

0 3 * * 0 psql -U listmonk -d listmonk -c "VACUUM ANALYZE;"

Also turn on slow-query caching in Settings then Performance. It stops the dashboard and subscribers page counting rows in real time, using periodic cached counts instead. At 500K that is a dashboard loading in 200ms rather than 8 seconds.

Bounce processing, the part people skip

An unconfigured bounce setup is how a good list rots. Listmonk gives you three routes, and they are not equal.

MethodSetup effortLatencyBest for
POP3 bounce mailboxMedium, needs a mailbox and Return-PathMinutes, polledYour own MTA (Postfix, Postal)
SES or SendGrid webhookLow, paste a URL in the provider consoleSecondsAnyone relaying through SES
Generic /webhooks/bounceHigh, you write the scriptSecondsParsing MTA logs directly

Turn it on in Settings then Bounces. Point the mailbox at [email protected] and make sure campaigns send that address in the Return-Path header, or the bounces land somewhere listmonk never reads. Then set thresholds. Per the listmonk docs on bounce processing, you configure a count per bounce type and an action. My values:

Bounce typeCount before actionAction
Hard1Blocklist
Soft3Blocklist
Complaint1Blocklist

One hard bounce is enough. The address does not exist and will not start existing. Soft at 3 gives a genuinely full mailbox a couple of chances. Complaints at 1 is not negotiable: Google's bulk sender guidelines put the spam complaint ceiling at 0.3% with a target under 0.1%, and you do not get there by keeping people who hit the spam button. More in email bounce handling best practices.

Listmonk classifies bounces with heuristics, reading the body and the status code, and anything unmatched defaults to soft. Reasonable, but a badly worded rejection from an obscure host can sit as soft forever. Check the hard/soft split after your first few campaigns.

Double opt-in and list hygiene

Listmonk has proper double opt-in in the public subscription page and the import flow. Use it. A single opt-in list at 500K carries spam traps you cannot see, and traps turn a reputation problem into a Spamhaus listing. Rules for a large install:

  1. Set new lists to double opt-in, not single, at creation.
  2. Send the opt-in confirmation campaign to every imported segment before mailing it.
  3. Keep subscribers who never confirm in the unconfirmed state and never mail them.
  4. Use SQL segments for re-engagement, for example subscribers with no click in 12 months, and mail that segment separately at a lower rate.
  5. Export the blocklist monthly and keep it, because it is your suppression list if you ever change tools.

The SQL segmentation is genuinely good here. You write raw SQL against the subscribers table, so last-clicked-over-365-days is one line rather than a filter builder puzzle.

Volume maths for a 500K list

Assume 500,000 subscribers, one campaign.

ConfigEffective rateTime to finish 500K
5 connections, 5 msg/sec25/sec5 hr 33 min
10 connections, 5 msg/sec50/sec2 hr 47 min
10 connections, 10 msg/sec100/sec1 hr 23 min
20 connections, 10 msg/sec200/sec42 min

Faster is not better. Pushing 200 per second at Gmail from a young IP earns 4xx deferrals, which listmonk retries, which makes the campaign slower than going at 25 would have been.

My rule: set the rate so the campaign finishes in 2 to 4 hours. Slow enough that receiver throttling never engages, fast enough to be done before lunch. For 500K that is 35 to 70 per second, so 10 connections at 5 per second is what I run. Still warming? Cap it lower and follow an IP warm-up schedule. Postfix ships with default_process_limit = 100, so 10 connections is comfortable and 40 is not.

What it costs at 100K, 500K and 2M a month

Listmonk is free, so the cost is the box plus mail transport. Monthly, rounded.

Line item100K/month500K/month2M/month
Listmonk licence$0$0$0
VPS running listmonk and Postgres$12$24$48
Listmonk plus Amazon SES at $0.10/1K$10$50$200
Total, listmonk plus SES$22$74$248
Total, listmonk plus dedicated SMTP server~$60~$70~$110
Hosted ESP at same volume$100 to $250$400 to $700$1,200 to $2,500

SES is cheapest at low volume and stays cheap, but it is shared infrastructure under Amazon's sending policy, and a complaint spike gets your account reviewed. A dedicated server costs more at 100K and less at 2M, and nobody reviews your account. Mailchimp at 500,000 sends with a comparable contact count sits in the $500 to $700 range, roughly ten times the listmonk plus SES total. Full breakdown in cost to send 500,000 emails per month.

The cost missing from the table is your time. Postgres backups, TLS renewal, OS patching and VACUUM are yours now. Budget an hour a month and a bad afternoon once a year.

Go-live checklist

Before the first real campaign, in order.

  1. DNS. SPF, DKIM and DMARC published for the sending domain, DMARC starting at p=none.
  2. rDNS. The sending IP's PTR record resolves to your HELO hostname and back again.
  3. SMTP block. Host, port 587, STARTTLS, auth set, skip-verify off. Hit the test button.
  4. Rate. Max connections 10, message rate 5 per second, retries 2.
  5. Bounces. Enabled, POP3 mailbox or SES webhook configured, thresholds set to 1 hard / 3 soft / 1 complaint.
  6. Return-Path. Points at the bounce mailbox, verified by sending to a known-dead address.
  7. Opt-in. Lists set to double opt-in, unconfirmed subscribers excluded from campaigns.
  8. Postgres. shared_buffers tuned, weekly VACUUM ANALYZE in cron, nightly pg_dump off the box.
  9. Performance. Slow-query caching on, batch size 1,000.
  10. Test send. A campaign to a 50-address seed segment, then check headers for DKIM d= alignment before you touch the real list.

Step 10 is the one people skip and regret. A misaligned DKIM domain on a 500K send cannot be taken back.

How BulkEmailSetup helps

Listmonk solves the campaign side for free. It does not give you an IP, a warmed reputation, or an MTA still delivering in six months. That is the dedicated SMTP server, and it is where self-hosted stacks fail, not in the software.

We supply listmonk-ready SMTP: credentials that drop into the Settings panel, dedicated IPs warmed on a managed schedule, and server-side rate limits matched to the warm-up so your message rate never outruns your reputation. Basic is $549 one-time for 1 SMTP server, 3 dedicated IPs, 25,000 emails/day and unlimited contacts; higher tiers go to 15 IPs and 200,000 emails/day. Details on the pricing page.

Frequently asked questions

What SMTP settings does listmonk need?

In Settings > SMTP, add your host, port 587 with STARTTLS (or 465 for implicit TLS), auth protocol PLAIN or LOGIN, and your username and password. The two settings that actually decide throughput are max connections and the per-connection message rate, both under the same panel. Retries defaults to a silent re-send over a different pooled connection.

How many concurrent SMTP connections should listmonk use?

Ten concurrent connections is a sane default for a single dedicated SMTP server. Postfix ships with a default process limit of 100, so 10 leaves plenty of headroom, and each listmonk connection holds a socket open for the whole campaign. Raising it past 25 rarely helps because the bottleneck moves to the receiving side, not your box.

How long does listmonk take to send to 500,000 subscribers?

At 10 connections and 10 messages per second per connection, that is 100 messages a second, so 500,000 emails takes about 83 minutes. Cut the rate to 5 per second and the same campaign runs about 2 hours 47 minutes. Most people should send slower than their hardware allows, because receiver throttling is the real limit.

Does listmonk handle bounces?

Yes. Listmonk reads a bounce mailbox over POP3, accepts webhooks from Amazon SES, SendGrid, Postmark and a few others, and exposes a generic /webhooks/bounce endpoint for your own scripts. You set a bounce count threshold per type and an action, and Blocklist is the one worth using.

Can listmonk do marketing automation and drip flows?

No. Listmonk is a list manager and campaign sender, so there is no visual flow builder, no behavioural triggers and no lead scoring. It has lists, segments via SQL queries, templates, campaigns and an API. If you need multi-step automation, Mautic is the closer self-hosted match.

What server does listmonk need for a 500K list?

Four vCPU, 8 GB RAM and NVMe storage handles a 500K-subscriber install comfortably. Listmonk itself is a single Go binary using a few hundred MB; PostgreSQL is what needs the memory, so give shared_buffers about 2 GB and run VACUUM ANALYZE on a schedule. Storage grows with campaign view and click rows, not just subscribers.

Is listmonk actually free?

Yes, listmonk is open source under AGPLv3 with no licence fee, no subscriber tier and no send limit in the software. Your only costs are the box it runs on and whatever carries the mail, which is why the total at 500K emails a month lands around $40 to $100 instead of $600 plus at a hosted ESP.

Tags

listmonk smtp setuplistmonkself-hosted email marketingbulk email softwarebounce handlingpostgresql tuningdedicated smtp server
BulkEmailSetup

Written by BulkEmailSetup Team

We help businesses set up their own bulk email infrastructure, dedicated SMTP servers, IP rotation, and full deliverability control. One-time setup, no monthly platform fees.

Ready to set up your email infrastructure?

Get dedicated SMTP servers, IP rotation, and expert support to scale your email sending.

View Pricing