TIL — Redis SET NX as a poor-man's singleflight
A 4-line pattern for de-duplicating expensive computations across processes when you don't need a full distributed lock.
1 min read 194 words
You don’t always need ZooKeeper, etcd, or a Redlock implementation to coordinate
expensive work across processes. For idempotent, short-lived computations — the
exact shape of cache rebuilds — SET key value NX EX <ttl> is enough.
const acquired = await redis.set(`lock:${key}`, processId, 'NX', 'EX', 30);if (acquired === 'OK') { // I'm the one who computes. Everyone else can wait or read stale. const value = await expensive(); await redis.set(`cache:${key}`, value, 'EX', 300);} else { // Someone else is computing — fall through to stale read.}Caveats it does not handle:
- The holder crashing mid-computation. The TTL bounds the damage but the work is lost; on the next miss someone re-acquires.
- Multiple keys forming a critical section. NX is per-key; for cross-key coordination, you need an actual lock manager.
- Cache stampede across regions if the keyspace fans out. Solve with jittered TTLs, not bigger locks.
For 80% of “we just don’t want all 50 pods recomputing this at once,” it’s enough. The longer-form treatment of stampede protection — including SWR, jittered TTLs, and the failure modes this pattern doesn’t cover — lives in the caching playbook entry.