ArchitectureMay 8, 20261 min read

Leader election for people who only have one job

You scaled to three replicas and now your hourly cron runs three times. You don’t need Raft — you need one lock.

The moment you run more than one replica, every @Cron job, every sweep, every "once an hour" task fires once per replica. Three pods, three duplicate settlements. You need exactly one of them to act.

You don’t need a consensus library

Reaching for Raft or ZooKeeper here is over-engineering. If you already run Postgres, it ships with everything you need: advisory locks.

leader.tsTypeScript
// Only the holder of this lock runs the job.
const [{ locked }] = await db.query(
  'SELECT pg_try_advisory_lock($1) AS locked', [JOB_KEY],
)
if (!locked) return            // another replica is leader
try { await runSweep() }
finally { await db.query('SELECT pg_advisory_unlock($1)', [JOB_KEY]) }
Why this works

A session-scoped advisory lock is released automatically when the connection drops. If the leader crashes mid-job, its lock dies with it and another replica picks up next tick. The failure mode is built in.

Properties you get for free

Leader election for people who only have one job is one row, one lock, and a finally block.

Reach for Raft when you need a replicated log. For "run this once," reach for the database you already have.

← All field notes