Skip to content

Design Document

An engineering document that explores a design space and justifies an approach before implementation.

A design document works through how a non-trivial piece of software will be built, before it is built: the problem, the constraints, the proposed design, the alternatives weighed, and the risks. Where an ADR records a single decision already made, a design doc is the working space where the design is reasoned through before decisions solidify. Its audience is the engineers who will build and review the system - it exists to surface problems early, coordinate understanding, and create a record of the reasoning behind the implementation.

The hallmarks of a good design doc are proportionality and specificity. It goes deep enough on schemas, APIs, component boundaries, and data flows to give reviewers something real to push back on - but it stays focused on the problem being solved rather than general principles. A design doc that covers everything equally covers nothing usefully.

Design docs live in the space between “we are going to build X” (a PRD) and “we decided to do it this way” (an ADR). They are working documents: they may be updated as understanding evolves, and they expire when the system is built and the decisions have been absorbed into ADRs and operational docs. Their value is in the conversation they make possible before a line of production code is written.

# [System / Feature Name] Design Document
## Status
[Draft | In Review | Accepted | Superseded]
## Problem
[What problem is being solved. The constraints that shape the solution space.]
## Proposed Design
[How the system will work. Schemas, APIs, component boundaries, data flows.
Be specific enough that a reviewer can evaluate the approach.]
## Alternatives Considered
[Other approaches evaluated and why they were not chosen.]
## Risks and Open Questions
[What could go wrong. What is still uncertain.]
## Appendix (optional)
[Supporting diagrams, data models, or reference material.]

Planning a non-trivial feature or system before implementation begins, coordinating design across multiple engineers or teams, surfacing risks and open questions before a line of code is committed, creating a reviewable artifact that lets engineers evaluate the implementation at the concrete level - schemas, APIs, component boundaries - before code is written, documenting the reasoning behind an implementation for future maintainers.

Small, self-contained changes where the implementation approach is obvious to any reviewer, after the system is already built (write ADRs for the decisions instead), when a decision about direction is still open and needs broad input before committing to build (write an RFC instead).

pragmatic-architect, senior-consultant, candid, matter-of-fact, problem-solution, comparison-contrast

adr: An ADR records a single decision already made and its consequences. A design doc is the working space that precedes those decisions - one design doc typically generates several ADRs as the design is reviewed and accepted.

prd: A PRD defines what should be built and why - its audience is product stakeholders. A design doc specifies how the engineering solution will be built - schemas, APIs, component boundaries, data flows - and its audience is the engineers who will implement and review the work.

rfc: A design doc is the implementation specification for something already being built; its currency is technical specificity - schemas, APIs, component boundaries, data flows. An RFC is a comment-seeking proposal for a design direction that invites pushback before a decision. A design doc assumes the decision to build has been made and works out how; an RFC is still asking whether and how to proceed.

  • A Problem or Background section that names the constraints shaping the solution space
  • A Proposed Design section committing to concrete implementation specifics - schemas, APIs, component boundaries, or data flows - that an RFC would not yet pin down
  • An Alternatives Considered section that shows what was evaluated and why it was rejected
  • A Risks and Open Questions section that names what could go wrong or is still uncertain
  • A Status header (Draft, In Review, Accepted, Superseded) tracking where the document stands
  • Technical specificity at the implementation level, not the product requirement level
  • Audience is the engineers who will build or review the system, not product stakeholders
  • Writing at the product requirement level - what to build and why - instead of the implementation level - how to build it - A design doc that describes desired outcomes without specifying schemas, interfaces, or component boundaries is a PRD, not a design doc; engineers cannot evaluate or build from it.
  • Omitting Alternatives Considered or listing alternatives without saying why they were rejected - The reasoning behind the chosen approach is where design docs earn their value; a list of alternatives without rejection rationale reduces to a menu, not a design.
  • Scoping the document to the entire system rather than the specific change or addition being designed - System-wide scope turns a design doc into unmaintainable reference documentation; each design doc should cover one bounded change or addition.
  • Soliciting a vote on whether to proceed rather than inviting technical review of how to proceed - That is the job of an RFC; a design doc assumes the decision to build has been made and works through the implementation, not the direction.
  • Over-specifies too early - locks in implementation details before the team has validated the approach, so review becomes defensive rather than generative - Flag uncertain areas explicitly in Risks and Open Questions; keep early drafts focused on structure and interfaces before committing to implementation minutiae.
  • Expands into a treatise - grows to cover every edge case and becomes unreadable before the first reviewer reaches the Proposed Design section - Aim for the minimum specificity needed for a reviewer to evaluate the approach; move exhaustive detail to appendices or linked documents.
Write as a Design Document. Work through how the system will be built, not what it should
do. Use these sections: Problem (the constraints shaping the solution space), Proposed
Design (concrete specifics: schemas, APIs, component boundaries, data flows - enough for
a reviewer to push back on the approach), Alternatives Considered (other approaches and
why they were rejected), Risks and Open Questions (what could go wrong and what is still
uncertain). Be technically specific. Your audience is engineers who will build and review
the system. Do not write at the product requirement level - that is a PRD. Do not
solicit a decision on whether to proceed - that is an RFC. Write at the implementation
level, assuming the decision to build has been made.

See the Design Document template.

Pragmatic Architect, Senior Consultant, Candid, Matter of Fact, Problem-Solution, Comparison-Contrast

