Chapter 13 · Denormalization, Caching, and Derived Data

Documenting and Testing Denormalized Structures

Document and test denormalized structures with reconciliation checks, freshness SLAs, rebuild procedures, observability, and failure-mode validation.

Beginner65–95 minutesTesting + governanceLast reviewed: August 2026

Learning outcomes

Denormalized structures fail differently from normalized source tables. They can drift, lag, duplicate events, miss updates, and become unrebuildable. Production readiness therefore requires explicit documentation, reconciliation, automated tests, observability, and recovery procedures.

01

Create a denormalization contract for each derived structure.

02

Test synchronization, idempotency, freshness, and rebuild behavior.

03

Build reconciliation checks that detect drift.

04

Operate projections safely through failures and migrations.

Denormalization contract

model · example
NamePurposeSource of truthDerived fieldsSupported access patternsRefresh mechanismFreshness SLAIdempotency strategyReconciliation methodRebuild procedureOwner

Example contract

model · example
Name: WorkOrderListProjectionSource: WorkOrder + Asset + Customer + StatusFreshness: <= 5 secondsUpdate: outbox eventsRebuild: full backfillOwner: Service OperationsSupports: Q2, Q5

Transformation tests

Given authoritative source rows, verify the projection computes correct labels, totals, null handling, default behavior, and historical semantics.

Idempotency tests

model · example
apply event 1001apply event 1001 againexpected: same final state

Out-of-order tests

model · example
version 42 arrivesversion 44 arrivesversion 43 arrives lateexpected: projection remains at 44

Missing-event recovery

model · example
event 1001 appliedevent 1002 lostevent 1003 applied

Version-gap detection, reconciliation, or a replayable source should expose or repair the gap.

Reconciliation

sql · example
SELECT wo.work_order_idFROM work_order woLEFT JOIN (  SELECT work_order_id,         SUM(quantity * charged_unit_price) AS actual_total  FROM part_usage  GROUP BY work_order_id) x ON x.work_order_id = wo.work_order_idWHERE wo.parts_total IS DISTINCT FROM x.actual_total;

Sample-based reconciliation

For very large projections, continuous full comparison may be expensive. Use random samples, partition checksums, high-risk subsets, and periodic full audits.

Freshness monitoring

model · example
source latest event timestampprojection latest applied timestamplag = source - projection

Alert if lag exceeds the documented SLA.

Rebuild test

  1. create a new empty projection;
  2. backfill/replay source;
  3. verify counts and checksums;
  4. catch up live deltas;
  5. switch reads;
  6. retire old projection.
Operational rule

If a projection cannot be rebuilt deterministically, it is dangerously close to becoming a second source of truth.

Migration compatibility

Source schemas and projection schemas rarely change at exactly the same moment. Use compatible evolution so old and new consumers can overlap during rollout.

Backfill observability

  • rows processed;
  • rows remaining;
  • throughput;
  • error count;
  • retry count;
  • current lag;
  • estimated completion based on measured throughput.

Failure tests

Simulate consumer restarts, duplicate messages, network timeout, cache eviction, database failover, and partial backfill failure. A design that only works in the happy path is not production-ready.

Stale-data behavior

When lag exceeds SLA, decide whether to serve stale data, fall back to authoritative queries, disable the feature, or block correctness-sensitive commands.

Ownership and alerts

Every derived structure should have an operational owner and actionable alerts. “Data team” or “backend team” is often too vague when an incident occurs.

WorkshopHub denormalization registry

StructureFreshnessRebuildable?
WorkOrderListProjection<=5 sYes
DailyWorkOrderSummary<=1 minYes
SearchIndex<=30 sYes
Invoice snapshot fieldsImmutableFrom invoice source/event

Production-readiness checklist

Before launch

A new CustomerDashboardProjection is ready. What must be proven?

Review answer

Source ownership is documented; refresh is idempotent; out-of-order events are safe; freshness is monitored; reconciliation exists; full rebuild works; migrations are compatible; failure behavior is defined; and an operational owner is accountable.

Chapter 13 synthesis

Summary and next chapter

Chapter 13 showed how to denormalize without losing control of truth. You can justify duplication from evidence, assign ownership, build materialized aggregates, design caching layers, and test/reconcile derived data. Chapter 14 moves into time and structure: event history, effective dates, slowly changing operational data, recursive hierarchies, closure tables, and graph-like relationships.

References

  • Martin Kleppmann, Designing Data-Intensive Applications.
  • Martin Fowler, writings on CQRS, event sourcing, and caching.
  • Ralph Kimball and Margy Ross, The Data Warehouse Toolkit.
  • DBMS documentation for materialized views and replication.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.