Chapters

10 AMQP Delivery: Sizing and Reliability Contracts

amqp
arch
messages
delivery
reliability
dlq

Start with the story: An AMQP message is a parcel with a label, a body, and a delivery receipt path. The chapter is about choosing when that parcel may be dropped, retried, acknowledged, or parked for investigation.

10.1 Start With the Decision

This section: Start With the Decision — Five hundred machines can turn a safe message rule into a queue bottleneck.

Five hundred machines can turn a safe message rule into a queue bottleneck. Size, rate, prefetch, and failure flow must be counted.

10.2 Route Overview

This section: Route Overview — This is part 2 of 2.

This is part 2 of 2. Review AMQP Delivery: Guarantees and Acknowledgements for the preceding evidence.

10.3 Learning Objectives

This section: Learning Objectives

  • Calculate smart-factory message volume and throughput.
  • Verify an AMQP reliability chain with explicit contracts.

10.4 Chapter Roadmap

This section: Chapter Roadmap

  • Worked Example: Smart Factory Message Sizing
  • Putting Numbers to It
  • Checkpoint: Sizing the Reliability Chain
  • Knowledge Check
  • Quiz: Match Concepts to Definitions
  • Label the Diagram
  • Code Challenge
  • Order the Steps
  • Design Contract: Delivery Reliability Chain
  • AMQP Delivery Reliability Chain Contracts
  • Summary
  • What’s Next
  • Key Takeaway

10.5 Worked Example: Smart Factory Message Sizing

This section: Worked Example: Smart Factory Message Sizing — Now combine structure, guarantees, acknowledgments, and DLQ handling.

Now combine structure, guarantees, acknowledgments, and DLQ handling. Pay for reliability where the consequence justifies it.

Scenario: A pharmaceutical manufacturing plant monitors 500 machines via AMQP. Each machine publishes three types of messages with different delivery requirements:

Message TypeFrequencyPayloadDelivery Need
Temperature telemetryEvery 5 seconds120 bytes JSONOccasional loss OK
Quality alertOn threshold breach (~10/hour/machine)350 bytes JSONMust not be lost
Batch completion event~2 per hour per machine800 bytes JSONAt-least-once delivery with an idempotent audit write

Step 1: Calculate message rates and bandwidth

  • Telemetry: 500 machines x 1 msg/5s = 100 msg/s
  • Quality alerts: 500 x 10/hr = 5,000/hr = 1.39 msg/s
  • Batch events: 500 x 2/hr = 1,000/hr = 0.28 msg/s
  • Total: ~102 msg/s

Step 2: Calculate per-message AMQP overhead

For this illustrative AMQP 0-9-1 sizing model, assume these frame sizes (actual sizes depend on field values and properties):

  • Method-frame envelope: 8 bytes
  • Method-frame content (basic.publish): ~40 bytes (exchange name, routing key)
  • Content-header frame: ~60 bytes (properties: delivery_mode, content_type, timestamp, message_id, correlation_id)
  • Content-body envelope: 8 bytes + payload

Illustrative overhead per message: 8 + 40 + 60 + 8 = ~116 bytes

Step 3: Choose delivery mode for each type

TypeQoSOverhead per msgRationale
TelemetryAt-most-once120 + 116 = 236 BNext reading in 5s replaces any loss
Quality alertAt-least-once350 + 116 = 466 B + ACK (40 B)Must arrive; dedup via message_id
Batch eventTransactional publish + idempotent audit write800 + 116 = 916 B + assumed 200 B transaction costAudit write must reject duplicate event IDs

Step 4: Aggregate bandwidth

  • Telemetry: 100 msg/s x 236 B = 23,600 B/s = 189 Kbps
  • Alerts: 1.39 msg/s x 506 B = 703 B/s = 5.6 Kbps
  • Batch: 0.28 msg/s x 1,116 B = 312 B/s = 2.5 Kbps
  • Total: ~197 Kbps (well within a 1 Mbps LAN connection)

AMQP protocol overhead per message consists of multiple frame components:

