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.
What Postfix already does with deferred mail
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.
Reading the reason in a status=deferred line
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_lifetimeConnection 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.
When a flush actually helps
- 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.
When waiting is the safer choice
| Reason in the log | Likely cause | Usual action |
|---|---|---|
| Timeouts or refused, across many domains | Local network or firewall | Fix, verify, then flush |
| DNS, relayhost auth, or disk errors | Local configuration | Fix, verify, then flush |
| Timeouts or refused, one domain only | Destination down or blocking | Wait, or flush once it's confirmed reachable |
| 421, 451, or 4.7.x from one provider | Remote rate limit or reputation | Wait and let backoff work |
| Greylisting notice | Remote policy, expected | Wait |
A middle ground: targeted retries
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.