Technical Design Document Template for Small Teams

A technical design document says how a change will be built before anyone builds it: the context, goals and non-goals, the proposal, the alternatives, the risks, the rollout, and the questions still open. A template to copy, a filled example, how to review one, and how it becomes tasks and context for coding agents.

8 min read

A technical design document, or design doc, describes how a change will be built, written before the code so that the expensive mistakes are made on paper. A template for a small team needs seven sections: context, goals and non-goals, the proposal, alternatives considered, risks, the rollout plan, and open questions. Two to five pages is usually enough. One person writes it, the people who will build, run and depend on the change review it, and once it is approved it is broken into tasks. The template, a filled example, a review routine, and how coding agents use the result are below.

The design doc sits between two other documents. The requirements say what the product must do and why, in a PRD; the BRD vs PRD vs FRD guide sorts those out. A single decision that should outlive the design goes in an architecture decision record. The design doc is the how, for one change.

The seven sections

  • Context. What exists today, what is wrong or missing, and the requirement or task that asked for the change. Facts, with numbers where you have them.
  • Goals and non-goals. What the design must achieve, as checkable statements, then what it deliberately will not do. Non-goals stop the review from growing the scope.
  • Proposal. The design itself: components, data model changes, interfaces and API shapes, and a diagram if it saves a paragraph. Enough detail that someone else could build it.
  • Alternatives considered. The other ways to do it, including doing nothing, and why each lost. This is the section reviewers read most closely.
  • Risks. What could go wrong: security, privacy, performance, cost, data loss, and the parts you are least sure of. Each with how you will reduce it or notice it.
  • Rollout. How the change reaches users safely: migrations, feature flags, staged release, what is monitored, and how to roll back.
  • Open questions. What is not settled yet, and who will settle it. A design can be approved with open questions as long as none of them could change the proposal.

None of this is new; long-running open-source projects have used the same shape for years. Python’s PEP 1 (opens in a new tab), which defines how Python design proposals are written, asks for a rationale that describes alternate designs that were considered, a section on security implications, a record of rejected ideas with the reasoning so the same idea is not raised again, and a list of open issues. Those map directly onto alternatives, risks and open questions.

A design doc template you can copy

docs/design/NNNN-short-title.md
# Design: [change, as a short title]

Author:     [name]
Reviewers:  [names, and what each is reviewing for]
Status:     Draft | In review | Approved | Superseded
Date:       [Month day, year]
Tasks:      [requirement or task refs this implements]

## Context
[What exists today. What is wrong or missing, with numbers.
Link the requirement.]

## Goals
- [Checkable statement]
## Non-goals
- [What this design will not do]

## Proposal
[Components, data model, interfaces, sequence of calls.
Diagram if it helps. Enough for someone else to build it.]

## Alternatives considered
1. Do nothing: [consequence]
2. [Option]: [why it lost]

## Risks
- [Risk]: [likelihood / impact] - [how we reduce it or notice it]
- Security and privacy: [data touched, access, abuse cases]

## Rollout
1. [Step, e.g. migration, flag off]
2. [Staged release, what is watched, for how long]
Rollback: [how, and what cannot be undone]

## Open questions
- [Question] - who decides: [name] - blocks: [yes/no]

A filled example

docs/design/0007-api-rate-limiting.md
# Design: Rate limiting the public API

Author:     Jordan Kim
Reviewers:  Ana Ruiz (backend), Marcus Lee (operations),
            Priya Shah (support: customer impact)
Status:     In review
Date:       September 29, 2026
Tasks:      ENH-301

## Context
The public API has no limits. Twice in August one customer's
script sent about 400 requests a second for an hour, and response
times for everyone went from 120 ms to over 2 s. Support has no
way to tell a customer they are over a limit.

## Goals
- No single API key can degrade response times for others.
- A limited client gets 429 with a Retry-After header.
- Limits are per API key and can be raised per customer.
## Non-goals
- Billing or plan-based quotas.
- Limiting the web app's own traffic.

## Proposal
Token bucket per API key, 20 requests/second, burst 40, held in
the existing Redis. Middleware runs before auth-heavy handlers.
Per-key overrides in the api_keys table (limit_rps, burst).
Every 429 is logged with key, route and count.

## Alternatives considered
1. Do nothing: the next spike takes the API down again.
2. Limit at the load balancer by IP: cheap, but customers behind
   one office IP share a limit, and it cannot be raised per key.
3. Fixed one-minute windows: simpler, but allows 2x bursts at
   window edges.

## Risks
- Legitimate heavy customers get cut off: log-only mode first,
  and contact the 5 keys above the limit before enforcing.
- Redis outage blocks the API: fail open, alert on Redis errors.
- Security: limits apply before auth, so a flood of bad keys is
  limited per source IP as well.

## Rollout
1. Ship in log-only mode; review 429-would-be counts for a week.
2. Enforce for 5% of keys, then 50%, then all, a day apart,
   watching error rates and support tickets.
