Copy this. You have a leader.

shell · hosted API
ROOM=$(curl -s -X POST https://api.octostore.io/elections \
  | jq -r .election_id)

curl -s -X POST \
  "https://api.octostore.io/elections/$ROOM/campaign" \
  -H "Content-Type: application/json" \
  -d '{"candidate_id":"worker-a","ttl_seconds":30}'

Run the campaign call from every candidate. The first live winner gets status: "leader". The others get status: "follower". They all see the same candidate ID, term, expiry, and retry timing.

The response tells you what to do next.

If you won

{
  "status": "leader",
  "leader": {
    "candidate_id": "worker-a",
    "term": 1842,
    "expires_at": "..."
  },
  "leader_token": "...",
  "renew_after_ms": 15000
}

Save the token, start leader-only work, and renew around renew_after_ms.

If someone else won

{
  "status": "follower",
  "leader": {
    "candidate_id": "worker-a",
    "term": 1842,
    "expires_at": "..."
  },
  "retry_after_ms": 29876
}

Do not perform leader-only work. Wait for the returned delay, then campaign again.

Keep the lease while you are healthy.

The leader token is a bearer capability. It can renew or resign the current term, but it does not create an account and it grants no authority over another room.

shell · renew
curl -s -X POST \
  "https://api.octostore.io/elections/$ROOM/renew" \
  -H "Content-Type: application/json" \
  -d "{\"leader_token\":\"$LEADER_TOKEN\",\"ttl_seconds\":30}"

Public leases can last from 5 to 300 seconds. Renewing keeps the same term. If renewal stops because the leader crashes or loses the network, the lease expires and a later campaign can create a higher term.

Resign when you are done.

A clean shutdown does not need to make followers wait for expiry.

shell · resign
curl -s -X POST \
  "https://api.octostore.io/elections/$ROOM/resign" \
  -H "Content-Type: application/json" \
  -d "{\"leader_token\":\"$LEADER_TOKEN\"}"

Why the term matters.

A lease tells candidates who should be leader now. It cannot erase an old process's memory. A paused leader can wake up after its lease expires and still believe it is in charge.

Term 1842 Worker A pauses Term 1843 Worker B wins Reject 1842 Old write is stale

Carry the returned term into downstream writes when the destination can remember the newest value. Once it has accepted 1843, it can reject a late write from 1842. Leases solve liveness. Fencing terms solve stale authority.

Use it from anything.

Cron and scheduled jobs. Let one machine run the cleanup even when the schedule fires everywhere.

Controllers and reconcilers. Keep one active coordinator while warm standbys observe.

Migrations and maintenance. Prevent two deploy processes from starting the same singleton task.

Agents and background workers. Choose one dispatcher without forcing the fleet into a workflow engine.

No signup does not mean no boundary.