Persistence and Coordination from Requirements
By Leo GorodinskiPublished Jun 29, 2026Updated Aug 30, 2026
AI-generated summaryIn brief
- Persistence and coordination patterns are realization choices, not identities for the whole architecture.
- Start by naming what must remain true at each commit, delivery, and recovery boundary.
- Outbox, inbox, event sourcing, workflows, brokers, and databases each preserve part of the required behavior.
- Correctness comes from composing those guarantees and keeping unresolved obligations visible.
Backend patterns are often presented as competing architectures: CRUD, event sourcing, CQRS, outbox, actors, sagas, durable workflows, and pub/sub. In practice, a system uses several of them at once.
The useful question is not “Which pattern are we?” It is “What must remain true at this boundary, and which mechanism preserves it?”
Cohesive keeps the requirement separate from the mechanism. Persistence, delivery, coordination, and recovery become explicit operational concerns. Databases, brokers, workflow engines, runtimes, and generated code become possible realizations.
Start With Guarantees, Not Pattern Names
Each pattern handles a limited set of operational concerns:
- Persistence: which facts become durable and authoritative?
- Reconstitution: how does usable state return after restart or failure?
- Delivery: how does work cross a boundary, and when may it be acknowledged?
- Commit and coordination: which effects become durable together?
- Recovery: what happens after crash, retry, redelivery, replay, or partial progress?
The dimensions overlap without becoming interchangeable. A broker accepts a message without deciding whether a domain transition was legal. A workflow engine retries an activity without defining entity invariants. An actor runtime serializes work for one identity without automatically making its state durable. A database commits a row without notifying downstream observers.
Completion Depends On The Boundary
“Success” may mean that a transport accepted bytes, a broker retained a message, a consumer committed local state, a read model caught up, or a business process finished. These are different facts.
An HTTP 200 does not prove downstream completion. A broker acknowledgment does not prove that a consumer committed its transition. Provider acceptance does not prove that an external effect settled.
Cohesive names the boundary for each claim. That makes completion, authority, failure, and evidence easier to reason about.
Persistence Determines Recovery
Persistence records authoritative material such as current entity state, committed events, workflow history, offsets, or projections. Reconstitution turns that material back into usable state.
Current-state persistence hydrates an entity from a snapshot. Event sourcing replays committed history, often from a snapshot. A workflow resumes from history or a checkpoint. A projector rebuilds a read model from retained input.
The persisted material determines which recovery paths exist. A cache can speed up a read, but it does not become authoritative merely because it is convenient. A search index can serve a projection, but its freshness and rebuild path remain part of the contract.
The Dual-Write Problem Is A Boundary Problem
Many reliability bugs begin with two effects that do not share a commit boundary:
Dual write without a shared commit boundary
Update authoritative state, then Crash window, Publish external work
If the state commits and publication fails, downstream observers never receive the work. If publication succeeds and the state commit fails, observers react to a fact that never became authoritative.
The same shape appears in a database plus search index, a local transition plus notification, a workflow checkpoint plus external API call, or an offset commit plus local state change. Ordering the calls does not close the crash window.
Outbox and event sourcing solve different versions of this problem by making coordination material part of the durable local commit.
An outbox commits state and the responsibility to publish together. Event sourcing commits history that supports both reconstitution and downstream work. Neither mechanism proves downstream completion.
Committed history coordinates downstream work
Committed history is the shared source for Reconstitute state, Drive projections, Start process work, Publish external effects.
Reliable Handoff Needs Both Sides
Producer-side durability does not remove consumer-side duplication. A relay may publish more than once, and a broker may redeliver after a crash.
Outbox and inbox handoff
State + outbox commit, then relay, Retryable delivery, then retry / redelivery, Inbox + local transition commit, then ack after commit, Acknowledge
The consumer needs a stable input identity, local atomicity, deduplication or idempotent interpretation, explicit acknowledgment timing, and a recovery path. Together these mechanisms provide effectively-once local effects without pretending the network delivers exactly once.
Patterns Compose Through Guarantees
One mechanism establishes a fact that the next mechanism can rely on. An outbox binds state to publication responsibility. A relay and broker carry the work. An inbox protects the receiver's local transition. A process coordinates later steps, timeouts, and compensation.
Database transaction
- Guarantee It Contributes
- Atomicity and durability inside one local boundary
- What Remains Open
- Cross-boundary delivery and downstream completion
Outbox
- Guarantee It Contributes
- Local state and publication responsibility commit together
- What Remains Open
- Delivery duplicates, ordering, and consumer correctness
Inbox or idempotent receiver
- Guarantee It Contributes
- Duplicate inputs do not repeat the protected local effect
- What Remains Open
- Producer reliability and wider process completion
Event sourcing
- Guarantee It Contributes
- Committed history supports reconstitution, replay, and derived work
- What Remains Open
- Coordination across unrelated commit boundaries
Durable workflow
- Guarantee It Contributes
- Process progress, retry, timeout, and compensation survive failure
- What Remains Open
- Strict atomicity across independent participants
Infrastructure comes after the requirement. PostgreSQL, Cosmos DB, Kafka, Temporal, Durable Task, Orleans, Redis, and search platforms provide different capabilities. Capability closure compares those capabilities with the system's needs and reports the fit.
Cohesive Keeps The Choice Explainable
Cohesive records semantic intent independently of any one mechanism. Entities define legal state change. Processes define durable multi-step work. Relations define read meaning. Surfaces expose selected actions and observations. Operational requirements qualify each boundary.
Bindings connect those definitions to storage, messaging, workflows, runtimes, and infrastructure. A binding states which capability satisfies each requirement, which assumptions apply, and what evidence supports the match.
The result is not a pattern taxonomy. It is a reviewable path from what the system means to the mechanisms that preserve that meaning across commit, delivery, coordination, and recovery.