Quickstart: elect one leader.

This flow uses the hosted API and requires no login or API key. Create a random room, share the ID with your processes, and let each one campaign.

shell
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}'

A winner gets status: "leader", a monotonic term, and a secret leader_token. Every other candidate gets status: "follower", the current leader, and retry_after_ms.

Account-free leader election.

Election rooms are capability-based, not identity-based. The room ID is a shared coordination address. The leader token is the authority to mutate the current term.

Leader election endpoints
MethodPathPurpose
POST/electionsGenerate a 192-bit room ID
POST/elections/:id/campaignBecome leader or observe the winner
GET/elections/:idInspect current public state
POST/elections/:id/renewExtend the current lease with its leader token
POST/elections/:id/resignRelease leadership immediately

Renew at half the TTL

shell
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 election TTLs range from 5 to 300 seconds. A candidate can renew indefinitely while it is healthy. If it crashes, the room becomes vacant after expiry and a new term can begin.

Resign on a clean shutdown

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

Durable task locks.

Locks are the authenticated primitive for self-hosted coordination. Give a task a deterministic name, acquire it before side effects, renew while work runs, and release when complete.

shell
export OCTOSTORE_URL=http://localhost:3000
export OCTOSTORE_TOKEN=change-me

curl -s -X POST "$OCTOSTORE_URL/locks/issue-1842/acquire" \
  -H "Authorization: Bearer $OCTOSTORE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ttl_seconds":120,"metadata":"agent=atlas"}'

Lock responses return acquired, held, or delayed. Each successful acquisition includes a lease ID and a fencing token. Lock names may be hierarchical, such as repos/acme/app/issues/1842.

Self-host in one minute.

The release installer verifies the published SHA-256 checksum and binary version before placing octostore in /usr/local/bin.

shell
curl -fsSL \
  https://raw.githubusercontent.com/octostore/octostore.io/main/install.sh \
  | sh

STATIC_TOKENS='ops:change-me' \
DATABASE_URL='./octostore.db' \
octostore

curl http://localhost:3000/health

The server binds to 0.0.0.0:3000 by default and stores state in one SQLite file using WAL mode. Put TLS and network policy in your existing reverse proxy.

Configuration.

OctoStore configuration variables
VariableDefaultMeaning
BIND_ADDR0.0.0.0:3000HTTP listen address
DATABASE_URLoctostore.dbSQLite database path
STATIC_TOKENSunsetComma-separated user:token credentials
STATIC_TOKENS_FILEunsetNewline-delimited static token file
PUBLIC_ELECTIONStrueEnable account-free election endpoints
MAX_PUBLIC_ELECTIONS10000Maximum simultaneous public rooms
PUBLIC_ELECTION_REQUESTS_PER_MINUTE600Per-client admission limit for room creation and campaigns
GITHUB_CLIENT_IDunsetEnable optional GitHub OAuth when paired with the secret
ADMIN_KEYunsetProtect admin and metrics endpoints

Safety model.

  • Terms are monotonic across restarts. The next fencing term is persisted before an acquisition is returned.
  • Leases recover from crashes. A vanished process stops renewing and loses authority after expiry.
  • Election tokens are bearer capabilities. Do not log them or put them in URLs.
  • Room IDs are not access controls. Use generated IDs and self-host when room discovery or traffic must be private.
  • Election admission is rate limited per client. Status, renewal, and resignation stay available so load cannot strand a current leader.
  • Locks are advisory. Downstream systems should be idempotent and reject stale fencing terms where possible.

Full API reference.

The interactive OpenAPI reference covers elections, locks, sessions, webhooks, authentication, health, and admin operations.