Distributed Locks with Redis

A
Author
21 Aug, 2026 2 min read 459 views

When several app instances run the same scheduled job, you often want exactly one of them to do the work. A Redis lock is a simple way to coordinate.

Acquire with SET NX PX

import { randomUUID } from 'node:crypto';

async function acquireLock(name, ttlMs) {
  const token = randomUUID();
  const ok = await redis.set(`lock:${name}`, token, { NX: true, PX: ttlMs });
  return ok ? token : null;     // null = someone else holds it
}
  • NX - only set if the key doesn't exist.
  • PX - expire automatically, so a crashed holder can't block everyone forever.
  • A random token identifies this holder.

Release only your own lock

Never just DEL the key: if your lock expired and someone else acquired it, you'd delete their lock. Check the token and delete atomically with a Lua script:

const RELEASE = `
  if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
  else
    return 0
  end`;

async function releaseLock(name, token) {
  await redis.eval(RELEASE, { keys: [`lock:${name}`], arguments: [token] });
}

Putting it together

const token = await acquireLock('nightly-report', 60_000);
if (!token) return;                 // another instance is running it
try {
  await generateNightlyReport();
} finally {
  await releaseLock('nightly-report', token);
}

The hard part: expiry

If the work takes longer than the TTL (or the process pauses, for example in garbage collection), the lock expires and a second worker can start. Mitigations:

  • Set a TTL comfortably longer than the expected run time, and extend it periodically while working.
  • Make the work idempotent, so running it twice is harmless.
  • For correctness-critical locks, use fencing tokens: an increasing number checked by the resource being written, or use a database row lock instead.

Single-instance Redis locks are great for efficiency ("avoid duplicate work"). For strict mutual exclusion where a mistake causes data corruption, prefer a system with stronger guarantees, such as SELECT ... FOR UPDATE in your database.

Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.