Distributed Locks and the Redlock Algorithm
Coordinate exclusive access across instances safely and understand the limits of distributed locking.
Why Distributed Locks?
When your Node.js API runs as a single process, a simple in-memory mutex is enough to serialize access to a critical section. But production backends run many instances behind a load balancer, often across multiple machines.
- Two pods may both try to charge the same invoice.
- Two workers may both pick up the same job from a queue.
- Two requests may both regenerate the same expensive cache entry (a cache stampede).
An in-memory lock lives inside one process only — the other instances know nothing about it. To coordinate exclusive access across instances you need a lock that lives in shared external storage, and Redis is a popular home for it.
A First (Naive) Redis Lock
The core primitive is the atomic SET key value NX PX ttl command. NX means "only set if the key does not exist", and PX sets an expiry in milliseconds so the lock auto-releases if the holder crashes.
- If
SETreturnsOK, you acquired the lock. - If it returns
null, someone else holds it.
The value must be a unique random token per acquisition — you will need it later to release safely.
const { createClient } = require('redis');
const crypto = require('crypto');
async function acquire(redis, key, ttlMs) {
const token = crypto.randomUUID();
// NX = set only if absent, PX = expiry in ms
const ok = await redis.set(key, token, { NX: true, PX: ttlMs });
return ok === 'OK' ? token : null;
}
// Usage sketch (needs a running Redis):
// const redis = createClient(); await redis.connect();
// const token = await acquire(redis, 'lock:invoice:42', 10000);
// if (token) { /* do exclusive work */ }All lessons in this course
- Cache-Aside, Write-Through, and TTL Strategies
- Distributed Locks and the Redlock Algorithm
- Pub/Sub, Streams, and Rate Limiting with Redis
- Preventing Cache Stampedes and Thundering Herds