Home / Alt manpages / qmgr(8postfix)

  • qmgr(8postfix)
  • Postfix admin command
  • linux

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:

  • incoming holds new mail waiting to be picked up.
  • active holds messages opened for delivery.
  • deferred holds messages that previously got a temporary failure.
  • hold holds mail deliberately kept back.
  • corrupt is where damaged queue files go.
  • bounce, defer and trace keep delivery status data separately.

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.

  • Transports can override. A destination's transport can override the matching transport_... parameter.
  • Slow start and feedback. A destination that fails during connection or handshake can have delivery suspended, while successful deliveries let concurrency grow.
  • History. The qmgr manual notes that minimal_backoff_time defaulted to 1000s before Postfix 2.4, so old tuning advice may quote that figure.

Two easy traps:

  • queue_run_delay is not a retry schedule. It is the interval between deferred-queue scans. Each deferred message also has its own backoff and timestamp, so nothing guarantees a retry exactly on that schedule.
  • default_destination_concurrency_limit is per destination, not a server-wide delivery cap.

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:

  • Leaky bucket. The active queue is limited so a burst cannot consume unbounded memory.
  • Fair shares. When active space is free, qmgr alternates between incoming and deferred work, and picks destinations round-robin.
  • Exponential backoff. The retry interval doubles after each temporary failure.

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

  • Keep corrupt files. Corrupt queue files are moved to corrupt for inspection. Preserve them and the related log entries until you understand the failure.
  • Look local before global. If only one remote destination is failing, inspect its response and the transport-specific settings before changing global qmgr limits.

Done means

  • Know the install. You can name the Postfix version, queue directory and configuration directory.
  • Spool untouched. You checked queue state and qmgr defaults without editing spool files.
  • Old value recorded. You wrote down the previous value before making one configuration change.
  • Reloaded and verified. You reloaded Postfix after editing main.cf and confirmed the setting.
  • Rollback ready. You have a tested rollback command and are watching the logs for the destination's response.