OverheadAMQP=frameheader+methodframe+contentheader+bodyframe\text{Overhead}_{\text{AMQP}} = \text{frame}_{\text{header}} + \text{method}_{\text{frame}} + \text{content}_{\text{header}} + \text{body}_{\text{frame}} =8B+40B+60B+8B=116 bytes minimum= 8B + 40B + 60B + 8B = 116 \text{ bytes minimum}

Message efficiency for different payload sizes:

Efficiency=payloadpayload+overhead×100%\text{Efficiency} = \frac{\text{payload}}{\text{payload} + \text{overhead}} \times 100\%
PayloadTotal SizeEfficiency
10 B126 B7.9% (poor)
120 B236 B50.8% (moderate)
800 B916 B87.3% (good)

For telemetry with 120-byte payloads, nearly half the bandwidth is protocol overhead. Batching 10 readings into one 1,200-byte message improves efficiency from 51% to 91%, saving (10×236B)−(1,200B+116B)=1,044B(10 \times 236B) - (1,200B + 116B) = 1,044B per 10 readings (44% reduction).

10.5.1 Interactive Calculator: AMQP Message Sizing

10.5.2 Interactive Calculator: AMQP Bandwidth Requirements

Step 5: Broker memory for persistent sessions

Quality alerts and batch events use persistent delivery (delivery_mode=2):

  • Persistent messages per second: 1.39 + 0.28 = 1.67 msg/s
  • Assumed average persistent message size: ~810 bytes (weighted on-wire size: (1.39 x 506 + 0.28 x 1116) / 1.67 ≈ 608 B; allow ~810 B with the example’s broker-framing estimate).
  • If a consumer goes offline for 10 minutes: 1.67 x 600 = 1,002 messages ≈ ~810 kB queued
  • With 5 consumers, worst case: ~4 MB broker memory for queued messages

Conclusion: The telemetry (about 98% of messages) uses fire-and-forget, keeping broker load minimal. Only alerts and batch events use persistent delivery in this scenario. Adding the assumed 200-byte transaction cost to every message would raise this model’s bandwidth from ~197 to ~360 Kbps (about 1.8×); transactions alone would not provide exactly-once business processing.

This section:

Broker Bex, Messaging and broker domain expertCheckpoint: Sizing the Reliability Chain

You now know:

  • The factory example produces about 102 messages per second from 500 machines.
  • Telemetry is 98% of traffic, so at-most-once keeps the total near 197 Kbps.
  • Persistent alerts and batch events are only 2% of messages, but they drive offline broker memory.

10.6 Knowledge Check

This section: Knowledge Check — Test your understanding of message structure and delivery guarantees.

Test your understanding of message structure and delivery guarantees.

AMQP dead-letter routing narrated tour

Play silently with captions on provisional storyboard timing; narration audio is pending. Production pacing is not protocol time. Choose Reduced motion for a complete still at each beat.

Play the tour to open the workbench. Pause, replay a beat, or read the full transcript below. Some situations cannot be shown by this teaching model; those beats keep the existing frame and provide captions only.

Full transcript — AMQP dead-letter routing (8 beats)

B1 — Unreadable payload
You are the engineer keeping a factory's sensor messages moving. A decoder cannot read one message's payload, the data it carries. If that bad message keeps returning to the main queue, it can block good traffic. How do you move it aside while keeping the details needed to repair the fault?

Model caption: An unreadable sensor payload can block useful work if it keeps returning to the main queue.

B2 — Dead-letter route
Dead-lettering gives failed work another route. A queue configured with a dead-letter exchange republishes the message to that exchange. An exchange routes messages onward using a routing key. For your failed sensor message, that route separates the failure from the main flow of work.

Model caption: A configured source queue republishes failed work to a dead-letter exchange.

B3 — Failure triggers
Rejection without returning the message to the source queue can trigger dead-lettering. So can expiry of its time to live, meaning its allowed lifetime. Queue overflow is another trigger: exceeding a length limit drops the oldest message by default.

