Part 2 · 1 chapters · ~8 min

Decision Records

Architecture decision records (Nygard's format), what deserves a record, writing context and consequences honestly, statuses and superseding, storing records in the repository, lightweight variants (decision logs, Y-statements), and using records in onboarding and reviews.

4

A record in full

code
# ADR-031: Use Postgres advisory locks for payout scheduling
Status: Accepted (2026-09-12) · Supersedes: none · Deciders: payouts team, platform

## Context
Payout batches must run once per 5 minutes across 6 replicas. Duplicate runs double-submit payouts (incident INC-212).
We already run Postgres 16; we do not run ZooKeeper or etcd and do not want a new dependency for one job.

## Decision
We will take pg_try_advisory_lock(hashtext('payout-batch')) at the start of each run; replicas that fail to get it skip.
Payout submission stays idempotent (unique key per payout) as a second line of defence.

## Consequences
+ No new infrastructure; lock released automatically if the session dies.
- Locks are per database: a future split of the payouts database needs a new mechanism (revisit then).
- A long GC pause holding the lock delays one batch; acceptable at 5-minute cadence.
Follow-up: alert if no batch completes for 15 minutes.

Y-statement (a one-sentence variant): "In the context of payout scheduling, facing duplicate runs across replicas, we decided for Postgres advisory locks and against etcd leases, to achieve single execution without new infrastructure, accepting per-database scope."

DECISION RECORDS
short, immutable, next to the code
titleADR-031: Use Postgres advisorylocks for payout scheduling.contextThe forces at play: constraints,requirements, what is true now.decisionWhat we decided, in active voice:"We will…"consequencesWhat becomes easier, what becomesharder, follow-ups.statusProposed, accepted, deprecated,superseded by ADR-047.wheredocs/adr/ in the repo; linked fromcode comments and PRs.
swipe the figure sideways, or tap expand for full screen
1/4
why record
Six months later someone asks "why did we do it this way?" Without a record the decision gets relitigated, or reversed by someone who does not know the constraint.
prevent relitigationpreserve the constraint