HomeJournalThis post

Foundations: event delivery semantics

End-to-end delivery contracts separate broker receipt, durable processing, external effects, acknowledgement, deduplication, retry, and reconciliation.

JP
JP Casabianca
Designer/Engineer · Bogotá

Delivery is not the same as completion.

A broker can deliver a record once while a consumer charges twice after crashing between the charge and its checkpoint. A transport can redeliver the same message while an idempotent state transition produces one final result. The product guarantee depends on the whole path.

Apache Kafka's design documentation distinguishes at-most-once, at-least-once, and exactly-once processing and explains how producer, consumer, and destination behavior shape the claim.

We will draw the failure windows, name the durable boundary for each effect, and combine idempotency, transactions, retries, and reconciliation instead of relying on a slogan.

A trustworthy delivery guarantee says exactly what cannot happen twice—and where that claim stops.

01 · PublishPersist intent and identity

A stable event or operation ID, ordering key, schema, and outbox record connect database truth to emission.

02 · ProcessMake an idempotent transition

The consumer validates, claims deduplication, updates local state, and commits its checkpoint in a defined order.

03 · ReconcileRepair uncertain outcomes

Queries compare source intent, broker progress, destination state, and side-effect receipts after ambiguous failures.

Figure 1: One event crosses several durable boundaries.

Name the product outcome

Start with the irreversible or user-visible state that must occur zero, one, or many times rather than a broker acknowledgement metric.

I would pressure-test that decision with four questions:

  • What outcome matters?
  • Can omission be tolerated?
  • Can repetition be tolerated?
  • Which effect is reversible?

The failure mode here is declaring exactly once without naming the effect. In queues, streams, webhooks, background jobs, integrations, analytics, and distributed workflows where retries, crashes, partitions, rebalancing, duplicate messages, and side effects make exactly-once claims dangerously incomplete, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be an outcome cardinality contract. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.

The result I would look for is a guarantee stated at the product boundary. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.

In practice, I would put an outcome cardinality contract beside the question “What outcome matters?” before the first implementation review. The next pass would use “Can omission be tolerated?” to test the boundary, then “Can repetition be tolerated?” to expose the state most likely to be missed. I would keep “Which effect is reversible?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports a guarantee stated at the product boundary.

Assign stable operation identity

Retries across producers, transports, consumers, and destination APIs need one durable identity that survives every attempt.

The practical review starts here:

  • Who creates the ID?
  • How long is it retained?
  • Does it identify intent or attempt?
  • Can destinations accept it?

Those questions keep generating a new idempotency key inside every retry from becoming the default. I would capture the decision in an operation-identity lifecycle, then use it while the work is still cheap to change. For reliable asynchronous product workflows, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.

Success would look like all attempts converge on one logical operation. If I cannot point to that evidence, I have a direction, not a finished decision.

The implementation move is to make an operation-identity lifecycle part of the working surface. I would use it to answer “Who creates the ID?” while scope is still flexible, and “How long is it retained?” before code or content becomes expensive to unwind. During QA, “Does it identify intent or attempt?” and “Can destinations accept it?” become concrete checks rather than discussion prompts. That sequence turns reliable asynchronous product workflows into something the team can operate and gives me a specific outcome to report: all attempts converge on one logical operation.

  1. Before effectRetry is harmless

    The message remains unacknowledged and the next attempt repeats validation with no committed product change.

  2. After effectOutcome is ambiguous

    The product change may exist while acknowledgement does not; identity and lookup decide whether retry repeats it.

  3. After ackCheckpoint advances

    The system considers the message handled; recovery now depends on durable evidence matching that claim.

Figure 2: Crash timing determines repetition or loss.

Choose ordering scope

Global order is expensive and rarely required; entity, account, aggregate, or partition ordering should match the invariant being protected.

Before implementation, I would answer:

  • Which events must precede others?
  • Can independent entities run concurrently?
  • What key selects a partition?
  • How is a gap handled?

The artifact is an ordering-key decision. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is assuming timestamps establish total causal order; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.

For me, the useful receipt is sufficient order without unnecessary serialization. That connects an end-to-end delivery contract that separates transport receipt, durable processing, state transition, external side effect, acknowledgement, deduplication, and reconciliation to an observable result instead of a process claim.

I would test this with one typical case and one boundary case. The typical case should make “Which events must precede others?” easy to answer. The boundary should force a decision about “Can independent entities run concurrently?” and “What key selects a partition?.” I would record both in an ordering-key decision, including the part that stayed unresolved after the first pass. The final check, “How is a gap handled?,” is where the artifact earns its place: it either supports sufficient order without unnecessary serialization, or it shows exactly why another iteration is needed.

