Dynamic Consistency Boundary (DCB)
Why DCB exists and how it actually works
Why DCB exists
Section titled “Why DCB exists”Streams are great for per-aggregate consistency. They fall apart when a rule spans multiple streams:
- unique usernames across all users
- no double-booking across all rooms
- invoice numbers that never collide
Traditional event sourcing pushes those into sagas and compensations. DCB keeps the rule in one place by letting you check a query, not a stream.
How DCB actually works
Section titled “How DCB actually works”DCB has three moving parts:
- Tags on events (opaque strings like
username:alice) - Query that matches events by type and/or tags
- Append condition that fails if any matching events appear after a position you already saw
The flow looks like this:
readByQuery(query) -> events + lastPositiondecide(events) -> new eventappend(events, { failIfEventsMatch: query, after: lastPosition })If someone else writes a conflicting event in between, your append fails. No saga. No compensation.
DCB in DeltaBase
Section titled “DCB in DeltaBase”DeltaBase keeps the stream API intact and adds a streamless DCB API.
- Stream path:
readStream()+appendToStream() - Atomic multi-stream path:
multiStreamAppend() - DCB path:
readByQuery()+append()
Both can coexist. Use DCB only where you need cross-stream guarantees.
What about multi-stream append?
Section titled “What about multi-stream append?”multiStreamAppend() is different from DCB.
It is a transaction across known streams:
await eventStore.multiStreamAppend([ { streamId: 'order-123', events: [{ type: 'order.created', data: { orderId: '123' } }], expectedStreamVersion: 'no_stream', }, { streamId: 'customer-456', events: [{ type: 'customer.orderAdded', data: { orderId: '123' } }], expectedStreamVersion: 7, },]);All stream version checks pass and all events are written, or nothing is written. That’s useful when one command changes several aggregates and you already know exactly which streams are involved.
DCB is a condition over a query. You use it when the rule is not tied to one known stream list, like “no user can claim this username after the position I just read.”
When to use DCB vs streams
Section titled “When to use DCB vs streams”Use DCB when:
- the rule spans multiple streams
- you need global uniqueness or limits
- you want one event to affect multiple entities
Use streams when:
- the rule is per aggregate
- your invariants live inside one stream
- you care about per-stream ordering and versioning
Use multi-stream append when:
- one command writes several known streams
- partial success would be wrong
- per-stream expected versions express the consistency rule
What DCB is not
Section titled “What DCB is not”- It is not a database transaction across aggregates
- It does not prevent all races, only the ones you model in the query
- It does not replace streams for aggregate-level logic
DCB is a targeted tool. Use it where it matters.