mutated × shared — the answer changes between runs
Stale Read From a Lagging Async Replica
You write to the primary, then read back from a replica that hasn't caught up -- so you act on a value that has already moved, but only when replication lag outruns your round-trip.
01the recipe
In the wild
compound ofvar / let / mut DeclarationsCWE-563Async IO MisuseCWE-662 Improper SynccompoundCWE-821 Incorrect Synchronization
example.js
// SMELL: write to primary, immediately read from an async replica.
// (var/let/mut x async I/O misuse)
await primary.set(userId, profile); // write
let current = await replica.get(userId); // replica lags -> stale read
render(current); // acts on a value that moved
// RIGHT: read-your-writes -- read from primary (or wait for the version).
await primary.set(userId, profile);
let current = await primary.get(userId); // or replica.waitFor(version)
render(current);Eventually-consistent replicas apply writes asynchronously, so a read issued right after a write can observe the prior value -- not a lost update (the data is consistent), just old at the moment you look. It only fails when lag happens to exceed the round-trip, so it survives every local test against a single node. Route read-your-writes reads to the primary or gate on a replication version token.
// observed
lagging: the just-written profile reads back as the old one (intermittently) right: read-your-writes -> you always observe your own write
02weakness catalog
Mapped weaknesses (CWE)
On its own, this defect is catalogued by MITRE as one or more of these weaknesses. The exploitable vulnerability usually appears only when it chains or combines with another.