THIS EXPLANATION
THE ROOM
CDA·259 Computing, Data & AI 6 MIN · 8 STATIONS

When responsibility transfers

A Socratic walk-through of when responsibility transfers — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

At what exact moment does a message stop being the sender's problem?

A service publishes an event and moves on. Somewhere downstream another service consumes it. Between those two sentences there is a moment when the message stopped being the first service's concern and became the second's — and almost nobody can name it.

Try to name it and the candidates multiply: when the bytes left the socket? When the broker replied? When the consumer received it? When the work finished? They cannot all be right, and picking the wrong one is how a system quietly loses work while every component reports success.

b

Reasoning it through

REASONING #

Begin by asking what "being responsible" for a message even consists of. Strip away the intuition of possession and one operational fact remains: the responsible party is the one who will send it again if it vanishes. That is the whole content of the idea. Responsibility is not about who holds a copy — during a handover both parties hold copies — it is about who still has a retry obligation.

That reframing makes the moment findable. Responsibility transfers at the instant the previous holder decides it will never retry. Which means it is not a physical event at all. It is a policy event, chosen by whoever wrote the acknowledgement logic, and it can be placed anywhere along the path.

Now trace the path with that lens. A producer sends a record and holds its retry obligation until the broker acknowledges. What that acknowledgement means is itself configurable, and the differences are not cosmetic: an acknowledgement from the leader alone means the record survives everything except that leader failing, while waiting for all in-sync replicas means it survives one machine's loss. Worth noting honestly: Kafka's durability here comes from replication across machines rather than from forcing every write to disk before replying, so a simultaneous power loss across the replica set is outside the guarantee.

Then the broker holds it. And the broker's obligation ends only when the consumer says so — which is the second transfer and the one people get wrong. AMQP 1.0 has the best word for it: settlement. A delivery is unsettled while either party might still act on it, and each side declares independently when it has settled. Kafka expresses the same thing as an offset commit; SQS expresses it as deleting the message before its visibility timeout expires; a classic broker expresses it as an explicit ack or nack.

Here is the question that exposes the design. In each of those, is the settlement sent before or after the work is done? If a client library acknowledges on receipt — which several do by default — then responsibility transferred at the moment of arrival, and a crash one millisecond later destroys the message with the job untouched. Nothing logs an error, because from the broker's view the handover succeeded.

And notice why duplicates exist. Between "the consumer settles" and "the broker learns it settled" there is a window where both believe they may be responsible. The broker cannot tell a consumer that crashed before finishing from one that finished and whose commit was lost, so it redelivers. Shrink that window to nothing by settling earlier and you have not removed the ambiguity — you have converted the duplicate into a loss.

One more layer, easy to miss. There is also responsibility toward the outside world. If your API told a caller "accepted" before the broker acknowledged, then you took on an obligation the system may not be able to keep, and the caller has no way to find out. The API response belongs after the broker's acknowledgement, not before it.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of a courier handing over a parcel against a signature. Before the signature the courier will come back tomorrow if the parcel goes astray; after it, the recipient's own filing system owns the problem. The signature is not a description of where the parcel physically is — it is the declaration that the courier's obligation has ended.

WHERE IT BREAKS DOWN

a parcel can only be in one place, so the courier's release and the recipient's acceptance are the same instant. A message is copied rather than moved, and the two declarations are separated by a network, so there is a real interval in which both parties believe they might still owe the work — and that interval, not the handover itself, is where duplicates and losses are born.

d

Clarifying the model

THE MODEL #

The refinement that ties it together: an unbroken chain of overlapping responsibility is the property you actually want. At no point should there be an instant where nobody would retry. Auto-acknowledgement breaks the chain by ending one obligation before the next begins. Settling after the work, with an identifier that lets a repeat be recognized, deliberately overlaps the obligations instead — which is why at-least-once and deduplication travel together.

A misconception worth naming: that a dead-letter queue is a failure handler. It is better understood as the broker's declaration that it is giving up its own obligation, because the redelivery loop is not converging. That makes it a transfer too — to a human, or to a process that has to decide what an unprocessable message means. A dead-letter queue nobody reads is a chain that ends in nothing.

And one genuine subtlety: settling does not mean the work's effects are visible. A consumer can commit its offset while its own database write is still in flight. The transfer of responsibility must be tied to the durability of the effect, not to the completion of the handler function, or the chain is broken inside your own process.

e

A picture of it

THE PICTURE #
When responsibility transfers
When responsibility transfers Read downward and watch the two dashed replies, which are the only lines where anything transfers -- the solid lines are just movement of bytes. Between the first solid line and the first dashed reply, the producer is obliged to retry; between delivery and settlement, the broker is. The final note marks the ambiguous interval: the consumer believes it is finished and the broker does not yet know, which is exactly the gap a duplicate arrives through. {"generator":"[email protected]","source":"../Socrates/.diagram-cache/_src/when-responsibility-transfers.md","sourceIndex":1,"sourceLine":4,"sourceHash":"86dce24255fa87a9e33cf7d6c77f65f1f21db6faf11fcb0221b6ee98508f8c25","diagramType":"sequence","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":774,"height":836},"qa":{"passed":true,"findings":[]}} Consumer 01 Broker 02 Producer 03 producer will retry until acked responsibility has moved here if this is lost the broker redelivers append record 1 replicate to in-sync replicas 2 acknowledged 3 deliver, unsettled 4 do the work and make it durable 5 settle, commit the offset 6
KINDSlifelineparticipantmessage

How to readRead downward and watch the two dashed replies, which are the only lines where anything transfers — the solid lines are just movement of bytes. Between the first solid line and the first dashed reply, the producer is obliged to retry; between delivery and settlement, the broker is. The final note marks the ambiguous interval: the consumer believes it is finished and the broker does not yet know, which is exactly the gap a duplicate arrives through.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

Responsibility for a message is not about who holds it but about who will send it again, so the moment of transfer is wherever an acknowledgement is placed — a decision, not a fact of the network. Designing the flow means keeping the obligations overlapping at every hop, never letting one end before the next begins, and accepting that the overlap you deliberately create is the same overlap that produces duplicates.

g

Where to go next

ONWARD #
  • How AMQP 1.0's settlement modes let each side declare its own moment, and what the unsettled state buys you.
  • Why a visibility timeout is really a lease on responsibility, and what happens when the work outlives the lease.
h

Key terms

TERMS #
TermWhat it means
SettlementAMQP 1.0's term for the moment a party declares it will take no further action on a delivery.
Offset commita consumer recording its position, which is how it ends the broker's redelivery obligation.
Visibility timeouta lease during which a message is hidden from other consumers, after which it reappears unless deleted.
Dead-letter queuewhere a broker places a message whose redelivery it has stopped attempting.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4