Model caption: Rejection without requeue, lifetime expiry, or length overflow can trigger the chapter's dead-letter route. Overflow drops the oldest message by default.

B4 — Routing and evidence
The dead-letter route uses a configured replacement routing key when one is set. Otherwise, it uses the original routing key. The broker adds failure details in a header called x-death. Those details include the reason, source queue and count. The count helps a retry policy decide when to stop.

Model caption: A replacement routing key is used when configured; otherwise the original key is used. The x-death header carries failure context for the retry policy.

B5 — Retry delay example
Take the chapter's decoder example. The decoder rejects the unreadable payload without requesting a return to the source queue. The dead-letter exchange routes it to a retry queue with a thirty-second lifetime. After thirty seconds, that queue dead-letters the message back to the main exchange for another attempt.

Model caption: Chapter example: rejected payload → retry queue; wait thirty seconds → main exchange for another attempt.

B6 — Parking after failures
Suppose the message reaches three failed attempts. The handler can send it to a parking queue for investigation. The original body and headers stay with it. The failure reason and source queue are preserved too. Your bad sensor message is set aside with the context needed for repair.

Model caption: After three failed attempts, the handler can park the message. Preserve its body and headers, plus the failure reason and source queue, for investigation.

B7 — Routing is not repair
The misconception is that dead-lettering repairs the failed message automatically. Moving an unreadable payload to another queue does not make the decoder able to read it. In the example, the retry policy uses the failure history to stop after three failed attempts and send the message to parking.

Model caption: Dead-lettering moves failed work. The example's retry policy stops after three failures; repair still requires investigation.

B8 — Failure route takeaway
Give failed work a route, a retry limit and a place to stop with its failure details intact.

Model caption: Give failed work a route, a retry limit and a place to stop with its failure details intact.

10.7 Design Contract: Delivery Reliability Chain

This section: Design Contract: Delivery Reliability Chain — Reliable AMQP delivery is a chain, not one setting.

Reliable AMQP delivery is a chain, not one setting. The deeper treatment now lives in AMQP Delivery Reliability Chain Contracts, covering publisher confirms, durable queues, persistent messages, manual acknowledgments, idempotent redelivery, and DLX retry/parking evidence paths.

10.8 AMQP Delivery Reliability Chain Contracts

This section: AMQP Delivery Reliability Chain Contracts — Start with the story: Reliability in AMQP is not one magic checkbox.

Start with the story: Reliability in AMQP is not one magic checkbox. It is a chain of receipts: the producer needs a broker confirm, the broker needs durable storage, the message needs persistence, and the consumer must acknowledge only after the real work is done.

10.8.1 Learning Objectives

Prove Every Link in One Alarm Chain

Picture a site unit sending a valve alarm to an incident worker. The message reaches a queue, the worker writes the incident, and then the worker crashes before it says the job is done. The next worker may see the same alarm, so the team must prevent a second incident without losing the first.

Trace one alarm from local copy to accepted store, waiting queue, worker, final record, and done signal. Name what each signal proves and what it does not. Keep one alarm id through every link so a resend or redelivery can be joined to the same physical event.

Test a failed send, a store restart, a message held only in memory, a worker crash before and after the write, a rejected item, and a full retry path. Check both loss and duplicate effects. One durable setting cannot protect a different gap in the chain.

Keep any urgent safe valve action local when delivery is late. The chain can notify and retain evidence, but it must not be the sole route to stop immediate harm.

This opening does not promise exactly-once physical action. Practitioner maps each loss window and owner. Under the Hood examines confirms, durable definitions, stored bodies, worker replies, repeated delivery, dead-letter paths, and safe replay.

After this page, you should be able to:

  • Explain why publisher confirms, queue durability, message persistence, and consumer acknowledgments protect different loss windows.
  • Diagnose which reliability link is missing from an AMQP delivery path.
  • Explain why at-least-once delivery requires idempotent consumers.
  • Identify the exact broker triggers that dead-letter a message.
  • Design a DLX retry and parking flow that preserves investigation evidence.

10.8.2 Why This Follows AMQP Message Delivery

