Skip to content

Architecture Decision Records

The project keeps Architecture Decision Records (ADRs) for non-trivial design choices. Each ADR documents:

  • The decision — what was decided.
  • Context — what problem prompted the choice.
  • Alternatives considered — what else was on the table.
  • Trade-offs — what was given up vs gained.
  • Consequences — what this implies for the codebase.

For most users, ADRs are optional reading — they’re for contributors + curious users who want the deep “why.”

ADRs are kept in the repo under docs/adr/ (if present) or as long-form comments in the relevant source files.

The framework follows the ADR pattern loosely — not every PR generates an ADR, but major decisions do.

(The actual ADR list is in the repo; this is a high-level sample.)

ADRTopic
001Why Bun as the primary runtime.
002The TypeScript-first message contract (vs. runtime checks).
003HOCON over YAML for configuration.
004The CRDT type set (which to ship, why not more).
005Single-process vs multi-process clustering as the default.
006The Lease abstraction (vs. embedded coordination).
007At-least-once delivery model (vs. exactly-once promises).
008Why ts-pattern as a peer dependency, not bundled.
009The schema-migration envelope format.

These names are illustrative — the actual ADR repo has its own numbering + scope.

A new ADR is written when:

  • A design change affects multiple modules.
  • A trade-off is non-obvious and future contributors would ask “why?”
  • An API surface is being committed to.

Trivial refactors and bug fixes don’t get ADRs. The bar is “would a smart contributor a year from now thank you for writing this down?”

ADRs are written in plain Markdown:

# ADR 005: Single-process clustering
## Context
Akka and Pekko run a JVM cluster across processes. For
TypeScript, single-process and multi-process are both
plausible defaults.
## Decision
Cluster across processes is the default. Single-process
"worker mesh" is a separate opt-in.
## Alternatives
- Single-process default: simpler, less flexible.
- Worker-thread cluster: complex to debug.
- TCP-only cluster: today's default, most operationally
familiar.
## Trade-offs
We gain operational simplicity (each process is independent).
We lose in-memory cluster-internal sharing.
## Consequences
- The cluster transport defaults to TCP.
- Worker-mesh has its own transport + setup.
- Tests use MultiNodeSpec (in-process) or
ParallelMultiNodeSpec (process-isolated).

Read the relevant ADR before proposing changes to the same area — context might dissuade or reframe your proposal.

If you submit a PR that changes a significant design choice, include an ADR. Reviewers will ask for one if it’s missing.

Template:

# ADR NNN: <title>
## Context
<the problem you're solving>
## Decision
<what you decided>
## Alternatives
<what else you considered>
## Trade-offs
<what you gain vs lose>
## Consequences
<what this implies>

Keep ADRs short (1-2 pages). Long-form discussion goes in the PR or in a design doc.