Skip to content

Architecture decision records

An ADR captures one significant decision: the context, the options considered, what we chose, and the consequences. We use a short version of MADR (see template.md).

  • When to write one: a decision is hard to reverse, shapes public API, or will be questioned later. Small, reversible choices do not need one.
  • Numbering: sequential, NNNN-short-title.md. Numbers are never reused.
  • Status: Proposed → Accepted (or Rejected). A later decision that reverses one is a new ADR. It marks the old one Superseded by NNNN and links back. To narrow part of it, the new record quotes the sentences it narrows, and the old record gains a line under its status, Narrowed by NNNN (Decision k); nothing else in it changes. We never delete or rewrite an accepted ADR’s decision.
  • Who decides: anyone can propose. The maintainer accepts.

Questions not yet decided are in open-questions.md.

# Decision Status
0001 Record architecture decisions Accepted
0002 The Django app is the unit of deployment Accepted
0003 Apps communicate only through contracts and connectors Accepted
0004 Each app owns its data Accepted
0005 Small required core; no bundled shared-service apps Proposed
0006 Contracts are typed and published as OpenAPI Accepted
0007 The in-process transport serializes, like the network ones Accepted
0008 Contract errors are typed and identical in both modes Accepted
0009 One database alias per app Proposed
0010 Pluggable principal resolution in core Accepted
0011 django-ninja for contract endpoints Proposed
0012 Supported Python and Django versions Accepted
0013 License: BSD-3-Clause Accepted
0014 Connector transports are pluggable Proposed
0015 Specification first; django-neolith is the reference implementation Accepted
0016 An app may run attached and detached at the same time Proposed
0017 The call context is explicit at the action and ambient for propagation Accepted
0018 Requirement IDs and spec-to-test traceability Accepted
0019 Wire encodings of the portable forms Accepted
0020 A portable form whose wire spelling differs from Pydantic’s default is a neolith Annotated type Accepted
0021 An app declares itself in class attributes of its NeolithAppConfig, with contracts named by their declaration classes Proposed
0022 The app host builds settings from declarations, checks at app loading, and boots when a handler is built Proposed
0023 A request’s principal comes from ordered backends that declare their request inputs, and a Django user is named by a deployer-given issuer and its primary key Proposed