AMQP Message Delivery teaches message structure, delivery modes, publisher confirms, consumer acknowledgments, prefetch, dead-letter queues, and delivery sizing. This page tightens the contract that connects those pieces: no single flag makes delivery reliable, and each acknowledgment only means something inside its scope.

Use it when a deployment needs a zero-loss audit, when a durable queue still loses messages after restart, when repeated deliveries must be made safe with idempotency, or when a DLQ runbook needs to distinguish retryable failures from messages that should move to parking.

10.8.3 Overview: “Reliable” Is a Chain, Not a Switch

A message survives from producer to processed only if every link in a chain holds. There is no single “reliable” flag. At-least-once delivery end to end needs four independent mechanisms lined up:

  1. Publisher confirms so the producer knows the broker actually took the message.
  2. A durable queue so the queue definition survives a broker restart.
  3. A persistent message (delivery-mode = 2) so the message body is written to disk, not just held in RAM.
  4. Consumer acknowledgements so the broker only removes a message after it has been processed, not merely delivered.

Break any one and you open a silent loss window: no confirm means the producer never learns a publish was dropped; a non-durable queue vanishes on restart; a transient message in a durable queue is still lost on restart; auto-ack deletes a message the instant it is sent, before the consumer has done anything with it.

Concrete chain example: a gateway sends a valve-state alarm and keeps its local copy until the broker sends a publisher confirm. If the broker crashes before the confirm, the gateway resends from local storage. If the broker confirms and then restarts, the durable queue and persistent message are what make the alarm still appear after recovery. If the consumer receives the alarm, writes it to an incident table, and crashes before basic.ack, the broker requeues the unacknowledged delivery on channel close. That is why the downstream incident write needs an alarm id: the next consumer may see the same delivery again, and the database should treat it as the same alarm, not a second incident.

The practical audit question is therefore always, “where can the message be acknowledged but not yet recoverable?” Publisher confirms answer the producer side, persistence answers the broker restart side, and manual acknowledgements answer the consumer side. Treating those as one chain keeps operators from over-trusting a single durable setting.

10.8.5 Under the Hood: When a Message Is Dead-Lettered

A queue configured with x-dead-letter-exchange re-publishes a message to that exchange on exactly three triggers — nothing else:

  • the consumer rejects or nacks it with requeue=false (a poison message it cannot process),
  • the message’s TTL expires (a per-message expiration or the queue’s x-message-ttl), or
  • the queue overflows a length limit (x-max-length or x-max-length-bytes), which by default drops the oldest message.

On dead-lettering, the broker routes the message to the dead-letter exchange using x-dead-letter-routing-key if set, otherwise the message’s original routing key, and prepends an x-death header recording the reason, the source queue, a count, and a timestamp. That count is what lets a retry loop give up after N attempts instead of cycling a poison message forever. A common design is: main queue -> DLX -> a “retry” queue with a short TTL that dead-letters back to the main exchange, plus a “parking” queue for messages whose x-death count has exceeded the limit.

For example, a decoder that cannot parse a payload should send basic.nack(requeue=false), not keep requeueing the same poison message at the head of the main queue. The DLX can route it to a retry queue with x-message-ttl=30000; after 30 seconds that retry queue dead-letters it back to the main exchange. When the message fails again, the next x-death entry or count tells the retry policy it has already been through the loop. After three failed attempts, the handler can route it to a parking queue with the original body, headers, failure reason, and source queue preserved for investigation. The DLQ is therefore an evidence path as much as a reliability path: it stops one bad message from blocking good traffic while keeping enough context to repair the producer or consumer.

Inspect Figure 10.1 to separate a bounded retry loop from the terminal evidence path for a poison message.

AMQP DLX retry pattern: rejected, expired, or overflowed messages leave the main queue through a dead-letter exchange; retryable messages wait in a TTL retry queue and return to the main queue, while messages over the x-death limit go to a parking queue for investigation.
Figure 10.1: A dead-letter exchange is a controlled branch: retryable failures loop through a TTL queue, while messages over the retry limit move to a parking queue with their evidence intact.
  1. Broker Bex: Bex diverts one damaged parcel-shaped message from a moving main conveyor to a side gate.

    One message fails. Bex moves it off the main line.

  2. Broker Bex: Bex clips a reason card and one tally token to the same message.

    The broker saves why it failed and adds one count.

  3. Broker Bex: A short clock-lit side conveyor pauses, then returns the same marked message to the main line.

    A retry line waits, then sends the message back.

  4. Broker Bex: The same message returns to Bex with several tally tokens while good messages keep moving.

    It fails again. The saved count reaches the limit.

  5. Broker Bex: Bex places the message and its intact cards at an investigation desk, away from the clear main belt.

    Bex parks it with its evidence. Good work can pass.

CW-0006 walkthrough: A failed message leaves the main line, waits for a bounded retry, carries its failure count, and is parked with evidence when the limit is reached.

Trace Figure 10.1 from the main queue through rejection, expiry, or overflow into the dead-letter exchange. Retryable work waits in the TTL queue and returns; excessive failures move to parking with context intact. This route turns x-death history into a retry decision instead of an infinite cycle.

10.9 Summary

This section: Summary

This chapter covered AMQP message structure and delivery guarantees:

First: Message Format: Analyzed header (durable, priority, TTL), properties (content-type, correlation-ID, message-ID), and body sections

Next: Delivery Modes: Compared at-most-once (fast, may lose), at-least-once (retried, may duplicate) and transactional publishing; an exactly-once business effect still needs application deduplication

Then: Publisher Confirms: Implemented broker acknowledgment to producers for reliable publishing

After that: Consumer Acknowledgments: Applied manual ACK/NACK with prefetch control for processing guarantees

Also inspect: Dead Letter Queues: Configured DLQ for capturing failed messages for investigation

Finally: Idempotency: Used message-ID for deduplication in at-least-once scenarios

10.10 What’s Next

This section: What’s Next

ChapterFocusWhy Read It
AMQP Frames and ReliabilitySASL authentication, TLS encryption, and AMQP 1.0 frame typesSecure and inspect the protocol layer that carries the messages you configured here
AMQP Core ArchitectureExchanges, queues, bindings, and the producer-broker-consumer modelReinforce how message routing decisions upstream affect the delivery guarantees you set
AMQP Implementations and LabsRabbitMQ broker setup, hands-on queue and DLQ configurationApply publisher confirms and DLQ patterns in a running broker environment
MQTT QoS LevelsMQTT at-most-once, at-least-once, and exactly-once equivalentsCompare AMQP delivery semantics with the constrained-device protocol used across most IoT edge devices
CoAP Fundamentals and ArchitectureRESTful CoAP reliability via CON/NON message typesContrast AMQP’s broker-mediated guarantees with CoAP’s direct endpoint reliability model
Protocol Integration PatternsBridging AMQP with MQTT, CoAP, and HTTP in IoT gatewaysSee how the delivery guarantees studied here propagate (or break) across protocol translation boundaries

10.11 Key Takeaway

This section: Key Takeaway — Reliable AMQP delivery depends on explicit acknowledgement and redelivery behavior.

Reliable AMQP delivery depends on explicit acknowledgement and redelivery behavior. Choose prefetch, acknowledgement timing, and dead-letter handling together so slow consumers do not turn into hidden message loss or unbounded backlog.

10.12 Continue Your Route

This section: Continue Your Route — This is the last part of this chapter.

This is the last part of this chapter. Return to AMQP Delivery: Guarantees and Acknowledgements or continue from the AMQP Module Guide.

Find help

3 reviewed answers.

Where should I start in a module?

Open the module page from the sidebar to see its chapters in order. Use the module map to return to a topic you need.

Modules and paths

Reviewed

What can I try when a project does not work?

Check the symptom, then work through the diagnostic steps. Keep the error message and the smallest example that reproduces it.

When you are stuck

Reviewed

How do interactive examples work?

Use the interactive guide to check how examples and simulations work before changing your project.

Interactive examples guide

Reviewed