Tune Postfix Queue Delivery Safely with qmgr

Mail piling up in the Postfix deferred queue? Before you crank up qmgr's concurrency, learn what it is actually doing. You will see where the queue manager fits, inspect the live queue defaults, and make one controlled delivery change that survives a reload. Allow about 20 minutes, plus time to watch the result. The examples are for the installed Postfix 3.8.6 package on this machine.

1. Check the service and configuration

qmgr is a daemon, not a command-line queue viewer. Postfix's master process starts it, and it arranges delivery through the delivery processes. Do not try to launch qmgr by hand.

Start with these unprivileged checks:

$ postconf mail_version queue_directory config_directory
mail_version = 3.8.6
queue_directory = /var/spool/postfix
config_directory = /etc/postfix

Your package revision may differ while the major and minor Postfix version stay the same.

Tip: The queue manager is a persistent process that reads main.cf settings, so editing the file alone does not change its running behaviour.

Checkpoint: You know which Postfix installation you are inspecting and where its queue and configuration live.

2. Map the queues before changing anything

The queue manager keeps a separate directory for each stage:

Listing them is read-only, but the spool is normally restricted, so use elevated privileges for this inspection only:

$ sudo find "$(postconf -h queue_directory)" -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | sort
active
bounce
corrupt
defer
deferred
hold
incoming
trace

The exact list depends on the installation. A large deferred queue means delivery has been postponed; it does not tell you why. Read the Postfix log and the destination's response before increasing concurrency.

3. Inspect qmgr's important defaults

Start with the settings for retry timing, per-destination parallelism and recipients held in memory:

$ postconf minimal_backoff_time maximal_backoff_time queue_run_delay maximal_queue_lifetime
minimal_backoff_time = 300s
maximal_backoff_time = 4000s
queue_run_delay = 300s
maximal_queue_lifetime = 5d
$ postconf initial_destination_concurrency default_destination_concurrency_limit default_destination_recipient_limit
initial_destination_concurrency = 5
default_destination_concurrency_limit = 20
default_destination_recipient_limit = 50

These are defaults, not promises that every message uses all of them.

Two easy traps:

Checkpoint: Save the output in your change record, and decide whether the bottleneck is retry timing, destination concurrency, recipient batching or the remote system.

4. Make one small, reversible change

For a temporary remote outage, easing pressure is usually safer than making Postfix more aggressive. For example, set a longer queue scan interval so deferred mail is checked less often. This changes the persistent configuration:

$ sudo postconf -e 'queue_run_delay = 600s'
$ postconf queue_run_delay
queue_run_delay = 600s

The command edits /etc/postfix/main.cf through Postfix's configuration tool. It does not restart the service and does not immediately alter the running queue manager. Record the old value first so recovery is exact.

Tip: Only shorten the scan interval when you have a real reason to check deferred mail more often; that can increase disk and network activity.

Warning: Do not lower retry intervals or raise concurrency to hide remote 4xx responses, rate limits or connection failures. That can amplify load and make the outage worse. Change one setting at a time, and never edit the queue directories by hand.

5. Reload and verify the running daemon

After a main.cf change you must reload Postfix.

Warning: A reload is a service-disrupting control action. Use a maintenance window if your mail flow is sensitive.

$ sudo postfix reload
$ postconf queue_run_delay
queue_run_delay = 600s

The reload asks the Postfix process manager to apply configuration to persistent daemons, including qmgr.

Checkpoint: The system's Postfix log shows the reload and subsequent delivery activity. The qmgr manual says problems and transactions are logged through syslogd or postlogd; the exact log file is distribution-specific.

Recovery: If the change was wrong, restore the recorded value and reload again. That is the undo path for this example.

$ sudo postconf -e 'queue_run_delay = 300s'
$ sudo postfix reload
$ postconf queue_run_delay
queue_run_delay = 300s

Warning: Do not remove deferred messages to make a queue count look better. Deleting queued mail is a separate, potentially irreversible operation.

6. Diagnose symptoms without guessing

A few qmgr behaviours explain most "why is this mail still stuck?" moments:

Together these explain why a new message can be delivered while older mail stays deferred, and why repeatedly forcing scans is not a cure.

Done means