Skip to content
ExponaBLOG
ENGINEERING CRAFT · DAY 093 / 100

Why I document everything: practical tips and trade-offs

My memory is bad. My docs are not.

Expona Admin6 min read

Why I document everything

My memory is terrible. I've forgotten production incidents, architectural decisions, and the exact reason we chose PostgreSQL over MongoDB for a critical service. But my documentation is not. After 5.5 years of building platforms where mistakes compound into outages, I learned that the only reliable system in a team is one where critical knowledge lives outside people's heads. Why I document everything isn't about perfection—it's about survival.

Decision records capture the why

Six months ago, we migrated our payment service from a synchronous HTTP call to an async Kafka pipeline. The migration worked beautifully. Then someone new joined and asked: "Why didn't we just add a queue library on top of the existing API?" Good question. And I had no answer in my head—only in my decision record.

Decision records aren't fancy. I use a simple ADR (Architecture Decision Record) format: context, decision, consequences, and alternatives considered. Here's a real example from a trade-matching system I built:

typescript

/*
  ADR-012: Use Redis for order book state instead of in-memory HashMap

  Context:
  - Matching engine processes ~50k orders/minute
  - Previous in-memory solution lost state on restarts
  - Multiple engine instances need consistent view of order book

  Decision:
  - Store active orders in Redis with expiry
  - Publish state changes to Kafka for audit trail
  - Keep hot cache in-memory with Redis as source of truth

  Consequences:
  - +15ms latency per match (acceptable, matched with requirements)
  - Need Redis cluster ops expertise
  - Can now scale horizontally

  Alternatives rejected:
  - PostgreSQL: too slow for this access pattern
  - Just make in-memory persistent: still can't coordinate across instances
*/

Without this, the next person debugging a state inconsistency issue will rebuild the entire reasoning. With it, they understand the tradeoffs immediately. They know why we tolerate that 15ms latency spike. They know what we were trying to solve.

I've seen teams burn weeks re-litigating decisions that were already made and rejected for solid reasons. Decision records kill that waste.

Runbooks turn incidents into checklists

At 3 AM, your Kafka cluster is degraded. Memory usage hit 92%. Your on-call engineer is groggy. This is not the time to think. This is the time to follow a checklist.

A runbook is a decision record's practical sibling. It captures how we've successfully recovered from a known problem before. Here's what I documented for a recent Redis memory spike in our ride-hailing platform:

typescript

Runbook: Redis Memory Usage Above 85%

1. Check current memory state
   redis-cli INFO memory | grep used_memory_human

2. Identify largest keys
   redis-cli --bigkeys (run for 30 seconds max)

3. Quick wins (do these first, takes ~2 min):
   - FLUSHDB for expired driver locations (safe: has 5 min TTL anyway)
   - Check if any bulk imports are running: SELECT 5; DBSIZE
   
4. If memory still >80%:
   - Scale up Redis instance (pre-warmed replica available)
   - Set maxmemory-policy to allkeys-lru (temporary)
   - Notify backend team to pause non-critical cache writes

5. Post-incident:
   - Adjust SCAN cursor batch size (was too aggressive)
   - Alert threshold should be 70%, not 85%
   - Update TTL policy for driver locations from 5m to 3m

Slack channel: #incident-redis
PagerDuty escalation: Check on-call rotation
Estimated time to resolution: 8 minutes (based on 3 historical incidents)

The first time we hit this, it took 40 minutes and three context switches between team members. The second time, with the runbook, it was 7 minutes. The cognitive load dropped to almost zero. We followed steps. We recovered. We moved on.

Every incident teaches you something. The runbook is how you teach that lesson to your future self and your team.

Onboarding gets faster for everyone

I onboarded four new engineers into a legacy CRM platform in the last year. Without documentation, each would spend two weeks asking questions about why we structured microservices the way we did, what the deployment pipeline looks like, and where the API contracts live.

With documentation, they had answers within hours. They could read a runbook about "First Deploy to Staging" and do it solo. They could check the architecture decision log and understand why we split the contact service from the billing service.

Better onboarding means less interruption for existing team members. It means new engineers contribute value faster. It means you're not answering the same question about Redis connection pooling for the fifth time in a year.

I keep a simple onboarding checklist that covers:

  • Architecture overview (what services exist, data flow diagram)
  • Local setup (Docker Compose, environment variables, database seeding)
  • First deploy checklist (staging only, includes rollback steps)
  • Key runbooks (common incidents, database migrations, cache invalidation)
  • Decision records (why we chose NestJS, why we use PostgreSQL, why we split services)
  • On-call handoff (what to monitor, who to escalate to)

A well-documented system is an onboarding multiplier. It's the difference between "ask the person who knows" and "check the wiki."

Writing exposes gaps in understanding

Here's the uncomfortable truth: I don't always understand why we built something a certain way until I try to document it.

Last year, I started documenting our event-sourcing approach in a financial trading platform. I knew it worked. I knew it gave us audit trails and replay capabilities. But when I sat down to write it, I couldn't clearly explain when to use event sourcing versus regular updates.

That friction revealed a gap. I didn't truly understand the tradeoffs. So I dug deeper: benchmarked append-only writes against update queries, measured storage overhead, calculated the cost of replaying events from year-old snapshots.

Writing forced me to think rigorously. That rigor made me a better architect.

When you write documentation and it feels awkward, that's a signal. It means:

  • You don't fully understand the thing
  • The thing might be poorly designed
  • Or both

I've caught bugs, architectural flaws, and configuration errors just by trying to document them clearly. The act of writing is a form of code review for your decisions.

Common mistakes

Writing docs nobody reads. Documentation that lives in a wiki nobody opens is waste. Keep docs where people actually look: in the repo README, in runbooks linked from your monitoring dashboard, in ADRs in the code commit history itself.

Documenting without updating. A runbook that's wrong is worse than no runbook. When you fix an incident, update the docs immediately. Build a culture where "update the runbook" is the first post-incident step, not an afterthought.

Over-documenting. Not everything needs a 10-page architecture document. A one-page decision record with context and tradeoffs is often enough. Documentation should be useful, not a resume-building exercise.

Documenting code that's still changing. Don't document the implementation details of a feature you're building this week. Wait until it's stable. Document the *why* from day one. Document the *how* after you're confident in it.

Key takeaways

  • Decision records (ADRs) capture the reasoning behind architectural choices, saving future teams from repeating the same deliberation.
  • Runbooks turn learned lessons from incidents into repeatable checklists, reducing MTTR and cognitive load during emergencies.
  • Good documentation accelerates onboarding dramatically by replacing "ask someone who knows" with "check the docs."
  • Writing forces clarity; if you can't document something clearly, you don't understand it deeply enough.
  • Keep documentation close to where it's used: in repos, in dashboards, linked from alerts—not in a wiki that nobody opens.
  • Update docs when you learn something new, especially after incidents. Documentation is a living system, not a one-time artifact.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles