Queue Management
PostMTA uses multiple internal queues to manage message delivery lifecycle. Each queue type has distinct retry, suspension, and dampening behaviour. Understanding queues is essential for tuning delivery performance and responding to delivery issues.
Queue Types
Scheduled Queue
Messages scheduled for future delivery are held in the scheduled queue. Messages are sorted by their send_at timestamp and released to the delivery pipeline when their window opens. Scheduled messages can be cancelled before release by calling the void endpoint.
- Retention: up to 72 hours in the scheduled queue
- After 72 hours, a scheduled message expires and the HOLD is VOIDed
- Priority: earliest
send_atfirst
Deferred Queue
Messages that receive a soft reject (4xx) from a recipient MTA are moved to the deferred queue. They are retried according to the soft retry schedule. Deferred messages do not count against the sending domain's live reputation until they are retried.
- Retention: up to 72 hours across all retry attempts
- Messages that exceed max retries are moved to the bounce queue
- Priority: messages with fewest retry attempts first
Bounce Queue
Messages that have exhausted all delivery attempts are placed in the bounce queue. Bounce events are recorded, suppression list entries are created, and webhook notifications are dispatched. Bounce queue entries are retained for 30 days for audit purposes.
- Hard bounces: immediately suppress the recipient
- Soft bounces: enter the retry schedule; moved to bounce queue only after all retries fail
- FBL (Feedback Loop) complaints: immediately suppress and tag the campaign
Suspend Queue
When a workspace, sending domain, or IP exceeds its bounce rate threshold, PostMTA automatically moves it to the suspend queue. Sending is halted until the operator investigates and manually reinstates the suspended entity.
- Suspended entities: no new messages are accepted from the API
- In-flight messages: completed or retried normally; no new injections
- Auto-reinstatement: not automatic; requires operator action
Bounce Classification
PostMTA classifies every failed delivery attempt into one of three categories. Classification determines whether the recipient is suppressed and whether the sending domain or IP is subjected to shaping or suspension.
Hard Bounce (5xx)
A hard bounce indicates a permanent delivery failure. The recipient address is invalid, the domain does not exist, the mailbox is full and rejects all mail, or the server has explicitly refused delivery.
550 5.1.1 User unknown
550 5.2.1 Mailbox full
550 5.7.1 Message rejected due to policyHard bounce actions:
- Recipient immediately added to suppression list (hard bounce entry)
- Message moved to bounce queue
- Bounce counter incremented for the sending domain
- Bounce rate recalculated
Soft Bounce (4xx)
A soft bounce indicates a temporary failure. The server is temporarily unavailable, the connection was refused due to load, or the message was too large for the recipient's server policy.
450 4.1.0 Unknown error
451 4.2.0 Mailbox temporarily unavailable
452 4.3.1 System storage fullSoft bounce actions:
- Message moved to deferred queue for retry
- Retry counter incremented
- No suppression applied until all retries are exhausted
FBL — Feedback Loop Complaint
FBL complaints are generated when a recipient clicks "Mark as Spam" in their email client and the recipient's email provider reports this back via an FBL mechanism (ARF format or via postmaster tools).
- Recipient immediately added to suppression list (complaint entry)
- Campaign tagged with complaint flag
- Complaint rate counter incremented
- If complaint rate exceeds 0.1% in any 24-hour window, domain shaping is applied
Soft Retry Schedule
When a message receives a soft bounce (4xx), PostMTA retries according to this schedule. After the final retry is exhausted, the message is moved to the bounce queue and classified as a hard bounce.
| Retry | Delay After Previous Attempt | Cumulative Time |
|---|---|---|
| Attempt 1 | Immediate (first attempt) | 0 min |
| Attempt 2 | 15 minutes | 15 min |
| Attempt 3 | 30 minutes | 45 min |
| Attempt 4 | 2 hours | 2 hr 45 min |
| Attempt 5 | 4 hours | 6 hr 45 min |
| Attempt 6 | 8 hours | 14 hr 45 min |
| Attempt 7 | 12 hours | 26 hr 45 min |
| Attempt 8 (final) | 24 hours | 50 hr 45 min |
Suspend Behaviour
PostMTA monitors the bounce rate for every sending domain and IP pool continuously. If the bounce rate exceeds a threshold, the affected entity is automatically moved to the suspend queue.
Auto-Suspend Thresholds
| Metric | Warning Threshold | Suspend Threshold | Window |
|---|---|---|---|
| Hard bounce rate | 1.5% | 3.0% | Rolling 24-hour window |
| Total bounce rate | 2.0% | 5.0% | Rolling 24-hour window |
| Complaint rate | 0.05% | 0.1% | Rolling 24-hour window |
Suspension Notification
When an entity is suspended, PostMTA:
- Sends a webhook
entity.suspendedevent - Sends an email to all workspace Owners
- Creates an audit log entry
- Halts acceptance of new messages for the suspended entity
Reinstatement
To reinstate a suspended sending domain or IP pool:
curl -X POST https://api.postmta.com/v1/panel/queues/reinstate \
-H "Authorization: Bearer pmta_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"entity_type": "sending_domain",
"entity_id": "mail.example.com",
"reason": "Bounce rate normalised after list cleanup. Reviewed suppression list and removed 847 hard bounces."
}'After reinstatement, the entity is moved back to epoch_0 (cold start) and must complete the warmup ladder again from day 1.
Queue Metrics API
Retrieve current queue depth and delivery metrics:
curl https://api.postmta.com/v1/panel/queues \
-H "Authorization: Bearer pmta_live_xxxxxxxxxxxxxxxx"Response:
{
"workspace_id": "ws_01HXABC123DEF456",
"queues": {
"scheduled": {
"depth": 1247,
"oldest_message_age_seconds": 3840,
"messages_per_minute_in": 34
},
"deferred": {
"depth": 583,
"oldest_message_age_seconds": 720,
"messages_per_minute_in": 12,
"retries_pending": 583
},
"bounce": {
"depth": 92,
"hard_bounces_24h": 61,
"soft_bounces_24h": 31
},
"suspend": {
"depth": 0,
"suspended_entities": 0
}
},
"bounce_rate_24h": 0.8,
"complaint_rate_24h": 0.02,
"delivered_24h": 149823,
"sent_24h": 151047
}Dampening Controls
Dampening controls allow an operator to manually reduce the injection rate for a workspace, domain, or IP without changing its epoch. This is useful during an incident investigation or when a downstream problem is anticipated (e.g., known maintenance window at a major ISP).
Dampening Factor
A dampening factor of 0.5 halves the effective daily sending rate. A factor of 0.1 allows only 10% of the normal rate. A factor of 1.0 disables dampening.
curl -X PUT https://api.postmta.com/v1/panel/queues/dampen \
-H "Authorization: Bearer pmta_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"entity_type": "workspace",
"entity_id": "ws_01HXABC123DEF456",
"dampening_factor": 0.25,
"reason": "Investigating elevated bounce rate — reducing volume while root cause is identified",
"expires_at": "2026-07-18T18:00:00Z"
}'Dampening Overrides
Dampening can be applied at three levels. More specific levels take precedence:
| Level | Entity Type | Precedence |
|---|---|---|
| IP address | 198.51.100.42 | Highest (most specific) |
| Sending domain | mail.example.com | Medium |
| Workspace | ws_01HXABC123DEF456 | Lowest |
Draining a Queue
To manually drain all messages from a specific queue (e.g., the deferred queue before a large sending domain migration):
curl -X POST https://api.postmta.com/v1/panel/queues/drain \
-H "Authorization: Bearer pmta_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"queue_type": "deferred",
"action": "void",
"reason": "Domain migration — voiding deferred messages; senders should resubmit"
}'Supported action values: void (credits returned), retry (immediate retry), move_to_bounce (force bounce classification).