Case Study 2 — The ADR That Saved Six Months: Documenting the Why
Where Case Study 1 rebuilt a front door, this one looks at the quietest and most under-written developer document: the Architecture Decision Record. It contrasts a real-feeling failure—a significant decision that lived only in people's heads—with the one-page ADR that would have prevented months of churn. The team and project are composites; the pattern is one every engineering organization repeats.
The decision nobody wrote down
A payments team at a mid-sized company made a consequential call early in a project: store user sessions in Redis (an in-memory store) rather than in their primary Postgres database. The reasoning, at the time, was sound and specific. Postgres session writes were causing lock contention under load—every request touched the sessions table, and the write traffic was serializing behind locks. Redis, being in-memory and built for exactly this read-heavy, high-churn access pattern, eliminated the contention. The team knew the trade-offs: sessions wouldn't survive a Redis restart unless persistence was configured, and Redis was one more piece of infrastructure to run and monitor. They weighed it, chose Redis, and moved on.
They moved on without writing it down. The decision lived in a Slack thread that scrolled into oblivion and in the memories of the three engineers in the room.
Six months later
Two of those three engineers had changed teams. A new senior engineer, reviewing the architecture, saw sessions in Redis and Postgres as the main database and reached the natural conclusion: this is needless complexity. Why run a second data store for sessions when Postgres is right there? She wrote a well-argued proposal to consolidate sessions back into Postgres, "simplifying the stack and removing an operational dependency."
It was a good proposal—by someone who didn't know she was proposing to walk straight back into the lock-contention wall the team had escaped six months earlier. The code showed her what (sessions are in Redis); it could not show her why (because Postgres melted under the write load). She had no way to know the team had started in Postgres and fled it for a concrete, measured reason.
What followed was the avoidable cost: a week of meetings, two engineers digging through old metrics dashboards to reconstruct the original reasoning, and a near-miss where the change was nearly approved before someone who'd been in the original room happened to see it and said, "Wait—we tried that, it doesn't work." The reasoning was eventually recovered. But it was recovered the expensive way: from human memory, by luck, after wasted effort.
What the ADR would have done
Here is the document that would have ended the whole episode in five minutes—a single page, written the day the decision was made:
# ADR 0011: Store user sessions in Redis, not Postgres
**Status:** Accepted (2023-09-04)
## Context
Every authenticated request reads and writes the user's session. With sessions
in the primary Postgres database, this created severe lock contention on the
`sessions` table under load: write traffic serialized behind row locks, and p99
request latency rose sharply above ~2,000 concurrent sessions. The access
pattern is high-churn, read-heavy, and short-lived—a poor fit for a relational
table and a good fit for an in-memory store.
## Decision
Store sessions in **Redis**, accessed by session ID, with a TTL matching the
session lifetime. Postgres remains the primary store for all durable data.
## Consequences
**Positive:**
- Eliminates the lock contention; session reads/writes no longer touch Postgres.
- Latency under load drops back to baseline; the system scales past the prior ceiling.
- TTL-based expiry handles session cleanup for free.
**Negative:**
- Sessions are not durable across a Redis restart unless persistence (AOF/RDB)
is configured. Accepted: a lost session means a re-login, not data loss.
- One more piece of infrastructure to run, monitor, and secure. Accepted:
worth it for the scaling headroom.
**Revisit if:** session data ever needs to be durable/auditable, or the
operational cost of Redis outweighs the contention it solved.
When the new engineer opened the codebase, this ADR would have been sitting in docs/adr/, surfacing in her review. Her proposal to consolidate into Postgres would have met its answer before she wrote a word of it: the Context section names the exact problem she'd be reintroducing (lock contention above ~2,000 concurrent sessions), and the Consequences section shows the trade-offs the team knowingly accepted. She'd either drop the idea or—better—make a genuinely new argument ("we've since moved to connection pooling that changes the contention math"), informed rather than blind.
What this case teaches
Three things, each a principle from §25.5:
- The code shows the what; only the ADR preserves the why. No amount of clean code or good naming could have told the new engineer that Postgres had been tried and abandoned. That knowledge is unrecoverable from the artifact—it exists only if someone writes it down.
- Record the rejected alternative and the costs, not just the choice. The ADR's power is in the Context (Postgres was tried; here's why it failed) and the honest Consequences (here's what Redis costs us). A bare "we use Redis for sessions" would not have stopped the proposal; the reasoning did.
- Write it the day you decide. The original reasoning was recoverable six months later, but only by luck and labor. The day of the decision, the context was fresh, the alternatives were in everyone's head, and the trade-offs were actively being argued. That is the one moment the ADR is cheap to write—and the brevity (one page) is exactly what makes the habit survivable.
The ADR is "comment the why, not the what" (Chapter 24) promoted to the scale of architecture. The most expensive knowledge on any software team is the reasoning behind its decisions, and it is the knowledge most reliably lost. A page, written once, keeps it.
Try it yourself: Think of one decision on a current or past project whose why lives only in someone's memory—a framework chosen over an obvious alternative, a pattern that looks like over-engineering but isn't, a library deliberately not used. Write its ADR: Context (what forced it, what you weighed), Decision, Consequences (including the costs you accepted). One page. Notice how much of the "why" would have evaporated if you'd waited another year.
Back to: Chapter 25 · Case Study 1 · Key Takeaways