Use transactional outbox and inbox patterns

Writing intent beside business data and deduplication beside consumer state closes common gaps between databases and brokers.

I would use these prompts during the working review:

  • Can business state and outbox commit together?
  • How is publication retried?
  • Can inbox and effect share a transaction?
  • When are records cleaned?

If the team slips into committing business data then publishing as an unrelated best effort, the product can still look complete while its operating rule stays ambiguous. I would make an outbox-and-inbox state model the shared reference and keep it small enough to update as evidence changes.

The standard is durable handoff through local transaction boundaries. That tells me whether the decision helped the product, not merely whether the document was completed.

The working sequence is small: draft an outbox-and-inbox state model, review it against “Can business state and outbox commit together?,” implement the narrowest useful path, and then return with evidence for “How is publication retried?.” I would use “Can inbox and effect share a transaction?” to inspect product consequence and “When are records cleaned?” to decide whether the result is stable enough to ship. This keeps committing business data then publishing as an unrelated best effort visible as a known risk and makes durable handoff through local transaction boundaries the release receipt rather than a hopeful conclusion.

SignalDecisionWorking note
At most onceMay lose, should not repeatAcknowledge before processing or avoid retry; useful only when omission is safer than duplication.
At least onceShould not lose, may repeatAcknowledge after durable processing; consumers must expect duplicate delivery and reordered attempts.
Exactly onceBounded transactional claimRequires precise scope; external APIs and human effects usually sit outside the broker's atomic transaction.
Figure 3: Common semantics trade loss against duplication.

Make consumers idempotent

Duplicate delivery should converge through uniqueness, compare-and-set transitions, version checks, or natural idempotency—not a short-lived memory cache alone.

I would pressure-test that decision with four questions:

  • What durable key rejects repetition?
  • Does the handler return the prior result?
  • Can payloads differ for one key?
  • How are concurrent attempts serialized?

The failure mode here is checking a volatile processed set and performing the effect separately. In queues, streams, webhooks, background jobs, integrations, analytics, and distributed workflows where retries, crashes, partitions, rebalancing, duplicate messages, and side effects make exactly-once claims dangerously incomplete, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be an idempotent consumer contract. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.

The result I would look for is retries that preserve one durable outcome. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.

In practice, I would put an idempotent consumer contract beside the question “What durable key rejects repetition?” before the first implementation review. The next pass would use “Does the handler return the prior result?” to test the boundary, then “Can payloads differ for one key?” to expose the state most likely to be missed. I would keep “How are concurrent attempts serialized?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports retries that preserve one durable outcome.

Bound external side effects

Email, payment, ticketing, and partner APIs may fall outside the transaction, so their idempotency support and lookup behavior define the real guarantee.

The practical review starts here:

  • Does the API accept idempotency keys?
  • Can outcome be queried after timeout?
  • Can the action be compensated?
  • Which ambiguity needs human review?

Those questions keep assuming a broker transaction includes a remote API from becoming the default. I would capture the decision in an external-effect capability matrix, then use it while the work is still cheap to change. For reliable asynchronous product workflows, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.

Success would look like honest semantics across the weakest boundary. If I cannot point to that evidence, I have a direction, not a finished decision.

The implementation move is to make an external-effect capability matrix part of the working surface. I would use it to answer “Does the API accept idempotency keys?” while scope is still flexible, and “Can outcome be queried after timeout?” before code or content becomes expensive to unwind. During QA, “Can the action be compensated?” and “Which ambiguity needs human review?” become concrete checks rather than discussion prompts. That sequence turns reliable asynchronous product workflows into something the team can operate and gives me a specific outcome to report: honest semantics across the weakest boundary.

Classify retries

Transient availability, throttling, invalid payload, permanent authorization, poisoned data, and code defects should not share one infinite retry loop.

Before implementation, I would answer:

  • Is another attempt likely to work?
  • What backoff and jitter apply?
  • When is the event parked?
  • Who owns remediation?

The artifact is a retry and terminal-state taxonomy. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is sending every exception to a dead-letter queue without context; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.

For me, the useful receipt is bounded recovery with actionable failure ownership. That connects an end-to-end delivery contract that separates transport receipt, durable processing, state transition, external side effect, acknowledgement, deduplication, and reconciliation to an observable result instead of a process claim.

I would test this with one typical case and one boundary case. The typical case should make “Is another attempt likely to work?” easy to answer. The boundary should force a decision about “What backoff and jitter apply?” and “When is the event parked?.” I would record both in a retry and terminal-state taxonomy, including the part that stayed unresolved after the first pass. The final check, “Who owns remediation?,” is where the artifact earns its place: it either supports bounded recovery with actionable failure ownership, or it shows exactly why another iteration is needed.

