Read Postfix Queue Age and Domain Pressure with qshape
You will finish with a repeatable way to see how old Postfix queue messages are and which sender or recipient domains account for them. The examples use qshape from Postfix 3.8.6, installed here as package version 3.8.6-1ubuntu0.1. Allow about fifteen minutes. You need a shell, a Postfix queue, and either root access or permission to run as Postfix's configured mail_owner.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Check the installed command
Start with read-only checks. They do not alter the queue or Postfix configuration:
$ command -v qshape
/usr/sbin/qshape
$ dpkg-query -W -f='${Package} ${Version}\n' postfix
postfix 3.8.6-1ubuntu0.1
$ qshape -h
Usage: /usr/sbin/qshape [ -s ] [ -p ] [ -m <min_subdomains> ] [ -l ]
[ -b <bucket_count> ] [ -t <bucket_time> ] [ -w <terminal_width> ]
[ -N <batch_msg_count> ] [ -n <batch_top_domains> ]
[ -c <config_directory> ] [ <queue_name> ... ]
The default report combines the incoming and active queues. It reports recipient domains, because one message can have several recipients. That makes the default useful for spotting recipient-side concentration, but it is not a count of messages per domain.
2. Run the smallest useful report
qshape must read queue directories and queue files. Run it as root or as the mail_owner from main.cf; on a standard installation that owner is often postfix. This is an operational read, not a queue-management action, but elevated access exposes mail metadata, so use the least-privileged permitted account:
$ sudo -u postfix qshape
T 5 10 20 40 80 160 320 640 1280 1280+
TOTAL 0 0 0 0 0 0 0 0 0 0 0
Your totals and domain rows will differ. The first column is the domain or summary name. The age columns are in minutes: the first bucket covers messages from 0 up to 5 minutes old, then the geometric intervals continue as 5-10, 10-20 and so on. The final bucket has no upper age limit. A quiet queue can therefore produce only a TOTAL row.
Checkpoint: if you see Can't cd to incoming: Permission denied or the equivalent for active, the command did not have enough queue access. Do not interpret the resulting zero totals as proof that the queue is empty. Rerun with the configured mail_owner or appropriate root privilege.
3. Choose a shorter or more detailed age view
The default uses a first bucket of five minutes and a geometrically doubling sequence. Adjust both the number of buckets and their starting size when a report needs to fit on screen or cover a particular incident:
$ sudo -u postfix qshape -b 6 -t 15
T 15 30 60 120 240 480 480+
TOTAL 0 0 0 0 0 0 0
-b 6 requests six buckets and -t 15 makes the first interval 15 minutes. With the default geometric mode, later limits double. The exact spacing in the header is adjusted to the terminal width.
Use -l for a linear sequence instead. With the same values, the intervals are based on multiples of 15 minutes rather than doubling. This is useful when each elapsed period has the same operational meaning:
$ sudo -u postfix qshape -l -b 6 -t 15
T 15 30 45 60 75 90+
TOTAL 0 0 0 0 0 0 0
Do not compare a geometric report with a linear report as if their columns represented the same ranges. Write the bucket settings into an incident note or script so later snapshots remain comparable.
4. Switch between recipient and sender pressure
Use -s for sender-domain distribution:
$ sudo -u postfix qshape -s
T 5 10 20 40 80 160 320 640 1280 1280+
TOTAL 0 0 0 0 0 0 0 0 0 0 0
The sender view is a message distribution because each message has one sender. The default recipient view can have more domain entries than messages when a message has multiple recipients. If you are asking 'which sender is producing queued mail?', start with -s. If you are asking 'where is delivery backing up?', start with the default recipient report.
For a busy installation, intermediate output can be useful while the deferred queue is being scanned. -N controls how many messages are processed between intermediate results, and -n limits the number of top domains shown in those terminal reports:
$ sudo -u postfix qshape -N 500 -n 10
T 5 10 20 40 80 160 320 640 1280 1280+
TOTAL 0 0 0 0 0 0 0 0 0 0 0
These options change reporting cadence and display, not queue contents. The default intermediate batch is 1000 messages and the default terminal top-domain limit is 20.
5. Aggregate parent domains carefully
Many separately named customer or sender domains can hide a common parent. Use -p to request parent-domain rows. Parent names have a leading dot, and top-level domains are omitted:
$ sudo -u postfix qshape -p -m 3
T 5 10 20 40 80 160 320 640 1280 1280+
TOTAL 0 0 0 0 0 0 0 0 0 0 0
Here -m 3 lowers the minimum number of subdomains needed before a parent gets its own line. The default is 5. A parent row is an aggregate view; it is not an additional queue entry. Compare it with the individual-domain report before blaming a parent organisation or changing delivery policy.
6. Inspect a specific queue or Postfix instance
Pass queue directory names after the options when the default pair is not the question you need to answer. Relative names are interpreted below Postfix's queue_directory; absolute paths are used as supplied:
$ sudo -u postfix qshape deferred
$ sudo -u postfix qshape incoming active deferred
The first command isolates postponed delivery. The second includes three named queues. The command does not expand variables used inside the queue_directory setting, so a setup that defines that parameter with a $variable needs explicit absolute queue paths instead.
For a non-default Postfix instance, select the directory containing its main.cf:
$ sudo -u postfix qshape -c /etc/postfix-instance
Check the directory before running the scan:
$ test -r /etc/postfix-instance/main.cf && echo 'main.cf is readable'
main.cf is readable
7. Keep the investigation non-destructive
qshape only reports what it finds. Do not add postsuper, postsuper -d, postqueue -f or service restarts to a copied diagnostic command. Deleting queued mail is irreversible, and forcing delivery can change the evidence while the incident is being measured. If you redirect a report to a file, choose a new path or use a shell-safe temporary file so an existing investigation is not truncated:
$ report="/tmp/qshape-$(date +%Y%m%d-%H%M%S).txt"
$ sudo -u postfix qshape -s > "$report"
$ sed -n '1,12p' "$report"
This creates a report under /tmp; it does not change Postfix state. Remove the report only when its contents are no longer needed and your local retention rules allow it.
Done means
- You confirmed the installed Postfix and
qshapeversions. - You ran the report with root or the configured
mail_owner, and did not mistake permission errors for an empty queue. - You recorded whether the report used recipient or sender domains.
- You recorded the bucket count, first bucket time and geometric or linear mode.
- You used
-ponly when an aggregate parent-domain view answered the question. - No queued message, Postfix configuration file or service state was changed.