Per-Domain Mail Queues in Exim

5/5 - (2 votes)

 

When you manage email on a cPanel server, you eventually face the classic Exim bottleneck:
one misbehaving domain can clog the queue and grind mail delivery to a halt for everyone else.

Picture this: a compromised account starts blasting out spam, or a single domain’s messages are all soft-bouncing at Outlook or Yahoo. Suddenly, your entire mail queue is backlogged, and critical messages from other customers get stuck waiting behind the flood.

This is where per-domain mail queues come in. By splitting Exim’s spool directories on a per-domain basis, you can isolate abusive or unlucky senders and prevent them from taking everyone else down with them.


Why the Default Exim Queue Fails at Scale

By default, Exim maintains a single global mail queue under /var/spool/exim/. All domains share this queue. That means:

  • If one domain generates thousands of deferred messages, the queue runner must churn through them before moving on.

  • A retry storm from one provider (e.g., AOL throttling your IP) can starve deliveries to Gmail, corporate servers, and everywhere else.

  • Administrators are forced to flush the entire queue or implement blunt tools like per-domain rate limiting.

In short: global queues don’t scale in multi-tenant environments like shared hosting.


The Solution: Per-Domain Mail Queues

Exim supports splitting the spool into sub-queues, which can be organized by domain. With this setup:

  • Each sending domain has its own queue directory.

  • Queue runners process domains independently.

  • If one domain is “sick” (spamming, deferred, throttled), others keep moving normally.

This is especially powerful on cPanel/WHM servers, where dozens or hundreds of domains share one Exim instance.


How to Enable Per-Domain Queues in Exim

Note: These steps assume you’re comfortable editing Exim configs on a cPanel server. WHM may overwrite changes during updates, so use the Exim Configuration Manager → Advanced Editor where possible.

  1. Enable queue splitting in Exim
    Edit (or add) the following in the advanced configuration:

    queue_run_max = 5
    split_spool_directory = true

    This instructs Exim to create subdirectories in its spool.

  2. Split by domain, not just by hash
    By default, split_spool_directory splits by hash, which isn’t enough.
    To split queues per domain, you’ll need to modify how queue runners are called.

    Add a cron or systemd timer to run something like:

    exiqgrep -y 60 -f '' | awk '{print $4}' | sort | uniq | while read domain; do
    exim -R @$domain
    done
    • exiqgrep -y 60 -f '' → grabs messages deferred for more than 60 seconds.

    • awk '{print $4}' → extracts domains.

    • exim -R @$domain → runs a queue flush for that domain only.

    This way, queue processing is isolated to the domain instead of global churn.

  3. Optional: Limit concurrency per domain
    Add to Exim config:

    remote_max_parallel = 10
    hosts_max_try = 2

    This prevents one domain from overwhelming outbound connections.


Monitoring Per-Domain Queues

Once enabled, you can inspect queues per domain like so:

exim -bp | exiqsumm | grep example.com

Or for an overview of top offenders:

exim -bp | exiqsumm | sort -nr -k3 | head

This quickly shows which domains are clogging up their own queues without affecting others.


Caveats & Gotchas

  • cPanel updates: WHM loves to reset configs. Always implement changes through the Advanced Editor in Exim Config Manager where possible.

  • Disk I/O: Splitting queues increases the number of spool directories, which can stress disks if you’re handling huge mail volumes. Consider SSD-backed spool storage.

  • Not officially documented: cPanel doesn’t provide first-class support for per-domain queues, so you’re on your own if something breaks.

  • Abuse masking: Per-domain queues prevent collateral damage, but you still need monitoring to stop compromised accounts from hammering.


Why This Matters

Shared hosting is all about isolation. You already isolate users by filesystem, CPU, and PHP-FPM pools — email should be no different. With per-domain queues, you:

  • Improve reliability for well-behaved customers.

  • Contain the impact of spammers or misconfigured clients.

  • Gain clearer visibility into which domains are causing delivery headaches.

In a world where inbox providers are stricter than ever, this small tweak can mean the difference between smooth mail flow and nightly queue firefighting.


 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top