Design acknowledgement timing

The checkpoint should move only after the durable work promised by the consumer is committed, with cancellation and rebalance handled explicitly.

I would use these prompts during the working review:

  • What must commit before ack?
  • Can leases expire mid-effect?
  • How is shutdown drained?
  • Can two consumers own the message?

If the team slips into acknowledging after parsing but before the consequential write, the product can still look complete while its operating rule stays ambiguous. I would make an acknowledgement state machine the shared reference and keep it small enough to update as evidence changes.

The standard is no silent gap between claimed processing and durable state. That tells me whether the decision helped the product, not merely whether the document was completed.

The working sequence is small: draft an acknowledgement state machine, review it against “What must commit before ack?,” implement the narrowest useful path, and then return with evidence for “Can leases expire mid-effect?.” I would use “How is shutdown drained?” to inspect product consequence and “Can two consumers own the message?” to decide whether the result is stable enough to ship. This keeps acknowledging after parsing but before the consequential write visible as a known risk and makes no silent gap between claimed processing and durable state the release receipt rather than a hopeful conclusion.

Reconcile beyond retries

Retries cannot resolve every ambiguous result; periodic comparison between intent and outcome is required for high-consequence workflows.

I would pressure-test that decision with four questions:

  • Which sources can be compared?
  • How old may an operation be?
  • Can repair be automated?
  • What evidence supports manual action?

The failure mode here is treating an empty dead-letter queue as proof of completeness. In queues, streams, webhooks, background jobs, integrations, analytics, and distributed workflows where retries, crashes, partitions, rebalancing, duplicate messages, and side effects make exactly-once claims dangerously incomplete, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a reconciliation query and runbook. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.

The result I would look for is detected and repairable drift after unknown outcomes. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.

In practice, I would put a reconciliation query and runbook beside the question “Which sources can be compared?” before the first implementation review. The next pass would use “How old may an operation be?” to test the boundary, then “Can repair be automated?” to expose the state most likely to be missed. I would keep “What evidence supports manual action?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports detected and repairable drift after unknown outcomes.

Drill the failure windows

Tests should crash before and after every durable boundary, duplicate messages, reorder partitions, expire leases, time out external calls, and verify both outcome and evidence.

The practical review starts here:

  • Can the process be killed deterministically?
  • Does one outcome remain?
  • Can stuck work be found?
  • Does replay preserve ordering?

Those questions keep testing one successful handler invocation from becoming the default. I would capture the decision in a delivery failure-injection suite, then use it while the work is still cheap to change. For reliable asynchronous product workflows, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.

Success would look like evidence that the declared semantics survive realistic interruption. If I cannot point to that evidence, I have a direction, not a finished decision.

The implementation move is to make a delivery failure-injection suite part of the working surface. I would use it to answer “Can the process be killed deterministically?” while scope is still flexible, and “Does one outcome remain?” before code or content becomes expensive to unwind. During QA, “Can stuck work be found?” and “Does replay preserve ordering?” become concrete checks rather than discussion prompts. That sequence turns reliable asynchronous product workflows into something the team can operate and gives me a specific outcome to report: evidence that the declared semantics survive realistic interruption.

What I would show in the work

The public version needs evidence from the work itself. For this topic, the first five artifacts I would reach for are:

  • an outcome cardinality contract
  • an operation-identity lifecycle
  • an ordering-key decision
  • an outbox-and-inbox state model
  • an idempotent consumer contract

I would not publish all five at equal weight. One should orient the reader, one should reveal the hardest tradeoff, and one should prove the result. The others can live in a downloadable note or appear as supporting frames. That edit matters because an end-to-end delivery contract that separates transport receipt, durable processing, state transition, external side effect, acknowledgement, deduplication, and reconciliation becomes harder to understand when every process detail is treated as equally important.

I would also show one rejected direction. The useful version is specific: which option looked attractive, which constraint made it wrong, and what evidence supported the narrower choice. That gives an engineering manager something real to question and keeps the case study from reading like the final answer was obvious from the beginning.

delivery-semantics-contract.md
# event
subscription.renewal:v3 / op_8F2
Producer outbox and consumer inbox share stable identity; account ID is the ordering key.

# effect ledger insert unique(op_id) Database constraint makes local financial transition idempotent; notification is a separate derived event.

# repair intent minus ledger minus processor state Reconciliation finds missing, duplicate-attempt, and stuck operations; runbook chooses replay, compensate, or investigate.

Figure 4: The receipt exposes the end-to-end boundary.

Resource path

