Novus Stream Solutions

2026 · Novus Stream Solutions (hub)About 13 min readNovus Stream Solutions

Documenting decisions: the ten-line ADR that saves future you

Six months from now I will open a file, wonder why I built it that way, and burn an evening reconstructing a decision I already made once. Architecture decision records fix that, and the solo version costs ten lines. Here is the template I use, when a decision earns one, and why the records live next to the code.

A ten-line decision record passing along a timeline from a developer writing it at decision time to the same developer reading it months later inside a code repository
Contents
  1. 1.Overview
  2. 2.What an ADR is when the whole team is you
  3. 3.The ten-line template
  4. 4.The threshold: which decisions deserve a record
  5. 5.Past you is the cheapest teammate you will ever hire
  6. 6.Keep the records next to the code
  7. 7.The five-minute habit
  8. 8.What a year of records taught me

Overview

The most expensive arguments I have are with a man who no longer exists: the me of eight months ago, who chose a library, structured a module, or ripped out a feature for reasons that were surely excellent and are now completely gone. I reconstruct his thinking from commit messages that say "fix" and from the code itself, which shows what he did but never why. On a team, someone else might remember. Alone, the memory layer is me, and it turns out I am a lossy medium. The fix costs ten lines per decision, and after two years of writing them I consider those lines the highest-leverage documentation in the repository.

Architecture decision records have a reputation as big-team ceremony — a form you fill in so that forty engineers stop relitigating the database choice in every sprint. That framing convinced me for years that they were not for me, since I had nobody to align. The premise was wrong. An ADR is not really a communication device between people; it is a communication device across time, and a solo developer crosses more time alone than anyone. Every project older than six months contains decisions whose context has evaporated, and the person most likely to curse the missing context is not a hypothetical hire. It is you, on a Tuesday, mid-refactor, with the old tab of reasoning long closed.

So this is the solo version, stripped of everything that only made sense with an audience: a ten-line template you can fill in five minutes, an honest threshold for which decisions deserve one, the argument for keeping the records in the repo next to the code they explain, and the writing habits that made the practice survive contact with real weeks. I will also show what a year of accumulated records revealed about my own decision-making, because the log turned out to be a mirror as much as a reference.

What an ADR is when the whole team is you

The format comes from a 2011 blog post by Michael Nygard, and the original is already refreshingly small: one short file per architecturally significant decision, stating the context you were in, the decision you made, and the consequences you accepted. No diagrams required, no approval workflow, no template with eleven mandatory headings. The file is written once, at the time of the decision, and then left alone as a historical fact. Teams adopted it because it ended circular debates; I adopted it because it ended something lonelier — the slow corrosion of knowing my own codebase, where every year a larger fraction of the design existed for reasons I could no longer state.

Solo, two properties of the format change meaning. First, the audience shifts from "colleagues who disagree" to "me, later, with no memory," which raises the bar for honesty and lowers it for polish. Nobody is going to judge the prose, so the record can say the true thing: I chose this because it was Sunday night and the alternative needed a week I did not have. That sentence is embarrassing in a team wiki and priceless in a personal log, because the mitigation for a time-pressured decision is different from the mitigation for a considered one.

Second, the record is append-only in a way documentation never is. Ordinary docs describe the current state of the system, which means they rot the moment the system moves and silently lie thereafter. An ADR describes a moment: given what I knew in March, here is what I chose. That statement can never become false. When the decision is reversed, you do not edit the old record — you write a new one that supersedes it, and the chain of records becomes the only accurate history of the project’s thinking. The decision to run this blog as typed TypeScript objects instead of a CMS — the one I later wrote up in Code-as-content: why our blog is hundreds of TypeScript objects, not a CMS — is a three-record chain in my log, and reading it in order replays the whole evolution of the idea.

The ten-line template

Ten lines is not a poetic exaggeration; it is the literal budget, and the constraint is load-bearing. A template that invites paragraphs produces records that take twenty minutes, and records that take twenty minutes stop getting written by the third busy week. Ten lines fits on one screen, takes about five minutes, and — this matters more than it sounds — feels almost silly to skip. The format is a title, a date and status, two lines of context, two lines of decision, two lines of alternatives, and two lines of consequences with a revisit trigger. Everything else the heavyweight templates ask for is either recoverable from git or ceremony.

The context lines answer one question: what pressure was I under? Not the history of the module — the forces. "Ad revenue depends on page speed; the current gallery ships 400 KB of script" is context. The decision lines must contain the word because, and the clause after it is the entire point of the exercise. "Chose static rendering because the interactive version cost 300 ms on mid-range phones" survives; "chose static rendering" is just a fact I could have read from the code. When I audit my old records, the ones I am grateful for are the ones where the because clause captured something the diff never could.

