The database layer the catalogues under-serve. Start dense, escalate only when forced. The combo slot is the heaviest carrying cost in the book.
| Pattern | What it solves | The shape | Skip-if |
|---|---|---|---|
| Multitenancy (shared schema + RLS) | Isolate tenants in one database | One DB, a tenant_id column, Row-Level Security enforcing the boundary | A single-tenant product: build none of it |
| Event Sourcing + CQRS + Materialized View | Audit, replay and read-scale without locking the write model | Events as the write log, materialized views as the read model, CQRS the umbrella | Most CRUD apps: the heaviest skip-if in the book |
| Optimistic Concurrency | Detect conflicting writes without locking | A version or rowversion checked on update; the loser retries | Single-writer data |
| Evolutionary Schema Migrations | Change the schema safely and reproducibly | Versioned, forward-only scripts (DbUp-style, not EF migrations) | Never, but keep it lightweight |
| Sharding / Partitioning | Scale data past one box | Data split across stores or partitions by a key | Nowhere near a single DB's limits: a classic tax |
| Cache-Aside | Cut read latency and DB load | Load on miss, populate the cache, serve from it next time | Writes dominate, or staleness can't be tolerated and you can't invalidate cleanly |
| Soft Delete / Temporal | Keep recoverable data and a change history | A flag or system-versioned rows; reads exclude deleted | No recovery or audit value (and mind the per-read query cost) |
Honorable mentions: lightweight Unit of Work (transaction boundary across gateways), Read Replicas, Connection Pooling.
Put a broker between the parts that produce work and the parts that handle it. A queue absorbs spikes, lets you add workers when volume grows, and parks failed messages instead of losing them. Broker-neutral: GCP Pub/Sub (AWS SQS+SNS, Azure Service Bus).
| Pattern | What it solves | The shape | Skip-if |
|---|---|---|---|
| Queue-Based Load Levelling | Absorb a spiky producer | A queue between producer and a steady-rate consumer | Synchronous, low-volume work |
| Competing Consumers | Scale processing horizontally | Many workers pulling from one queue | Ordering matters more than throughput |
| Publish/Subscribe | Fan one event out to many consumers | A topic; independent subscribers add themselves without touching the producer | Exactly one consumer, forever |
| Outbox | Stop lost or double events between DB and broker | The event written in the same DB transaction, published after commit | No cross-system consistency need |
| Backpressure / Dead-Letter Queue | Never silently drop failed work | Signal upstream to slow; park unprocessable messages for inspection | In-memory, single-process work |
| Saga / Process Manager | Keep consistency across services with no 2PC | A multi-step distributed transaction with compensating actions | You don't yet have a distributed transaction: a heavy skip-if |
| Claim-Check | Keep messages small and fast | The large payload stored externally; only a token rides the bus | Payloads are already small |
Honorable mentions: Idempotent Consumer (see Altitude 5), Event-Carried State Transfer, Priority Queue.
Download the full PDF for free?
Free download — no account required