Design docs and ADRs
Why this matters
Staff engineers write. Not code — designs, decisions, post-mortems. The Staff job is half writing. Your influence at scale comes from documents that propagate through the org: design docs that align teams, ADRs that record decisions, post-mortems that change practices.
Most SDE2s don't write design docs except when forced. Most Staff engineers write them as the first step of any non-trivial project. The doc is the design — once it's clear in writing, the implementation follows almost mechanically.
This isn't a "soft skill" in the dismissive sense. It's the technical skill of converting fuzzy intent into clear specification, making tradeoffs explicit, and leaving a durable artifact.
What a design doc is for
- Forcing clarity: writing the design exposes hidden assumptions and unresolved questions. Many "we'll figure it out later" issues surface during writing.
- Alignment: stakeholders (other engineers, PM, ops, security) read and agree before you spend weeks building.
- Record: future engineers asking "why is this the way it is" find the doc. Reduces archaeological work.
- Review: senior engineers can catch fatal flaws before you've committed code.
The standard design doc structure
1. Title and metadata
Title: [Service / Feature / System Name] Design Author(s): [you] Status: Draft | In Review | Approved | Implemented | Superseded Last updated: 2026-05-16 Reviewers: [list]
2. Context (why are we doing this?)
What's the current state of the world? What's the problem? Why now? Why us? This grounds the rest of the document. Without good context, reviewers don't know what they're evaluating.
Bad context: "We need a notification service."
Good context: "Today, every product team builds its own notification logic. Five teams have built duplicate retry / dedup / templating systems. We've had three outages this quarter from notification bugs. Engineering leadership has asked the platform team to build a shared service. This doc proposes the design."
3. Goals
What this design does. Each goal should be specific and measurable where possible.
Good goals:
- Provide a unified API for sending email, SMS, push notifications, and in-app messages
- Support 10K notifications/sec at peak
- Guarantee at-least-once delivery (consumer idempotency required)
- Provide observability: delivery success rate, latency by channel, per-tenant breakdown
4. Non-goals
The most important section. What we're explicitly NOT solving. Prevents scope creep. Tells reviewers what to skip when they assume otherwise.
Good non-goals:
- This is not a marketing automation tool (no audience segmentation, A/B testing of message content)
- This is not a chat / messaging service (no real-time delivery; latency budget is > 1 second)
- This will not handle voice calls
- Not in scope for v1: webhook delivery (Phase 2)
5. Design
The meat. What you're building. Sufficient detail that another engineer could implement it. Subsections typically:
- High-level architecture with diagram
- Data model — schemas, key data flows
- API surface — what callers use
- Component design — each major service / module
- Operational concerns — deployment, configuration, observability
6. Alternatives considered
The section that separates Staff from senior. List the other approaches you considered. For each:
- What it was
- Why you didn't pick it
- Under what circumstances it might have been better
Sample alternatives for the notification-service example:
- Buy SendGrid / Twilio for everything: rejected because of cost at our scale and lack of cross-channel coordination.
- Each team continues building their own: rejected because of duplication and outage history.
- Build a thin wrapper around providers, no async processing: rejected because we need retry/dedup/batching.
- Build a full event-sourced notification platform: rejected as over-engineered for v1; mentioned as future evolution.
Without "alternatives considered," your doc looks like you didn't think about it. With it, your doc demonstrates Staff judgment.
7. Risks & mitigations
What can go wrong, and what you're doing about it.
| Risk | Severity | Mitigation |
|---|---|---|
| Provider outage (SendGrid down) | High | Multi-provider failover with health checks |
| Notification queue backup during incident | Medium | Per-priority queues; shed low-priority on overload |
| Duplicate notifications confusing users | Medium | Idempotency keys; consumer-side dedup |
8. Rollout plan
How you'll ship this incrementally and what milestones look like.
- M1: API deployed, single channel (email), 1 team migrated
- M2: Multi-channel support, 3 teams migrated
- M3: All teams migrated, old code removed
- M4: Production-ready (SLO defined, alerts in place)
9. Open questions
Honest declaration of what you haven't figured out. This is OK. Better to call out unknowns than to pretend you have all answers.
10. Appendix
Supporting material: detailed schemas, benchmark data, related links.
Anti-patterns in design docs
- No non-goals: scope creeps in review. Every reviewer adds requirements.
- No alternatives considered: looks like you only thought of one option.
- Too high-level: "we'll use a queue and workers" doesn't help anyone.
- Too low-level: 50 pages of class diagrams; reviewers tune out.
- Missing risks: looks like you're hiding problems.
- No rollout plan: nobody knows how to validate or what to expect.
- Too long: keep to ~5-10 pages for a typical project. If longer, break into multiple docs.
Architecture Decision Records (ADRs)
Lighter-weight than design docs. A few paragraphs per decision, lived in the repo alongside code. Future engineers find them when asking "why did we do it this way?"
ADR format (Michael Nygard's)
# ADR 015: Use Postgres logical replication for cross-region read replicas ## Status Accepted - 2026-05-16 ## Context We need to provide low-latency reads in EU for our US-based application. Latency from EU to US is 90ms; reads from app servers in EU should be under 50ms total. Options included streaming replication, logical replication, application-level dual-writes, and a Cloud SQL cross-region read replica. ## Decision Use Postgres logical replication from us-east-1 primary to eu-west-1 replica. Application servers in EU route reads to the local replica; writes route to the US primary. ## Consequences + Reads from EU complete in ~20ms (local replica) + Writes from EU users go cross-region (~90ms latency) — acceptable given EU traffic is read-heavy + Replication lag typically <500ms; we accept stale reads for non- critical paths - Operational complexity of managing logical replication slots - Schema changes require coordination (don't break replication) - If primary fails, EU is read-only until failover to a new primary ## Alternatives considered - Streaming replication: simpler but couples versions; harder to filter tables - Multi-master active-active: too complex for our team; conflict resolution risks correctness - Cloud SQL cross-region replica: tied to managed service; less control over replication mechanics
ADRs accumulate in docs/adr/ in the repo. Numbered sequentially. Never edited after accepted (a new ADR supersedes it). The history is the value.
Post-mortems as a kind of doc
Post-mortems are doc artifacts too. The blameless-postmortem structure (covered in SRE chapter) applies. Treat post-mortems as first-class artifacts: archived, searchable, referenced when similar incidents occur.
How to actually write better docs
- Start with the alternatives. Write that section first. It forces you to think about the option space before locking in.
- Write the non-goals second. What are you NOT doing? This frees you from defensive over-scoping.
- Write the goals third. Concrete and measurable.
- Sketch the design. Diagrams first, then prose.
- Iterate based on questions. Share early. Each question reveals where the doc is weak.
- Length: 5-10 pages for a typical project. If it's too long, split. If it's too short, you're probably hand-waving.
- Always have a rollout plan. No design is complete without "how we ship it."
The cultural element
Writing culture is contagious. If your team doesn't write design docs, start. Write yours; review others'; mentor juniors through writing their own. After a few months of consistent practice, the team's collective output improves dramatically because everyone is forced to clarify before they code.
Conversely: be patient. The first design doc takes 4 hours and produces mediocre output. The tenth takes 2 hours and produces great output. Build the muscle.
Further reading
- Gergely Orosz: Scaling Engineering Teams via Writing Things Down — overview of how serious companies use design docs.
- Design Docs at Google by Malte Ubl — what Google's culture looks like.
- ADR templates by Joel Parker Henderson
- Michael Nygard: Documenting Architecture Decisions — the original ADR post.
- ADR organization site — templates, examples.
- Triggers for better design docs
- StaffEng: Writing an engineering strategy — when design docs aggregate into strategy.
- Book: The Staff Engineer's Path by Tanya Reilly — chapter on writing.
- Book: Staff Engineer: Leadership beyond the management track by Will Larson.