Every codebase has decisions baked into it that nobody remembers making.
Why is this service synchronous instead of async? Why does this module use Repository pattern but that one doesn't? Why are we on PHP 8.3 instead of 8.4?
The answer is usually "because someone decided that two years ago and we don't know why."
Architecture Decision Records (ADRs) are the fix. They're short documents — often just a page — that record:
- The context (what problem were we solving?)
- The decision (what did we choose?)
- The consequences (what does this mean going forward?)
What we actually did
When I joined the team, the codebase was brownfield — years of accumulated decisions with no written rationale. That made it the perfect moment to change the habit. I introduced ADRs and wrote the first 11 myself, covering:
- Module boundary rules (enforced by Deptrac)
- Database interaction patterns (no raw SQL outside Repository classes)
- Naming conventions for handlers, DTOs, and services
- When to use Doctrine vs raw PDO
- How to version the OpenAPI spec
- CI quality gate requirements
They live in docs/adr/ in the repo, numbered sequentially: 0001-module-boundaries.md, 0002-database-patterns.md, etc.
The format that stuck
I tried multiple ADR formats. The one that the team actually used was the shortest one:
# ADR 0001: Module boundaries enforced by Deptrac
## Status
Accepted
## Context
Without explicit boundaries, modules will import from each other freely,
making the codebase increasingly tangled over time.
## Decision
Each module may only depend on its direct dependencies as defined in
deptrac.yaml. Cross-module access goes through interfaces.
## Consequences
- New features must think about which module they belong to
- Deptrac runs in CI; violations fail the build
- Refactoring across modules requires updating deptrac.yaml explicitly
That's it. The key is: write it before you implement, while the reasoning is fresh.
Getting the team to write them
The hardest part is habit formation. What worked for us:
- Led by example — I wrote the first batch before asking anyone else to
- PR requirement — significant architectural changes needed a linked ADR
- No perfectionism — a rough ADR written in 20 minutes beats a perfect one that never gets written
- Reference them in code review — "this violates ADR 0003, here's the link"
The compounding return
Six months in, the value becomes obvious. When a new developer joins and asks "why do we do X this way?" — you have an answer. When you're about to make a decision that conflicts with a past one, you catch it. When you're debugging something weird, the decision log is a map.
The investment is small. The return is compounding. Start your ADR log today.