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.

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.