# Distributed Lock Service

**Solution Architecture v1.0 · open source, fully on-premises · Platform Architecture · 2026-09 · 26 views · 24 architecture decision records**

A coordination service that issues expiring, ordered grants on named resources, built on dedicated etcd Raft quorums on hardware the operator owns, where the fencing token, not the lock, is the real output and mutual exclusion is enforced at the guarded resource's write path.

A lock service cannot stop a process from writing. A holder paused for longer than its lease looks exactly like a crashed one, and it wakes up still believing it holds the lock. So this design promises ordered grants everywhere and claims mutual exclusion only where the resource refuses a stale token. Everything else on these views follows from that.

The decisions that carry the design:

- **Token = epoch · 2^48 + the etcd revision of the granting transaction.** The commit mints it, so there is no per-key counter to keep forever.
- **The epoch is bound to the etcd cluster ID.** A restored cluster always gets a new ID, so it is sealed until a committed epoch advance, and token regression is impossible by construction.
- **Sessions are etcd leases, and every hold attaches to one.** Renewal is paid per process, not per lock: 8,000 keepalives a second instead of 50,000 consensus writes.
- **The holder stops before the log says it has lost.** It stops starting work at the first failed keepalive and fences at a deadline measured from when that keepalive was sent.
- **The resource's own conditional write is the fence.** A reference implementation and a SIGSTOP pause-test kit back every class marked fenced. Advisory correctness classes go on a dated risk register.
- **Two cluster tiers chosen by the lock class.** Coord handles leader election and entity handles high churn. Regional only, with a stretched quorum priced and deferred.
- **Audit is read from etcd's revision stream into ClickHouse,** so expiries are recorded and replays are idempotent.
- **No release without a checked history.** Chaos Mesh fault injection and the Porcupine linearizability checker gate every arbiter release and every etcd upgrade.

The architecture one-pager (including why the design holds up over time) and the full decision record appear on the landing page of the diagram set, directly below the index of views. Each record gives the forcing question, the on-premise mechanism, the options that lost, the consequences, when to choose differently, why it holds up over time, and the lesson. The same content is published as [docs/architecture-one-pager.md](docs/architecture-one-pager.md) (~11 min) and [docs/decision-record.md](docs/decision-record.md) (~55 min).

---

## What is here

| Path | Contents |
|---|---|
| `diagrams/index.html` | The landing page: 26 views in seven acts with every format linked, then the **architecture one-pager** and the **decision record** |
| `diagrams/*.html` | One self-contained page per view: the inlined diagram plus the reasoning cards, with copy / PNG / PDF export |
| `diagrams/svg/*.svg` | The same views as SVG with the diagram XML embedded; they re-open fully editable in diagrams.net |
| `diagrams/drawio/*.drawio` | draw.io source |
| `docs/architecture-one-pager.md` | The one-pager as markdown |
| `docs/decision-record.md` | The 24 decision records, the technology table and the package glossary as markdown |
| `specs/part-a..d.json` | Diagram specifications, the source of truth for every view |
| `specs/manifest-a..b.json` | Acts, page titles, subtitles and reasoning cards |
| `specs/adr.json` | The one-pager, the decision records, the capability-to-technology table and the glossary |
| `scripts/build.sh` | Rebuilds every deliverable from the specs (Node only) |
| `ask.md` | The requirement |

## Rebuild

```bash
bash scripts/build.sh
```

This needs Node 20+ and the `architecture-diagram-web` skill. The build checks every view against the geometry gate (0 errors, 0 warnings) and the routing gate (0 errors; 2 label-proximity warnings accepted on the hub-layout integration view), and checks that every link resolves.
