Consistency Models and Convergence in Denormalized Systems
The Staleness Problem
Denormalized data becomes stale the moment its source changes. If a product price updates at 10:00:00 but the denormalized product listing cache updates at 10:00:05, users see the old price for 5 seconds. This staleness window is unavoidable in async propagation. The design question: what staleness can your domain tolerate? Social feeds can accept seconds to minutes. Price displays might tolerate seconds. Inventory availability for checkout should be real-time (no denormalization).
Sync vs Async Propagation
Synchronous updates (update denormalized copies in the same transaction as source) guarantee consistency but add latency and failure modes. If updating 10 denormalized stores per write, any failure rolls back the entire transaction. Asynchronous updates (publish change events, consumers update copies) are faster and more resilient but introduce staleness. Most production systems choose async with staleness SLOs: target 95% of changes visible within 5 seconds, 99% within 30 seconds.
Change Data Capture Pattern
Change Data Capture (CDC) reads the database transaction log to publish change events. Every committed write to the normalized table automatically becomes an event in a message stream. Consumers process events and update denormalized stores. This is more reliable than application-level dual writes because the database guarantees the log captures all changes. If the consumer crashes, it resumes from its last checkpoint. Typical propagation lag: 100-500 ms under normal load, seconds during spikes.
Handling Out-of-Order Updates
Distributed message systems may deliver events out of order. If price changes from $10 → $15 → $12, events might arrive as $15, $10, $12. Without versioning, the denormalized store shows $10 (last processed) instead of $12 (actual). Solution: include a version number or timestamp in each event. Consumers only apply updates with version greater than current. Older events are discarded. This makes consumers idempotent: processing the same event twice produces the same result.