A guide to writing engineering design documents that actually drive alignment — what goes in them, why each section exists, how reviewers read them, the social dynamics no one talks about, how to think through trade-offs that signal seniority, and the writing process that produces good docs. For engineers who want intuition, not templates.
A design doc is three things at once: a thinking tool that forces clarity before code, a persuasion artifact that builds consensus, and a decision record that explains why things were built the way they were. The doc is the medium — the real output is aligned understanding across everyone who needs to say yes.
If someone joins your team 6 months after the project ships and reads only the design doc, they should understand: what problem was solved, what approaches were considered, why this one was chosen, and what trade-offs were accepted. If your doc doesn't pass this test, it's incomplete.
Good docs maximize decisions per page. Bad docs maximize words per page. Every paragraph should do one of three things: frame a decision, present evidence for a decision, or record a decision. Paragraphs that do none of these should be cut. This single heuristic explains why "The Novel" anti-pattern fails — 20 pages with 4 decisions is worse than 4 pages with 4 decisions. When editing your doc, ask of every paragraph: "which decision does this serve?" If you can't answer, delete it.
You don't need one for: bug fixes with obvious solutions, refactors that don't change behavior or interfaces, features where the implementation path is well-established and uncontroversial, or changes with blast radius limited to a single file. The test: is there a genuine decision to be made, and does more than one person need to agree on it? If no, a CL description suffices. Over-documenting erodes trust — people stop reading carefully when most docs didn't need to exist.
Design docs sit between "what should we build?" (product) and "how exactly does the code work?" (implementation). Confusing a design doc with adjacent artifacts is one of the most common mistakes.
| Artifact | Answers | Audience | Owned By |
|---|---|---|---|
| PRD | What should we build and why does the user want it? | PM, eng, design, leadership | Product Manager |
| Design Doc | How should we build it technically, and why this approach over alternatives? | Engineers, TL, cross-team | Engineer (you) |
| RFC | Should we adopt this standard/practice/migration org-wide? | Broad engineering org | Senior eng / TLM |
| Tech Spec | What are the exact APIs, schemas, and implementation details? | Implementing engineers | Engineer |
| Postmortem | What went wrong, why, and how do we prevent it? | Team + incident reviewers | On-call / incident lead |
A design doc should be readable without the PRD but reference it. It should make the tech spec nearly mechanical to write — if someone reads your design doc and still can't predict what the tech spec will say, your doc is too abstract. The design doc is the "why this approach" layer between "what to build" and "the exact code."
Not all sections are created equal. Reviewers spend disproportionate time on certain sections — and the sections that take the most writing time are often not the ones that carry the most value.
| Section | Purpose | Weight | Common Mistake |
|---|---|---|---|
| Title & Metadata | Author, reviewers, status, date. Sets scope expectations. | Low | Missing reviewer list — ambiguous ownership |
| Context & Problem | Why now? What's broken? Best docs quantify the pain with data. | High | Jumping to solution without establishing pain |
| Goals & Non-Goals | Scope boundaries. Non-goals are as important as goals — they prevent scope creep. | Very High | Vague goals that can't be evaluated post-launch |
| Proposed Solution | Architecture, data models, APIs, flows. Detail should match project complexity. | Critical | Too much code-level detail, not enough architecture |
| Alternatives | What else could we do? Why not those? Proves you explored the solution space. | Critical | Token alternatives never seriously evaluated |
| Trade-offs | What are we explicitly giving up? Latency vs cost, consistency vs availability. | Very High | Pretending the chosen approach has no downsides |
| Risks & Mitigations | What could go wrong? Technical, org, and dependency risks with concrete responses. | High | Listing risks without concrete mitigation plans |
| Milestones & Rollout | Phased delivery, feature flags, rollback criteria, success metrics, monitoring. | Medium | Big-bang launches with no incremental validation |
| Open Questions | Things you don't know yet. Focuses reviewer energy on what actually matters. | High | Omitting to appear more confident |
Good design docs almost always include at least one architecture diagram. A diagram compresses 500 words of system description into something a reviewer absorbs in 10 seconds. The best diagrams show data flow (what moves where), system boundaries (what's yours vs. external), and failure domains (where blast radius stops). If your doc describes interactions between 3+ systems and has no diagram, you're making reviewers work unnecessarily hard. A rough Excalidraw sketch beats a missing diagram every time.
The process matters as much as the structure. The most important work happens before the doc exists, and the first draft is always wrong in important ways.
The best design docs are pre-aligned. Before opening a blank document, have conversations with the 2–3 people whose opinions matter most: your TL, the person who'll review it most critically, and anyone whose system you're depending on. These conversations answer: "Am I solving the right problem? Is my general direction sane? Are there constraints I don't know about?" A 20-minute hallway conversation can prevent a week of review back-and-forth. If your TL is surprised by anything in the design doc, you skipped this step.
Pick reviewers who are skeptical of your approach, not cheerleaders — you want someone who'll find holes before the broad audience does. The 1–2 days this adds saves a week of back-and-forth later. At Google, this is often your TL or a senior peer on an adjacent team who understands the problem space.
Your first draft will be wrong in important ways — maybe your cost model is off, maybe you missed a dependency, maybe the alternatives are thin. That's normal. The best engineers treat early feedback not as criticism but as the design process working. A doc that goes through zero revisions either wasn't reviewed carefully or wasn't ambitious enough.
Most engineers write design docs in section order: context, goals, solution, alternatives. This is wrong. The writing order matters as much as the final structure — it shapes how you think.
Not the solution. Write 3–5 sentences about what's broken, who it affects, and why it matters now. If you can't do this without mentioning your proposed solution, you haven't separated the problem from the approach. Force yourself.
The moment your scope starts expanding in your head — "oh, we could also handle X" — write it as a non-goal. Do this throughout the drafting process, not at the end. Non-goals are live scope defense, not a post-hoc section.
This is counterintuitive but critical. If you write the solution first, your alternatives will be thin strawmen designed to lose. By exploring 3–4 approaches first, you often discover that your original idea isn't the best one — or you find a hybrid that's better than any single approach.
Keep a running list as you write. Every time you think "I'm not sure about this" or "I need to check with team X," capture it immediately. Don't wait until the end. The open questions section should be a curated version of notes you took during writing, not something you brainstorm after you're "done."
By this point, if you've done the problem framing, alternatives, and trade-off analysis properly, the solution section should almost write itself. It becomes "obviously, we chose Option A because..." rather than a standalone monolith you have to defend from scratch.
The difference between a mediocre and excellent design doc comes down to specificity. Every "weak" example below is something reviewers see weekly. Every "strong" example reflects real decision density.
Our current system is slow and we need to make it faster. Users have been complaining about performance.
P95 latency for /api/feed degraded from 120ms→840ms over 6 months as DAU grew 2M→8M. 23% of users on 3G connections experience timeouts. This correlates with a 12% drop in D7 retention for new users in SEA markets (dashboard: go/feed-perf).
Goal: Improve performance Goal: Better user experience Goal: Scalable architecture
Goal: P95 latency ≤200ms at 10M DAU Goal: Zero-downtime migration path Goal: ≤$500/mo incremental infra cost Non-goal: Redesigning feed ranking (separate effort, go/feed-ranking-q3) Non-goal: Supporting offline mode Non-goal: Backward compat with v1 API (deprecated, 0.3% of traffic)
We could use Redis but decided not to. We considered a rewrite but it would take too long.
Option A: Redis caching layer + Reduces DB reads by ~80% + Team has operational exp (3 yr) + Est: 6 weeks, 1 eng − Cache invalidation complexity − New operational dependency − $340/mo for r6g.xlarge cluster Option B: Read replicas + connection pool + Simpler architecture, no new deps + No cache coherence issues − Only ~3× throughput gain − Doesn't address serialization overhead − Est: 4 weeks, 1 eng Option C: Do nothing + vertical scaling + Zero eng time − Buys ~3 months at current growth − Monthly cost scales linearly with DAU Decision: Option A. 80% read reduction gives headroom for 2 years at projected growth. We accept invalidation complexity and mitigate via event-driven updates (§4.2). B was close but doesn't solve the serialization bottleneck driving 60% of current latency.
[Section omitted, or:] No open questions at this time.
1. Cache warming on deploy: cold cache → latency spike. Pre-warm from DB or accept first-request penalty? Need SRE input. (Owner: me, ETA 2/25) 2. Team X owns feed ranking — do they need API contract changes? Meeting scheduled 2/25. (Owner: me) 3. Cache hit rate instrumentation: per user segment or per endpoint? Affects dashboard design (§6.1). (Owner: @jsmith, ETA 3/1)
Trade-offs are the hardest section to write well and the single biggest gap between L4 and L5 docs. Most engineers either skip this section or write vague platitudes. Here's how to think through them systematically.
"We chose eventual consistency (30s TTL) over strong consistency because feed freshness ≤30s is acceptable per PM, and strong consistency would require a write-through cache that adds 4 weeks and doubles operational complexity." These are decisions — you had a choice and you made it with eyes open.
"We're accepting single-region deployment because multi-region is blocked by the billing team's migration timeline (Q4). This means a regional outage takes down the feed for all users." These aren't your choices — they're reality. Naming them explicitly prevents reviewers from thinking you missed them.
"We're not addressing the write amplification problem in this design. At current write volume (~200 QPS), it's manageable. At 2000 QPS (projected Q2 next year), we'll need a follow-up design. Tracked at go/feed-writes-followup." Time-boxing technical debt is L5 thinking.
You almost never have exact numbers. That's fine. What matters is order of magnitude. "This will cost somewhere between $200–500/month" is infinitely more useful than "this will have some cost." "Latency will increase by roughly 50–100ms" is better than "latency will increase slightly." Use back-of-envelope math, state your assumptions, and let reviewers challenge the assumptions rather than the absence of numbers.
Every trade-off can be expressed as: "We are choosing [thing A] over [thing B] because [quantified reason], and we accept [specific downside] which manifests as [concrete consequence]." If you can't fill in every blank, you haven't thought it through. If the "quantified reason" is just "it's better," you're not quantifying.
No one says this out loud, but design docs are political documents. They build consensus, manage expectations, and — at companies like Google — serve as primary artifacts for promotion. Understanding the persuasion layer makes your docs dramatically more effective.
Every good design doc follows: tension (a problem worth solving) → exploration (the solution space and trade-offs) → resolution (why this approach) → confidence (rollout plan and failure modes). The reader should feel the problem's weight before encountering the solution, understand why alternatives were rejected before reading the chosen approach, and feel confident in the rollback plan before approving.
"I understand the problem. I can see they explored the space thoroughly. The chosen approach makes sense given the constraints. I have one concern about failure mode X — oh, they addressed it in §5.3. I trust this person's judgment. LGTM."
"Why are we doing this? This feels like the solution was decided first and the doc was written to justify it. Where are the alternatives? This risk section is suspiciously empty. I have 14 comments and we're going to need at least two more rounds. This is going to take 3 weeks."
When a senior reviewer disagrees with your approach, the worst response is defensiveness. The best: "That's a good point — let me add Option D based on your suggestion and compare it explicitly." Treat feedback as the design process working, not as attack. If you genuinely believe your approach is right after incorporating feedback, state your reasoning clearly and escalate to the decision-maker (TL or area lead). Don't let unresolved disagreements rot — a doc in permanent "under review" is worse than no doc at all.
This happens. The move is: document both approaches explicitly in the alternatives section with honest trade-offs. Make it clear you understand both perspectives. Then state your recommendation with reasoning. Let the decision-maker decide. Your job as the doc author is to create clarity around the decision, not to win. If your doc clearly frames the decision such that either the TL or the staff engineer can point to the analysis and say "this is why we chose X," you've succeeded regardless of which option wins.
At Google, design docs are often the primary evidence of technical depth in promotion packets. Promo committees look for: problem framing that demonstrates understanding beyond your immediate scope, alternatives that show thorough exploration, trade-off analysis that proves mature judgment, and cross-team impact awareness. A well-written design doc for a medium-complexity project can be more compelling for L5 than a brilliant solution to a narrow problem that was never documented. Your doc is your artifact — treat it accordingly.
The bar shifts from "can you design a working system" to "do you demonstrate depth of reasoning about trade-offs, failure modes, and organizational impact." The radar below shows where the gap is widest.
The three biggest gaps: Alternatives Quality (L4 docs have 1 token alternative; L5 docs have 2–3 genuine ones with quantified comparison), Org Awareness (L4 treats the system in isolation; L5 acknowledges on-call burden, partner team capacity, migration cost), and Quantified Trade-offs (L4: "faster"; L5: "3× faster at $2.4K/month additional cost, payback in 6 weeks").
Instead of "Option A is faster," write "Option A reduces P95 by 3× but increases storage cost by $2.4K/month and adds 1 new operational dependency." Numbers — even order-of-magnitude estimates — enable actual decision-making.
Walk the data path and ask at every hop: "What if this returns garbage? What if this times out? What if this returns 10× the expected data?" Enumerate the top 5 failure modes with blast radius and recovery strategy. This is the skill reviewers look for most.
"This adds a new pager to team X's rotation." "This requires team Y to migrate by Q3 — confirmed capacity with their TL." Acknowledging the human and organizational cost of technical decisions is L5+ territory.
Distinguish one-way doors (schema changes, public API contracts, data deletion) from two-way doors (internal implementation, feature flags). Call out which decisions are irreversible. Spend review energy proportional to reversibility difficulty.
"We will address X in a follow-up, tracked at go/feed-v2-followups." Explicitly deferring work shows you can resist scope creep. Non-goals are your strongest tool — they prove you know the boundaries.
What metrics ship with the feature? What SLOs are defined? What does the monitoring dashboard look like? Monitoring as afterthought is L4. Monitoring as integral design — with alert thresholds and escalation policy — is L5+.
Patterns that consistently produce docs that fail to drive alignment, waste reviewer time, or rot without resolution. If a reviewer has seen one, they've seen a hundred.
Reads like a code walkthrough — method signatures, class hierarchies, pseudocode. Design docs describe what and why, not how at the code level. Implementation belongs in code comments and tech specs.
Written after the code is already done to satisfy process. Reviewers always detect this — the alternatives feel performative and there are zero genuine open questions. Destroys trust in the review process for everyone.
20 pages when 5 would do. Low decision density. Buries critical choices in noise. Reviewers skim or abandon it entirely. If you can't express the core design in 2 pages, you don't understand it yet.
Conspicuously avoids the elephant in the room — the migration risk, the SPOF, the flaky upstream. Reviewers always find it. Better to name it yourself with a mitigation than to have it surfaced as a "blocking concern."
Only the chosen solution, no alternatives. Signals tunnel vision or retroactive documentation. Even when the answer is "obvious," showing you considered alternatives builds reviewer confidence in your judgment.
Starts as a caching layer, ends up redesigning the data model, the API, and the deployment pipeline. Scope creep in the doc predicts scope creep in implementation. Aggressive non-goals are your defense.
Approved but never updated as implementation diverges from design. Six months later the doc is actively misleading. Add a "Status" field at the top and update it when reality changes. A doc marked "SUPERSEDED — see go/feed-v3" is better than a stale doc treated as truth.
Good reviewing is a skill distinct from good writing. The goal is to improve the design, not to demonstrate your own expertise or rewrite the doc in your image.
1. Is the problem clearly defined and worth solving at this priority?
2. Would the alternatives actually change my mind about the approach?
3. What's the worst failure mode and is it explicitly addressed?
4. Can this be built and rolled out incrementally, with rollback criteria?
5. What's missing that the author might not realize is missing?
"The best design review comment isn't 'I would do it differently.' It's 'What happens when X fails at 3am on a Saturday?'"
— Common wisdom across Google, Stripe, and Meta eng orgs
Not all comments are equal. Blocking concerns (usually prefixed with "blocking:" or stated as "I can't approve until...") require resolution before approval. Strong suggestions ("I think you should consider...") are worth serious engagement. Nits ("optional: you could also...") can be addressed or acknowledged without changing anything. When you get 20 comments, triage first — answer the 3 blocking ones thoroughly, batch the nits, and don't let volume overwhelm your judgment about what matters.
As of early 2026, AI coding tools are reshaping how design docs get written. Used well, they accelerate the hardest parts. Used poorly, they produce confident-sounding docs that don't actually think.
"Here's my problem and constraints. Generate 5 genuinely different approaches with trade-offs for each." AI excels at expanding solution spaces — it suggests approaches you didn't consider, which you then evaluate with your domain knowledge.
"Here's my proposed architecture. What are the 10 most likely failure modes and their blast radius?" Systematic enumeration of edge cases is exactly the kind of thinking that separates L4 from L5 docs.
Dictate rough thinking, then use AI to structure it into sections. Especially effective for Context/Problem — talk through pain points, let AI organize them into a coherent narrative with data references.
AI can enumerate options and trade-offs, but choosing requires judgment about your team's capacity, org politics, technical debt history, and risk tolerance. AI doesn't have your context.
"Write me a design doc for adding Redis" produces exactly the kind of retroactive, no-genuine-alternatives doc that kills reviewer trust. Use AI to think harder, not to avoid thinking.
AI generates plausible-sounding latency estimates and cost projections. Always verify quantitative claims. A doc with fabricated numbers is worse than one with honest "TBD — need to benchmark" notes.
Calibrate to blast radius. If the change touches 1 team, 1–5 pages. If it touches 3+ teams, 5–10+. If it could page someone at 3am who isn't on your team, it definitely needs a doc.
| Scope | Example | Length | Reviewers | Timeline |
|---|---|---|---|---|
| S | New API endpoint, schema migration | 0.5–1 pg | 1–2 peers | 1–2 days |
| M | New service, caching layer, auth overhaul | 2–5 pg | 3–5 incl. TL | 1–2 wk |
| L | Data pipeline redesign, multi-team feature | 5–10 pg | 5–10, x-team | 2–4 wk |
| XL | Platform migration, infra overhaul, new storage system | 10–20+ pg | 10+, leadership | 4–8+ wk |
Run through this before the doc goes to the broad reviewer list. Each item maps to a failure mode that wastes reviewer time or causes extra review cycles.