13.8 Decision cheat sheet
Precompute (write path) when the query set is small and known; compute on read when it's large or unbounded.
How do I keep N systems in sync? Designate one system of record. Funnel all input through it. Derive everything else from its ordered change log. Never let the application write to two stores. Whether it's CDC or event sourcing matters far less than deciding on a total order.
Distributed transaction or derived data?
Either way, do not reach for XA. Where read-your-writes is not needed, asynchrony is a feature: it contains faults locally instead of amplifying them.
Should I unbundle? Only when no single piece of software satisfies all your requirements. Unbundling is about breadth, not depth. If one database does everything you need, use it. Every additional component brings a learning curve, config quirks, and operational surprises.
Where do I draw the write-path / read-path boundary? Precompute (write path) when the query set is small and known; compute on read when it's large or unbounded. Split it — cache the common queries, index the rest — and draw the boundary differently for outliers (the celebrity case). This is a dial, not a binary.
Do I need a hard constraint here?
On the apologizable side, build the compensating transaction. You almost certainly need the apology workflow anyway — the forklift argument.
And note the asymmetry: coordination reduces apologies-for-inconsistency but increases apologies-for-outage. Optimize the total.
Timeliness or integrity? Integrity always. Timeliness where it's worth paying for. Violations of timeliness are temporary and self-healing; violations of integrity are permanent and require explicit repair.
How do I make an operation exactly-once? Mint a request ID on the client before the first attempt. Propagate it through every hop. Enforce a uniqueness constraint at the durable end. Then make the derivation deterministic so replay is safe. No framework can do this for you — it is an end-to-end property by definition.
What must I audit? Anything you'd be unable to reconstruct if it were silently wrong. At minimum: a periodic source-vs-derived reconciliation, a restore-from-backup test, and an invariant check (debits = credits, counts match). Prefer end-to-end checks over per-component ones — they implicitly cover every disk, network, service, and algorithm on the path.