Node.js › Caching with Redis
How would you implement a distributed lock using Redis to coordinate access to a shared resource across multiple Node.js instances?
AdvancedAnswer
A distributed lock uses Redis's atomic SET with the NX (only set if not exists) and EX (expiration) options to acquire a lock -- only one instance can successfully set the key, guaranteeing mutual exclusion, with the expiration ensuring the lock is automatically released even if the instance holding it crashes without explicitly releasing it, preventing a permanently stuck lock.
async function acquireLock(resource, ttlMs = 10000) {
const lockId = crypto.randomUUID();
const acquired = await client.set(`lock:${resource}`, lockId, { NX: true, PX: ttlMs });
return acquired ? lockId : null;
}
async function releaseLock(resource, lockId) {
// Only release if we still hold the lock (using a Lua script for atomicity)
const script = `if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end`;
await client.eval(script, { keys: [`lock:${resource}`], arguments: [lockId] });
}Real-world example A daily report-generation job that must run exactly once, even though it's triggered from multiple redundant scheduler instances for high availability, uses a Redis distributed lock so only the first instance to acquire the lock actually runs the job, while the others detect the lock is held and skip execution.