Reza Golkhandani // Senior Software Engineer | Backend platforms
How Thirty-Four Decision Records Became a Platform's Engineering Conventions
Architecture | Team conventions | Documentation
How Thirty-Four Decision Records Became a Platform's Engineering Conventions
The goal
When I joined the platform, conventions lived in people's heads. Three ways to open a transaction, two error formats, authorization checks wherever the last person had put them. The team was small and fast, and the goal was to keep the speed while giving it a shared shape: one way to do each thing, written down, enforced.
The approach
Architecture decision records, one page each: context, options, choice, consequences. Written in the twenty minutes while the decision is fresh. And a rule for myself: every record that shapes code gets paired with something mechanical that enforces it, so nobody has to remember it.
What I built
Thirty-four records over the year. The ones that reshaped the codebase:
- One request pipeline. Authentication, authorization, validation, unit of work, error mapping, in that order, for every route and action. There is no other door.
- Controlled transactions. The pipeline opens the unit of work and hands it to feature code, which never begins its own.
- Typed errors. A small library with stable codes, HTTP statuses, and messages written per audience.
- Durable side effects. Anything leaving the process goes through an outbox.
- Authorization by relationship. Permissions as relationships between people and objects, with a convention for how each screen and endpoint declares what it needs, and role guides for the team.
Each is paired with a mechanism: a scaffolding skill that generates the right shape, a lint rule that rejects the wrong one, or a shared type that makes the wrong one fail to compile.
The result
Review threads shortened from "why this way" to "does not match record twelve". New engineers, and new agent sessions, start with the records instead of a tour. About a third of the records were superseded within the year, on purpose, which is what a living set of decisions looks like.
Takeaways
- Write the record when a decision constrains other people or is expensive to unwind. Otherwise just do it.
- A record without a mechanism decays. Pair every one with a generator, a lint rule, or a type.
- Superseding a record is a feature. It means the team changed its mind deliberately, once.