Bali, Indonesia
Insights

Should You Run postqueue -f or Let Postfix Retry Deferred Mail on Its Own?

October 21, 2026
0:00
Mail is piling up in the Postfix queue, someone says their messages haven't arrived, and the first reflex is to run postqueue -f. Sometimes that clears everything in seconds. Other times the queue looks the same afterwards. Or the deferrals get worse, going from occasional to constant for one big mailbox provider. Which outcome you get depends on why the mail was deferred, and Postfix records that reason in every status=deferred log line. So the real question is not flush or don't flush. It's whether the thing that caused the deferral has changed since the last attempt. If it hasn't, a flush means asking the same question again, louder.
A deferred message is one that got a temporary failure: a 4xx SMTP reply, a timeout, a refused connection, a DNS lookup that didn't resolve. Postfix doesn't give up on these. It moves them to the deferred queue and retries on a backoff schedule. The wait between attempts grows after each failure, between a minimum and a maximum. A separate timer controls how often the queue manager scans the deferred queue at all. If a message is still undeliverable when it reaches the maximum queue lifetime, Postfix bounces it back to the sender. The parameters that control this are minimal_backoff_time, maximal_backoff_time, queue_run_delay, and maximal_queue_lifetime. On Postfix 2.4 and later the defaults are usually 300 seconds, 4000 seconds, 300 seconds, and 5 days. Packagers and earlier admins sometimes change them, so check your own values rather than trusting a blog post. The command is in the block further down. Postfix also tracks the health of each destination, not just each message. When a receiving server keeps failing or pushing back, Postfix lowers how many parallel connections it opens to that destination. If things get bad enough, it may treat the destination as temporarily dead and defer new mail for it without trying. Those lines often contain delivery temporarily suspended. This is deliberate. It's Postfix being polite to a server that has said it's overloaded or doesn't want more traffic right now. postqueue -f overrides all of that. It tells Postfix to attempt delivery of everything in the queue now, ignoring where each message sits in its backoff schedule. That's useful when the backoff is protecting you from a problem that no longer exists. It's counterproductive when the backoff is the only thing keeping you under someone else's limit.
Each delivery attempt logs a line with the queue ID, the recipient, the relay Postfix tried, a dsn= code, and the status. For deferred mail, the useful part is the text in parentheses at the end. That's either the remote server's reply or Postfix's description of what went wrong locally. Read the dsn= code too. It's the enhanced status code. Anything starting with 4 is temporary, and 5 is permanent. Permanent failures show up as status=bounced and won't be retried at all, so flushing does nothing for them. With a big queue, reading 50 lines by eye is slow. Grouping the reasons and the relays shows the pattern quickly. The commands below are read-only. Adjust the log path for your distro: Debian and Ubuntu usually use /var/log/mail.log, RHEL-family systems usually use /var/log/maillog, and some minimal installs only log to journald.
BASH
# Most common deferral reasons (text inside the final parentheses)
grep 'status=deferred' /var/log/mail.log | sed -E 's/.*status=deferred \((.*)\)$/\1/' | sort | uniq -c | sort -rn | head -20

# Which relays the deferred mail was trying to reach
grep 'status=deferred' /var/log/mail.log | grep -o 'relay=[^,]*' | sort | uniq -c | sort -rn | head -20

# Current retry and lifetime settings on this server
postconf minimal_backoff_time maximal_backoff_time queue_run_delay maximal_queue_lifetime
The reasons usually fall into a few groups. The first group is network failures, like Connection timed out or Connection refused. Either something between you and the destination is blocking port 25, or the destination is down. The test that matters is whether it happens for every destination or only one. The second group is remote pushback, like 421 Too many connections, 451 4.3.2 Temporary local problem, or 4.7.x replies about rate or reputation. The receiving server is up and talking to you, and it's telling you to slow down or come back later. The third group is local problems: DNS lookups failing, a relayhost rejecting your credentials, a full disk, a broken transport map. These are your server's fault, and they tend to hit many destinations at once. The relay breakdown helps separate them. If deferrals are spread across hundreds of unrelated domains, the problem is probably on your side. If they're concentrated on one provider, that provider is usually the one pushing back. For a closer look at that pattern with Gmail specifically, see Why Exim Logs Gmail 421 Rate Limit Deferrals for cPanel Domains. The MTA in that article is different, but the receiving side behaves the same way.
A full flush makes sense when the cause was local, you've fixed it, and you've confirmed the fix. Common examples:
  • The server's resolver was broken and you repaired it.
  • A firewall rule blocked outbound port 25 and you removed it.
  • The relayhost password expired and you updated it.
  • The disk filled up and you freed space.
In each case, every queued message failed for a reason that no longer applies. Without a flush, some of them would sit for up to the maximum backoff time before their next attempt. Speeding that up costs nothing. The same logic applies when one destination was clearly down and is clearly back, for example a partner's mail server that you can now reach on port 25. Test the fix before flushing. Send one message or watch one retry succeed in the log. Flushing a few thousand messages to confirm a fix you haven't verified just produces a few thousand new deferral lines to dig through.
If the parentheses contain a 421 or 451 from a remote server, a rate-limit message, or a greylisting notice, the receiver is in control. Retrying everything immediately opens a burst of new connections to a server that just said it's getting too many. That burst doesn't make the server more willing to accept mail, and it can keep you over its limit for longer. With the backoff schedule left alone, Postfix spreads retries out and lowers concurrency to that destination on its own. This is the slower path, and it's also the one most likely to drain the queue without new rejections. This is also where support conversations get confusing. A customer sees mail sitting in the queue and assumes the server is broken or the IP is blacklisted. Often neither is true. The receiving side is metering traffic, and the server is responding correctly. Why Outbound Emails Queue Up When Your IP Is Not Blacklisted covers that misconception in more detail. Explaining that the mail is scheduled for retry, not lost, usually helps more than any command. If the same provider keeps throttling you day after day, waiting isn't a fix either. That points to sending volume, list quality, or authentication. It might also call for slowing delivery to that provider on purpose with per-destination concurrency and rate-delay settings. That's a configuration change to plan, not something to fix by flushing.
Reason in the logLikely causeUsual action
Timeouts or refused, across many domainsLocal network or firewallFix, verify, then flush
DNS, relayhost auth, or disk errorsLocal configurationFix, verify, then flush
Timeouts or refused, one domain onlyDestination down or blockingWait, or flush once it's confirmed reachable
421, 451, or 4.7.x from one providerRemote rate limit or reputationWait and let backoff work
Greylisting noticeRemote policy, expectedWait
You don't have to choose between retrying everything and doing nothing. postqueue -p lists the queue with queue IDs and the last deferral reason. On newer Postfix releases, postqueue -i followed by a queue ID retries a single message. That's useful when one urgent message is stuck behind a now-fixed problem, or when you want to test a fix with one message before releasing the rest. Check your version's man page, because older releases don't have this option. postqueue -s with a domain name is often suggested as a per-domain flush, but it has a narrower purpose. It's the server side of the SMTP ETRN command, and it only works for destinations listed in fast_flush_domains. By default that follows relay_domains. It isn't a general way to retry outbound mail to an arbitrary domain like a large mailbox provider. If you want to see how the queue breaks down by destination and message age, the qshape tool that comes with Postfix gives a compact view. Depending on the distro, it may be packaged separately. The habit worth building is simple. Before touching the queue, read the parentheses and group the deferrals by reason and relay. If the cause was yours and it's fixed, flush. If the cause belongs to the receiving server, leave the schedule alone, keep an eye on whether the queue is shrinking, and save the configuration work for providers that throttle you every day.