Postfix is a modular, queue-based MTA where mail flow depends on a chain of cooperating daemons, filesystem-backed queues, DNS resolution, and external filters. Monitoring maturity is not about collecting more metrics for their own sake. It is about closing the gap between what you can detect and what actually causes incidents: inode exhaustion hiding behind “No space left on device,” active queue saturation from one slow destination, silent filter backpressure, or deferred queues that grow for hours before anyone notices.
This four-level progression maps survival checks to expert-grade observability. Identify your current level, then target the signals at the next level that close your biggest blind spots. The model reflects incident patterns where teams had monitoring in place but still missed the signal that mattered. The gap was rarely “no monitoring” – it was monitoring the wrong layer, or collecting a metric without alerting on its rate of change.
flowchart TD
L4["Level 4: Expert
Latency distributions, per-transport
throughput, reputation checks"]
L3["Level 3: Mature
Per-destination metrics, filter health,
queue breakdown, pattern detection"]
L2["Level 2: Operational
Flow rates, bounce rate, TLS,
security signals, inode monitoring"]
L1["Level 1: Survival
Master alive, ports listening,
queue not growing, disk not full"]
L1 --> L2 --> L3 --> L4Level 1: Survival
Survival monitoring answers one question: is Postfix running and can it accept mail? If any of these checks fail, you have a complete outage. These are the signals your paging system must cover before anything else.
| Signal | Why it matters | What to check |
|---|---|---|
| Master process liveness | No master means no mail reception or delivery. Complete outage. | PID file at /var/spool/postfix/pid/master.pid exists and references a running process named master. |
| SMTP listener responsive | Socket present but no greeting means master issue or all smtpd processes busy. | TCP connect to port 25, expect a 220 greeting with your hostname within 2 seconds. |
| Total queue not growing | Unbounded queue growth is the earliest indicator of delivery failure. | Count files across all queue subdirectories. Compare against a rolling baseline. |
| Queue partition has space | Disk full halts all mail I/O immediately. | df -h /var/spool/postfix below your alert threshold (typically 90%). |
Master PID file check. The PID file must exist and point to a running process. A stale PID file after an unclean shutdown is a common false positive. Compare the PID file mtime against the process start time to detect this. In containers, PID namespace confusion can cause the PID file to reference PID 1 or the wrong namespace entry.
Greeting test. A TCP socket that accepts connections but never sends a 220 banner means the smtpd pool is exhausted or the master process is stuck. Test the full path, not just the port bind. If postscreen is enabled, it answers on port 25 and passes to smtpd internally, so test both the postscreen path and the backend smtpd path.
Queue size as a survival signal. At this level you do not need per-queue breakdowns. You need to know whether the total file count is trending up. A static threshold (for example, “page if total queue exceeds 50,000”) is sufficient for survival. Velocity-based alerting comes at Level 2.
Disk space only. Level 1 tracks disk space, not inodes. This is a known blind spot. Most teams at this level have been surprised by “No space left on device” when df -h shows 40% free. Inode monitoring arrives at Level 2, but if you take one thing from this article before finishing, add df -i to your survival checks today.
Level 2: Operational
Operational monitoring adds early warning. You can detect degradation before it becomes an outage. The focus shifts from “is it running?” to “is it draining?”.
| Signal | Why it matters | What to check |
|---|---|---|
| Injection vs delivery rate | Persistent injection exceeding delivery causes queue growth. | Parse logs for client= (injection) and status=sent (delivery) over 5-minute windows. Ratio should be near 1:1. |
| Deferred rate | High deferred ratio indicates destination problems or policy rejections. | Count status=deferred lines. Healthy systems run below 5% of injection. Above 20% warrants investigation. |
| Active queue vs limit | Active queue at qmgr_message_active_limit means the queue manager cannot schedule new deliveries. | Compare active queue file count against postconf -h qmgr_message_active_limit (default 20,000). |
| Deferred queue growth rate | Velocity matters more than absolute size. A static 5,000 that is shrinking is fine. The same 5,000 growing at 1,000/hour is not. | Track the derivative of deferred queue file count over time. Any sustained positive growth over 4 hours is abnormal. |
| Bounce rate | High bounce rates damage IP reputation and indicate data quality or routing problems. | Count status=bounced lines. Above 1% sustained for transactional mail warrants a ticket. Above 5% is critical. |
| Inode utilization | Postfix creates one file per queued message plus metadata. Inodes exhaust before disk space. | df -i /var/spool/postfix. Alert below 10,000 free inodes or above 90% usage. |
| File descriptor count | Each connection and queued message consumes an fd. Exhaustion halts new connections. | Sum open fds across Postfix processes. Compare against ulimit -n. Alert above 80% of soft limit. |
| SMTPD process utilization | Services at maxproc cause “to limit” log messages and connection delays. | Check for to limit in logs. Monitor smtpd process count against maxproc in master.cf. |
| TLS certificate expiration | Expired certificates cause mandatory TLS destinations to defer silently. | Monitor both inbound (smtpd) and outbound (smtp) certificate expiry dates. Do not forget client certificates for mutual TLS. |
| Authentication failure rate | Brute force against submission ports (587, 465). | Count SASL authentication failed lines. Baseline is very low. Above 100/minute from a single IP is active attack. |
| Relay denial rate | Confirms smtpd_recipient_restrictions are blocking unauthorized relay attempts. | Count relay access denied lines. Any successful unauthorized relay is a security incident. |
The deferred growth trap. Teams at this level often set a static threshold (“page if deferred exceeds 10,000”) and miss the transition from linear to exponential growth. Once throughput saturates, retried messages compound new arrivals. Track the rate of change, not just the absolute count. A deferred queue growing at 1,000 messages/hour with no plateau is a page, regardless of total size.
Inodes, not just bytes. This is the single most common gap at every level. Postfix stores each queued message as an individual file with associated metadata. A deferred queue with hundreds of thousands of messages can exhaust inodes while df -h shows ample free space. The error message “No space left on device” is technically correct but deeply misleading. XFS dynamically allocates inodes and is less susceptible, but ext4 with default inode density is vulnerable on /var partitions.
File descriptors in production. The default soft limit (often 1024) is inadequate for production mail servers. Each smtpd process, each queued message being processed, and each network connection consumes file descriptors. Monitor the sum across all Postfix processes and compare against the configured limit. Production servers commonly need 65,536 or higher.
Level 3: Mature
Mature monitoring moves from individual metrics to correlation. You can identify which destination is causing queue gridlock, which filter is creating backpressure, and which composite failure pattern is unfolding.
| Signal | Why it matters | What to check |
|---|---|---|
| Per-destination delivery metrics | One slow destination can monopolize active queue slots via fair queueing. Identifying the destination is the first step to resolution. | Parse deferred logs grouped by recipient domain. Look for one or few domains dominating. |
| Content filter / Milter health | Filter slowdown causes queue backup long before process failure. | Monitor filter response time. Baseline is typically under 1 second. Alert at p99 above 5 seconds. |
| Queue subsystem breakdown | Knowing which queue is growing (maildrop vs incoming vs active vs deferred) narrows the problem immediately. | Track file counts per queue subdirectory independently. |
| Anvil connection state | Rapid connection table growth indicates dictionary attack or connection pool abuse. | Parse connect from lines, group by client IP. NAT/proxy environments appear as a single client. |
| Relay recipient map latency | Slow recipient verification causes smtpd to hang before queueing. | time postmap -q test@example.com hash:/etc/postfix/relay_recipients. Network-backed maps should be under 500ms. |
| Composite pattern detection | Individual metrics within thresholds can still form a known failure pattern. | Correlate active queue saturation with per-destination deferred rates and filter response times. |
Queue gridlock pattern. Active queue near qmgr_message_active_limit with deferred growing steadily, CPU and network low, and one destination dominating deferred entries with “connection timed out” or rate-limit 4xx responses. The queue manager is working as designed, but fair queueing without priority means one slow destination stalls everything. Detecting this pattern requires correlating active queue depth, deferred growth rate, and per-destination breakdown. No single metric tells the whole story.
Filter backpressure pattern. Incoming queue growing while active queue remains small. This is the reverse of normal gridlock and is easy to miss if you only monitor deferred. The filter is accepting mail (incoming grows) but not completing processing (active stays empty because cleanup cannot finish). SMTP clients may time out and retry, amplifying load. The tell is incoming queue growth with healthy active queue depth.
Postscreen and anvil. If postscreen is enabled, its statistics reveal how effectively zombies are being blocked before reaching smtpd. Anvil tracks per-client connection counts and rates in memory. Both are cleared on restart, so there is a brief window after restart where rate limits reset. In NAT or proxy environments, all clients appear as the same IP address, which can trigger false connection count limits.
Level 4: Expert
Expert monitoring adds distributions, per-transport granularity, and external reputation signals. The focus shifts from detecting problems to predicting them.
| Signal | Why it matters | What to check |
|---|---|---|
| Message age distribution | Average queue age hides long tails. A distribution reveals whether most mail flows quickly with a stuck minority, or whether the entire queue is aging. | Analyze mtime of files in deferred and active directories. Bucket by age ranges. |
| Per-transport throughput | smtp, local, virtual, and pipe transports have different bottlenecks. Aggregate throughput hides per-transport saturation. | Parse delivery logs grouped by transport. Compare throughput against configured concurrency limits per transport. |
| DNS latency distribution | DNS is Postfix’s most critical external dependency. Latency distribution, not just failure rate, reveals resolver degradation before it causes deferrals. | Postfix does not export resolver timing directly. Instrument the system resolver (unbound, systemd-resolved) or parse delay= fields from postfix/smtp log entries. |
| Postqueue responsiveness | Slow postqueue -p response indicates queue manager under pressure. | Time postqueue -p execution. Normal is under 5 seconds. Above 10 seconds indicates qmgr stress. |
| Predictive queue growth | Time-to-full estimation based on current growth rate and remaining capacity. | Calculate runway: free inodes divided by growth rate (files/hour). Alert when runway drops below a threshold. |
| Reputation / blocklist checks | Blocklistings appear within hours of sustained high bounce rates. Proactive checks catch listings before users report them. | Query major DNSBLs programmatically for your sending IP(s). Monitor sender score externally. |
Message age vs message count. A deferred queue with 5,000 messages where the oldest is 10 minutes old is a transient blip. The same 5,000 messages where the oldest is 6 hours old is a delivery crisis. Count alone is insufficient. The distribution of message ages reveals whether retries are succeeding for recent messages while old messages are stuck, or whether the entire queue is aging uniformly.
Reputation as a monitoring signal. Most teams discover blocklistings when external parties report them. By then, deliverability is already damaged. Querying DNSBLs programmatically (Spamhaus, Barracuda) for your sending IPs provides early detection. Correlate with bounce rate trends: sustained bounce rates above 2% precede most blocklist appearances.
Multi-instance contention. If you run multiple Postfix instances (inbound vs outbound, per-customer, submission vs receiving), aggregate metrics hide resource starvation. One instance can exhaust file descriptors or disk I/O while others appear healthy. Per-instance resource accounting is essential at this level.
How to use this model
Assess your current state honestly. Most teams operate at Level 1 with some Level 2 signals. The gap between “we collect it” and “we alert on it” is where most incidents live. A metric you collect but never page on might as well not exist.
Pick one blind spot to close. Do not attempt to jump from Level 1 to Level 4. Pick the single most impactful signal at the next level and implement alerting for it. For most teams, that is deferred queue growth rate (velocity, not absolute size) or inode utilization.
Calibrate thresholds to your workload. The thresholds in this article are starting points. A backup MX legitimately maintains large deferred queues. A marketing sender has higher bounce baselines than a transactional sender. Establish baselines during stable operation, then set thresholds relative to those baselines.
Test recovery procedures, not just detection. Monitoring tells you something is wrong. Knowing which lever to pull (reduce destination concurrency, bypass a failed filter, hold a problem destination’s mail) is a separate skill. Document playbook steps before you need them at 3 a.m.
What teams consistently get wrong
- Inode blind spot. Almost every major Postfix queue-growth incident eventually hits inode exhaustion. Teams monitor disk space, not inodes. Add
df -itoday. - Static thresholds on dynamic queues. A deferred queue of 5,000 that is growing is more urgent than 20,000 that is draining. Track velocity.
- DNS as unmonitored dependency. Postfix depends entirely on DNS. Resolver failure looks like “slow mail to everyone.” Monitor resolver latency and failure rate independently.
- Filter health measured as process liveness. “Is Amavis running” is the wrong question. “Is Amavis responding in under 2 seconds” is the right one. Slow filters cause queue backup before they crash.
- Bounce rate blindness. Bounces count as “sent” in simple delivery metrics. Explicit bounce rate monitoring is required separately.
- Ignoring maildrop queue. Local submission failures (cron, monitoring scripts) are invisible in SMTP logs. Pickup daemon failure manifests as missing local mail.
How Netdata helps
Netdata’s per-second collection and anomaly detection shorten the path from symptom to root cause for Postfix incidents.
- Disk and inode metrics at per-second resolution catch the inode exhaustion cliff before it halts mail delivery. Correlating inode usage with queue file count confirms whether growth is Postfix-driven.
- Process and file descriptor metrics reveal smtpd pool exhaustion, fd pressure, and process spawn anomalies before they cause connection failures.
- System-level DNS latency and resolver health provide the independent DNS visibility that Postfix itself cannot surface.
- ML-based anomaly detection on queue-related filesystem activity (file creation rate, directory growth) flags unusual patterns without requiring static thresholds that miss workload-specific baselines.
- Correlation across system, disk, network, and process metrics in a single timeline makes it faster to distinguish between a Postfix-internal problem (active queue saturation) and an external dependency failure (DNS, filter, destination reachability).
Related guides
- Postfix monitoring checklist: the signals every production mail server needs
- How Postfix actually works in production: a mental model for operators
- Postfix master process not running: the whole MTA is down
- Postfix not listening on port 25 or 587: connection refused
- postfix check warnings: configuration drift and permission problems
- Postfix mail flow: injection rate outpacing delivery rate
- Postfix active queue saturation: hitting qmgr_message_active_limit
- Postfix maildrop queue growing: pickup daemon and local submission failures
- Postfix queue message age: the delivery latency queue depth cannot show
- Postfix deferred queue growing: why mail piles up and how to drain it
- Postfix flushing and clearing the deferred queue: postqueue and postsuper
- Postfix Connection timed out: delivery deferrals to unreachable destinations