Alternatives get two lines because rejected options are where the real information hides — future me does not just need to know what I picked, but what I already ruled out and on what evidence, so he does not spend an evening re-evaluating a library I benchmarked and discarded. The final lines state consequences honestly, including the bad ones I accepted on purpose, and end with a revisit trigger: a concrete condition under which this decision should be reconsidered, like "revisit if the content file count passes 500." A decision with a stated expiry condition ages into a scheduled review; a decision without one ages into folklore.

  • Line 1 — title, phrased as verb plus object: "Serve all image processing on-device."
  • Line 2 — date and status: proposed, accepted, or superseded-by with a record number.
  • Lines 3–4 — context: the two or three forces that made this a decision at all.
  • Lines 5–6 — the decision itself, containing the word "because" and the real reason after it.
  • Lines 7–8 — alternatives considered, with the one-clause reason each was rejected.
  • Lines 9–10 — consequences you accept, plus one concrete revisit trigger.

The threshold: which decisions deserve a record

Record everything and the habit dies in a week; record nothing and you have a diary of zero pages. The threshold I use is two questions. The surprise test: would a competent stranger reading this code six months from now be surprised by the choice, or ask why the obvious default was not taken? And the argument test: did I actually deliberate — hold two options in my head for more than an hour, read comparisons, sketch trade-offs? A decision that passes either test gets a record. A decision that passes both gets a careful one.

In practice that means my log contains things like: why the background remover has no user accounts, why every model runs in the browser instead of on a server, why the ad integration is one network and not a waterfall, why a whole product was retired while its store stayed live. It does not contain variable names, folder structures, or which testing library I picked, because none of those would surprise anyone and none were real deliberations. The archive stays small enough to actually re-read — about thirty records in two years — which is itself a feature. A decision log you cannot read end to end has quietly become documentation, with documentation’s failure modes.

One category earns automatic entry regardless of the tests: anything I decided not to do. Rejected features, retired surfaces, roads deliberately not taken. Code shows what exists; nothing in a repository naturally records what was removed on purpose and why, which is precisely the knowledge that evaporates hardest. Half of my records are "no" decisions, and they have prevented more wasted evenings than the "yes" records combined, because the strongest gravitational pull in a solo project is toward re-attempting your own abandoned ideas with the original counter-argument forgotten.

Past you is the cheapest teammate you will ever hire

The payoff arrives at retrieval moments, and they are more frequent than I expected. Before any refactor that touches an old module, I grep the ADR folder for its name and read whatever comes back — two minutes that routinely change the plan, because the refactor I was about to do often un-solves a problem the original design was quietly solving. During bug hunts, the records answer the eternal "is this behavior intentional?" question without archaeology. And when a shiny idea arrives at midnight, the folder is where I check whether I have already had this idea, tried it, and written down why it died.

A concrete save: last winter I sketched a "quick" plan to bring back a capability I had removed from one of the tools, convinced the removal had been overcautious. The record from the original decision listed three costs I had completely forgotten — one of them a support burden that had been eating hours weekly — and ended with a revisit trigger that explicitly had not fired. I closed the sketch in ten minutes instead of rediscovering the costs over a month. The same thing happened while writing up the reasoning behind Why we retired Novus Stream Tools: generic utilities that didn't earn their place: the record held details my narrative memory had already smoothed over.

There is also a payoff at write time, before any retrieval happens. Forcing the decision through the template is a comprehension check: if I cannot state the context in two lines, I do not understand the forces yet; if the because clause will not come, I have not actually decided — I have drifted into a default and am about to launder it as a choice. Several times the act of writing the record talked me out of the decision it was recording. Ten lines is short enough that this still counts as thinking, not paperwork.

Keep the records next to the code

Location decides whether the habit survives, and the answer is a folder in the repository — mine is docs/adr/, with files named 0001-serve-processing-on-device.md and counting upward. The records travel with every clone and branch, show up in the same editor I am already in, and cost nothing to search: the grep that starts every refactor covers code and decisions in one pass. When a decision changes inside a pull request, the superseding record rides the same diff, so the history of the code and the history of the reasoning cannot drift apart. Version control even dates everything for free.

Every away-from-the-repo alternative I tried leaked. Notion and wiki pages rot behind a login I am not in when I am coding; links to them break; nothing connects a page to the commit that implemented it; and a decision documented outside the repo is invisible at exactly the moment of maximum need, which is mid-review of the change that contradicts it. The pattern matches how I handle everything else in this operation — the whole site is content-as-code for the same reason — and the shipping process in How we ship and test small apps without a full team leans on the repo being the single place where truth lives.

One distinction worth keeping sharp: ADRs are internal memory, not public documentation. The user-facing pages under Documentation promise behavior — what the tools do, what the limits are — and get edited whenever behavior changes. The ADR folder records why the behavior is shaped that way and never gets edited at all. Blur the two and you get either public docs full of self-absorbed history or decision records sanded down for an audience. Keeping them in different places with different rules lets each be fully itself.

A ten-line architecture decision record file shown inside a repository tree, with a timeline arrow carrying it from the March decision to the same developer reading it in November
The whole practice: ten numbered lines, one folder in the repo, and a payoff that arrives months later at grep speed.

