Module 11 · Lesson 02

Twelve patterns that reappear in every design

Most design problems are one of a dozen shapes wearing a product name.

Advanced 8 min read Updated 2026-11-02

What you will be able to do

  • Map a novel problem onto a known pattern
  • Explain the cost of precomputation versus computation at read time
  • Recognise when CQRS or an outbox is the missing piece
  • Combine patterns without contradicting one another

The catalogue

PatternSolvesCost
Precomputed feed (fan-out on write)Fast timeline readsExpensive/awkward for celebrities
Fan-out on readCheap writes, one timeline per viewerRead amplification
CQRSDifferent read and write shapesLag between models
Transactional outboxGuaranteed event publicationRelay to operate
SagaMulti-service workflow without a distributed transactionCompensations, intermediate states
Idempotency keySafe retriesStore of keyed outcomes
Write-ahead logDurability and replicationRecovery time
Read repairDivergent replicasBackground reads and comparisons
Consistent hashingRebalancing when nodes changeVirtual nodes and complexity
Sharding by keyHorizontal scale beyond one nodeCross-shard queries
Circuit breakerCascading failureFallback design
Cold tieringStorage costRetrieval latency
Two consistency choices, one design
A strong-consistency write path feeding an eventually-consistent read model is normal — as long as you say the lag exists. Saying both are strongly consistent is the mistake.

Patterns as questions

Each pattern answers a question. Read rate high and data changing rarely? Precompute. Writes spread across many services and someone must know the truth? Outbox. Reads and writes want different schemas? CQRS. Cross-service business transaction? Saga with compensations. These are the same three sentences every time, applied to a different noun.

Reduce the problem to a shape
Is it a feed, a counter, a lookup, a workflow, a stream, or a search?
Name the dominant constraint
Read latency, write volume, correctness, or cost. One dominates most designs.
Pick two patterns, not seven
A cache and a precomputed read model is a design. Seven named patterns with no interaction described is a vocabulary exercise.
State the failure mode
What happens when the cache is cold, the outbox relay stops, or the shard is unavailable? That answer is the design.

Worked example: notifications

A notification service takes events, decides who to notify, renders a channel-specific message, and delivers with retries. Patterns: fan-out on read of preferences, a queue per channel for rate limits, idempotency keys so a retry does not double-send, a dead-letter queue for permanent failures, and a deduplication window of minutes.

That is five patterns in four sentences because they answer different questions: who, how fast, how often, what if it fails, and what if it fails twice. Being able to decompose a problem this way is worth more than naming more tools.

The closing move
"This is a precomputed read model with an outbox to keep it in sync. The lag is under a second, and if the relay stops the model is stale but recoverable from the log."

Worth remembering

  • Precompute what is read constantly and changes rarely; compute what is read rarely or must be exact.
  • A write-ahead log is the basis of durability, replication and replay — one idea, three uses.
  • CQRS separates the write model from read models, at the cost of eventual consistency between them.
  • Patterns compose, but two conflicting consistency choices in one design is a bug, not a nuance.

Checkpoint

Answer all 3 questions to finish the lesson.
1. Which pattern keeps a read model in sync without a distributed transaction?
The outbox commits the event with the write and relays it afterwards, so committed changes always produce events.
2. When is fan-out on write the wrong choice?
Write cost scales with follower count. Very large accounts need pull-based merging instead.
3. What is the main risk of combining CQRS with a strongly consistent read requirement?
Separating models introduces propagation delay. If reads must be exact, read from the write model or wait for the projection offset.