The practical follow-up I would build is an event-delivery semantics worksheet with producer IDs, ordering keys, consumer checkpoints, idempotency records, retry classes, dead-letter policy, outbox and inbox patterns, side-effect boundaries, reconciliation queries, and failure drills. I am treating that as a resource backlog item, not pretending the adjacent downloads below are the same artifact. The related cards cover useful pieces of the workflow today; this specific file should only be published when its examples, fields, and instructions are complete.

The first version should stay concise: context, constraint, decision, evidence, owner, and follow-up. Its value would come from helping someone repeat this exact review, not from adding another generic PDF to the site.

Review checklist

The article-specific review questions are:

  • What outcome matters?
  • Who creates the ID?
  • Which events must precede others?
  • Can business state and outbox commit together?
  • What durable key rejects repetition?
  • Does the API accept idempotency keys?
  • Is another attempt likely to work?
  • What must commit before ack?
  • Which sources can be compared?
  • Can the process be killed deterministically?

I would add two editorial checks before publishing: can a recruiter find the point in the first minute, and can an engineer trace at least one claim to an implementation or production receipt? If either answer is no, the article needs another edit.

Implementation notes

For reliable asynchronous product workflows, I would write the implementation note before polish. It would name the changed surface, source of truth, owner, failure boundary, and verification path. Those details prevent the principle from floating above the actual code or operational workflow.

The proof signals I care about are specific to this article:

  • honest semantics across the weakest boundary
  • bounded recovery with actionable failure ownership
  • no silent gap between claimed processing and durable state
  • detected and repairable drift after unknown outcomes
  • evidence that the declared semantics survive realistic interruption

I would choose two or three of those signals for the first release rather than instrumenting everything. The strongest pair usually combines one direct behavior check with one operating check: a route and a data query, a keyboard path and a support state, a handler replay and a reconciliation result, or a migration count and a rendered screen.

The follow-up belongs in the note before shipping. It should say what remains temporary, what evidence would trigger another pass, and who owns that decision. That is how the first version stays intentionally narrow without making the boundary invisible.

Case-study packaging

I would structure the case-study version around the four visual lessons already established:

  • One event crosses several durable boundaries.
  • Crash timing determines repetition or loss.
  • Common semantics trade loss against duplication.
  • The receipt exposes the end-to-end boundary.

The opening frame explains the product pressure. The middle two show the decision moving through the system. The last frame is the receipt: what was checked, what held, and what remained unresolved. That order lets the reader move from product judgment into implementation detail without reconstructing the whole project first.

I would include one caveat tied to queues, streams, webhooks, background jobs, integrations, analytics, and distributed workflows where retries, crashes, partitions, rebalancing, duplicate messages, and side effects make exactly-once claims dangerously incomplete: a data limit, rollout boundary, unsupported state, external dependency, or result that is still directional. A precise caveat makes the evidence easier to trust because it shows where the claim stops.

The final test is whether the page creates a better conversation. If the artifact helps someone ask a sharper question about product judgment, implementation detail, or release proof in a live interview, it belongs in the story.

Interview angle

In an interview, I would explain this through an end-to-end delivery contract that separates transport receipt, durable processing, state transition, external side effect, acknowledgement, deduplication, and reconciliation. The story should start with the product pressure, then move into the system constraint, the artifact, and the proof. That order keeps the answer grounded. It also gives the interviewer several places to go deeper: data, frontend architecture, design systems, support, migration, accessibility, or release process.

The strongest version of the answer includes a tradeoff. I want to be able to say what I chose, what I left alone, and how I knew the work helped. That is more credible than presenting every project as a clean win.

The hiring signal

An end-to-end delivery contract is a hiring signal because it shows I can translate distributed-systems guarantees into durable product outcomes, observable recovery, and honest boundaries.

That is the level I want this site to communicate. The work should show taste, but it should also show operating judgment. It should make me look like someone who can enter a real product system, understand the messy middle, ship the useful version, and leave enough proof for the next person to trust it.

Companion artifacts

Use this after reading.

Practical downloads and templates that turn the article into something you can bring into a product review, implementation pass, or agent workflow.

RepoJun 2026

Agent-Ready API Spec Template

An OpenAPI and Postman starter template for APIs that AI agents can discover, call, and recover from safely.

OpenAPIPostmanAI agents
View details
TemplateJul 2026

Dependency Adoption Receipt

A reviewable receipt for package need, identity, provenance, permissions, supply-chain risk, verification, ownership, and removal.

Supply chainSecurityAI-assisted
View details
DownloadJun 2026

UI PR Risk Review Checklist

A merge-readiness checklist for product intent, states, accessibility, visual durability, and UI implementation risk.

UI reviewQAFrontend
View details