The five-minute habit

The record gets written in the same sitting as the decision — ideally in the minutes between deciding and implementing, and at worst before the merge. Freshness is not a nicety; it is the whole ballgame. The context lines are trivial to write while the pressure is still on your neck and quietly impossible three weeks later, when the decision has already begun rewriting itself in memory as more considered than it was. I keep a template.md in the ADR folder, so starting a record is copy, rename, fill. Any step heavier than that — a script, a form, a tool to install — I have watched kill the habit in other people’s repos.

I deliberately run no tooling around the folder. No linter checks the format, no CI job counts the lines, no index page is generated. The ten-line budget is a norm, not a law, and a record that runs to fourteen lines because the decision was genuinely hairy is fine. The moment the practice acquires enforcement, writing a record becomes a compliance task, and compliance tasks get batched, deferred, and gamed. The only mechanism is the number prefix on the filename, which exists so records sort chronologically and so a superseding record has something unambiguous to point at.

Supersession is the one rule I hold strictly: old records never get edited, not even to fix a wrong prediction. When a decision is reversed, a new record states the new context — usually "the revisit trigger from 0009 fired" — and the old file gets one line added to its status: superseded by 0023. The result is that reading the folder in order replays the project’s reasoning the way a commit log replays its code, mistakes preserved. The mistakes are the valuable part. A log that only contained the decisions I still agree with would teach me nothing.

What a year of records taught me

Somewhere past record twenty, the folder stopped being a reference and became a dataset. Reading it end to end, patterns emerged that no single entry showed. My worst decisions cluster late at night and carry confident language; my best ones cite a measurement within the first two lines. Every record whose context mentioned a deadline chose the more reversible option, and none of those were regretted. Two records in a row from last spring rejected the same library for different stated reasons, which told me the real reason was neither — something I only noticed because the records sat side by side.

The decision log pairs with the incident log the way a ledger pairs with a bank statement. My reliability practice from Error budgets for tiny teams: reliability without an SRE org produces six-line notes about what broke; the ADR folder holds ten-line notes about what was chosen; and cross-referencing them is where the operational learning actually lives, because a repeated incident frequently traces back to a specific record whose consequences section already predicted it. Prediction confirmed is a design validated; prediction missed is the cheapest possible tuition. Together the two files are the entire written memory of this operation, and they fit in less space than one sprint-planning document.

If a second contributor ever joins, the practice will need to grow — statuses that mean something during review, maybe real tooling like adr-tools, records written to persuade rather than merely to remember. I plan to resist most of it. The ten-line version works because its cost sits beneath the threshold where skipping is tempting, and every gram of added process moves it toward the fate of all heavyweight documentation, which is to be admired and unwritten. Start with ten lines and a folder. Past you has been trying to send you notes for years; this is just finally handing him a pen.

Frequently asked questions

Quick answers to common questions about this topic.

What is an architecture decision record?

A short file, written at the moment of an architecturally significant decision, that records the context you were in, the choice you made and why, the alternatives you rejected, and the consequences you accepted. The format comes from Michael Nygard’s 2011 essay and deliberately stays small — my version is ten lines. Unlike ordinary documentation, which describes current state and rots as the system changes, an ADR describes a moment in time, so it never becomes false; when a decision is reversed you write a new record that supersedes the old one.

Are ADRs worth it for a solo developer?

More than for a team, in my experience, because a team has redundant memory and a solo developer has none. Every question a colleague would normally answer — why is there no login? why this library? — lands on you, months later, with the context gone. Ten lines at decision time costs five minutes; reconstructing a decision from commits and code costs an evening and often gets the answer wrong. The records also pay off before any retrieval: writing the "because" clause is a check that you actually decided rather than drifted into a default.

Which decisions deserve an ADR and which do not?

Use two tests. The surprise test: would a competent stranger reading the code ask why the obvious default was not taken? The argument test: did you genuinely deliberate between options for more than an hour? Either passing earns a record. Decisions touching data, money, security, or user trust qualify almost automatically, and anything you decided not to do — removed features, rejected roads — deserves one regardless, because negative decisions are the knowledge a codebase preserves worst. Skip variable names, folder layouts, and anything you would redo identically without thought.

Where should ADRs be stored?

In the repository, next to the code they explain — a docs/adr/ folder of numbered markdown files works. The records then travel with every clone, appear in the editor you already work in, get dated by version control, and are covered by the same grep you run before a refactor. Wikis and external tools put the records behind a login you are not in while coding, break links over time, and hide the reasoning at the moment of maximum need: reviewing a change that contradicts it.

Should I edit an old ADR when the decision changes?

No — supersede it. Add one status line to the old record pointing at the new one, and write a new record explaining the new context, ideally noting which revisit trigger fired. Editing old records destroys the property that makes them trustworthy: each is a true statement about what you knew and chose at a specific time. The chain of superseded records, mistakes intact, is the actual history of the project’s thinking, and the mistakes are the most instructive entries in it.