Rollback: a config switch returns to log-only in one deploy.

## Open questions
- Default limit for trial keys? Decides: Priya. Blocks: no.

The rollout follows a pattern large operators rely on. Google’s SRE book, in its chapter on reliable product launches (opens in a new tab), describes almost all updates proceeding gradually with verification steps in between, starting with canaries whose behavior under real traffic is watched, and rolling back automatically when a change fails validation. A small team does not need the tooling to borrow the order: log only, then a slice, then everyone, with a switch back.

Reviewing a design doc

  1. The author names each reviewer and what they are reviewing for: correctness, operations, security, the customer. A reviewer with no brief skims.
  2. Reviewers comment in the document for a fixed window, often two or three working days, and read alternatives and risks first. A proposal that looks fine alone can look wrong next to a cheaper alternative.
  3. Hold a meeting only if comments conflict. Thirty minutes, the author runs it, and it ends with each conflict decided or turned into an open question with an owner.
  4. The approver, usually the tech lead, sets the status to Approved and dates it. Changes after that are new sections or a new doc, not silent edits.

Be honest in the document, because reviewers notice. Rust’s RFC process (opens in a new tab) warns that proposals which do not present convincing motivation, show a lack of understanding of the design’s impact, or are disingenuous about the drawbacks or alternatives tend to be poorly received. The fastest reviews go to designs that state their own weak points.

Design docs vs ADRs

A design doc covers one change and is mostly finished once the change ships. An ADR records one decision, short, and stays true until a later ADR supersedes it. A design often produces one or two ADRs: in the example, “per-key token bucket limits in Redis” is worth an ADR, because the next engineer to touch the API needs to know it was chosen on purpose. The ADR template covers the format; link the ADR from the design, and the design from the ADR.

Design docs as context for coding agents

A coding agent working from a vague task invents a design as it goes, and you review that design in the diff, where it is most expensive to change. A design doc moves the review earlier. Anthropic’s Claude Code best practices (opens in a new tab) recommend separating exploration and planning from implementation: explore in plan mode, ask for a detailed implementation plan, edit it before approving, then let the agent code. The design doc is that plan, written or approved by a person and kept in the repository.

  • Save it under docs/design/ and name it in the task, so the agent opens it before touching code.
  • Have the agent draft it from the requirement and the codebase, then review it like any other design. Check the alternatives and risks yourself; an agent tends to list the risks it can see in the code, not the ones in production.
  • Tell the agent to stop at open questions rather than choose. A line in AGENTS.md or CLAUDE.md does it; see AGENTS.md examples.
  • When the implementation departs from the design, update the design in the same pull request, or the next agent will build to the old plan.

Breaking the design into tasks

The rollout and proposal sections are usually the task list in disguise: each migration, component and rollout step is a task that can be finished and checked on its own. On a fenbs board, file each one as a feature or enhancement with the design path in the note, and put the relevant slice of the proposal in the task’s plan, which can be rewritten as the work teaches you something. Size each XS to XL; an XL is a signal to split it again. Open questions go on the Decisions and rules page as open decisions, linked to the tasks they block, and each card shows “decision waiting” until a person decides. A rule the design sets for everyone, such as “every public endpoint goes through the rate limiter”, is worth recording as a rule there too, because every connected AI assistant reads the rules before it starts.

Prompt, with the board connected over MCP
Read docs/design/0007-api-rate-limiting.md. Propose one task per
migration, component and rollout step, each finishable on its own,
with a size XS to XL. Show me the list and wait.
When I approve: fenbs_search for each, then fenbs_create_item with
kind enhancement, the design path and goal in the note, and the
matching proposal steps as the plan. Record each open question
with fenbs_add_decision as open, linked to the tasks it blocks.
Do not write code yet.

Related

Recording one decision for the long term: architecture decision record template. Which requirements document comes first: BRD vs PRD vs FRD. Splitting work so an agent can finish it: AI agent task decomposition. Planning before code in Claude Code: Claude Code plan mode.

Questions people ask.

What should a technical design document include?

Context, goals and non-goals, the proposed design, alternatives considered including doing nothing, risks with how each is reduced, a rollout and rollback plan, and open questions with who will decide them. A header with the author, reviewers, status and date makes it easy to trust later.

How long should a design doc be?

For a small team, two to five pages for most changes. If it runs much longer it usually covers several changes and should be split; if a change fits in half a page, a well-written task may be enough.

What is the difference between a design doc and an ADR?

A design doc explains how one change will be built and is mostly finished once it ships. An ADR records a single decision and why, and stays in force until a later record supersedes it. One design often produces one or two ADRs.

When do you need a design doc?

When a change touches several components, changes a data model or public interface, is hard to roll back, or when reasonable engineers would disagree about the approach. Small, easily reversed changes rarely need one.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.