Playful, Pastoral, Urgent, Reverent

Architecture Decision Record, Product Requirements Document, RFC (Request for Comments)

Accepted

The engineering team (11 engineers, 4 timezones) runs a synchronous daily standup at 9am Pacific. This format fails on three fronts.

Timezone asymmetry. 9am Pacific is 9:30pm IST. The three India-based engineers averaged 3.2 out of 5 standup appearances per week in Q1, against 4.6 for US-based engineers. The gap is not a performance issue; the schedule is structurally unfair.

No persistence. Status exchanged verbally disappears when the call ends. We documented three Q1 incidents where an engineer spent over an hour on a problem already surfaced and resolved in a previous standup. The meeting produces no searchable record.

Low signal-to-noise ratio. The standup averages 14 minutes. Roughly 4 minutes drives an action - a blocker raised, a dependency flagged, a context shared. The remaining 10 minutes is status nobody needed to respond to.

Constraints shaping the solution:

  • Cannot require attendance outside normal working hours for any engineer
  • Must preserve the coordination value of the standup: blocker detection and dependency surfacing
  • Must produce a persistent, searchable record
  • Tooling must stay within Slack; no new paid tools unless value clearly exceeds cost and complexity

Each engineer posts one message to #team-standup by 10am their local time. The message follows a three-field template:

Shipped:
- <what completed since last post>
In progress:
- <current focus>
Blocked or at risk:
- <what is stuck and who or what resolves it, @mentioning the responsible party>

Empty fields carry the literal value “nothing today.” Fields are not optional - an absent field is ambiguous between “I forgot” and “nothing to report.” The 10am local cutoff creates a clear posting window that gives all four timezones time to post before the Pacific-based on-call scan runs.

One channel: #team-standup. A pinned message carries the template and two exemplar posts (one from a high-load day, one from a quiet day). No bots. No automated summaries. The channel is a log, not an inbox.

The /standup Slack message shortcut pre-fills the template into the compose box. It is optional convenience, not the mechanism - typing the three headers manually is equally valid.

The on-call engineer scans #team-standup once, between 10am and 11am Pacific. Their responsibility is narrow:

  1. Confirm every engineer has posted; DM late posters
  2. Ensure every @mention in a Blocked field has received a substantive reply within 30 minutes of the scan

The on-call is not a summarizer. They do not re-broadcast channel contents. Thread replies are the response surface; a new top-level message is only appropriate for a team-wide blocker affecting multiple people.

This role replaces the meeting facilitation slot already on the on-call rotation.

The 60-minute weekly slot at 8am Pacific / 8:30pm IST replaces the five daily sync standup slots. Agenda lives in docs/thursday-agenda.md, maintained by the engineering manager. If the doc has no items by Wednesday 5pm Pacific, the session is cancelled for that week.

This is not a standup in async clothing. It is reserved for discussion that requires real-time exchange: design review, cross-team dependency negotiation, or issues that carry nuance the three-field template cannot hold. Status reporting is not a valid agenda item.

Engineer post (by 10am local)
--> #team-standup (persistent, searchable)
--> On-call scan (10am-11am Pacific)
--> @mention reply (SLA: 30 min during business hours)
--> Thursday agenda item (if discussion needed but not urgent)

Geekbot or equivalent async standup bot. Rejected. Geekbot solves the scheduling problem and adds structure, but it introduces a paid tool, a data store outside Slack’s native search, and vendor dependency for a process the Slack-native approach handles. Cost and complexity are not justified given functional parity.

Rotating the meeting time. Rejected. A rotating time makes the schedule equitable on average but does not create information persistence. It also adds coordination overhead and removes engineers’ ability to hold a stable recurring block for deep work, since the standup slot is always moving. Solves one of three problems; the other two remain.

Eliminating the standup entirely. Rejected. The coordination value - blocker surfacing, dependency flagging, context sharing - is real, even if the signal is buried in noise under the current format. Removing the standup removes the mechanism without replacing the value.

Moving standup to 12pm Pacific. Rejected. 12pm Pacific is 12:30am IST the next day, shifting the timezone burden from late evening to late night for India. Worse, not better.

Post quality drift. If engineers write long-form updates instead of three-bullet summaries, the channel becomes slower to scan and on-call triage load increases. Mitigation: pin two exemplar posts from day one; set an explicit expectation in the process playbook that each field should be readable in under 15 seconds.

On-call triage load. The target is 10 minutes per morning for the channel scan. If blockers surface earlier and louder than they did in the sync model, actual time could run higher. If the role consistently exceeds 20 minutes, consider splitting triage responsibility by timezone cluster.

Participation cliff. The format’s coordination value scales with participation. If one or two engineers consistently miss the cutoff, the channel becomes unreliable as a team signal. Mitigation: on-call DMs late posters; the 30-day trial retro surfaces participation data to catch this early.

Social cohesion. The sync standup provided a daily shared moment that the async format does not replicate. The Thursday session is a partial substitute. This is a real trade-off accepted because the equity and persistence gains are larger, but qualitative feedback in the trial retro should track it explicitly.

Open question: cutoff enforcement. The 10am local cutoff is a norm, not a hard technical constraint. Whether to add a bot reminder at 9:45am local is deferred until after the 30-day trial produces data on late-posting patterns.

Open question: holiday handling. Behavior on local public holidays (UK bank holidays, Indian national holidays, US federal holidays) is not yet specified. Deferred to trial retro.