It can feel daunting to write a technical spec. It can feel like too much hard work, or worse, busy work that’s not really important.
But writing a design doc doesn’t need to take a lot of time and ideally saves you time in the future. You don’t even need to know what you are going to do before starting, as writing a design doc can be a great exercise in “thinking through writing”.
The purpose of a technical design document is to aid in the critical analysis of a problem and the proposed solution, while also communicating priority, effort, and impact with various stakeholders.
A good design doc will preempt questions and queries that might arise during the code review process, identify edge-cases, and will allow people to suggest improvements before a lot of work has been done.
If a design doc proves controversial that’s a great signal that an in-person discussion should be had or that the problem isn’t well defined.
Here's a template for your next design doc
Starting with a blank canvas is difficult. I’ve found that a good template can speed up the writing process and prompt you to think through important areas that may not be top of mind.
Each section in this article mirrors a section in your design document, it’s a variation on the documents I wrote at Google and brought to the engineering team at Medium. You may find that some sections aren’t relevant to all teams and projects, so use what is helpful and drop the rest.
The ultimate goal of a design document is to facilitate communication and alignment, not to create unnecessary bureaucracy.
Start at the beginning. What problem are you trying to solve? If you jump straight into solutions, it will be hard for people to orient themselves and will inevitably lead to misalignment and misunderstanding. It’s worth spending 2 or 3 sentences to effectively set the context for your spec.
Then, briefly state your proposed solution. This should be enough for most people to decide whether they should continue reading and should be understandable by someone who is not familiar with the project. Between a few sentences and two paragraphs should be enough.
It’s unlikely that writing the design document is the first time you’ve thought about the problem. The background section is an opportunity to bring readers up to speed, and share the context you have on the problem space.
What are the motivations for the project or design? Is there any historical perspective that will help people understand the proposal? Has someone tried to solve the problem in the past? If so, why are those solutions no longer appropriate? Are there any other things going on that will affect the design?
Goals, non-goals, and future goals
In order to build alignment and communicate a definition of done, it is important to clearly articulate the goals of this work. The best goals are simple, truthy sentences that describe a future state of the world. Unlike an OKR, it’s fine for these goals to be hyper-specific. Projects will often have 3-5 goals.
- Hot backups are available in 3 regions
- Deactivated accounts have their data automatically purged after 30 days
- Web UI uses React instead of Vue
- Mobile clients receive automatic updates
As well as explaining what you want to achieve, it is equally important to say what you are explicitly not addressing. These can sometimes be hard to identify, but imagine what another person might expect to be coupled with this work.
Future goals are an opportunity to list things you want to do in the future, but have descoped for this phase of the project. In other words, these are things you want to make sure your solution doesn’t accidentally make difficult or impossible.
This is the meat of the document and also the most variable. Depending on the project, the size of your team, or number of stakeholders, it may be a few paragraphs or a few pages. It will often contain pseudo-code, schema definitions, or flow diagrams.
Here are some common questions that get answered as part of the detailed design:
- What are the user requirements?
- What systems will be affected?
- What new data structures are needed, what data structures will be changed?
- What new APIs will be needed, what APIs will be changed?
- What are the efficiency considerations (time/space)?
- What are the expected access patterns (load/throughput)?
- How will data be validated and what are the potential error states?
- Are there any logging, monitoring or observability needs?
- Are there any security considerations?
- Are there any privacy considerations?
- Are there any mobile considerations?
- Are there any web-specific considerations?
- How will the changes be tested?
- How does internationalization and localization — translations, time zones, unicode, etc. — affect your solution?
(You probably don't need to answer all of them.)
Today it is common to rely on 3rd party platforms to support our development work, whether this be part of AWS or GCP, or a whole separate service. It’s worth thinking through the implications of using a third-party and looking ahead for potential future issues.
The cost of these services is often less than an engineer’s time, but sometimes it can scale unexpectedly. Quickly think through how the service is billed and do a back-of-the-envelope calculation of what could be expected once the service is fully rolled out.
While security and privacy considerations were addressed in the detailed design, when using a 3rd party there are specific things to think about and call out.
For example, if the 3rd party is being used to perform operations on customer data they will likely be considered a subprocessor under the EU’s General Data Protection Regulation (GDPR). So, do you need a data processing addendum? Do you need to collect and review SOC2 reports? Sometimes customers will require notification of new subprocessors, which will affect the roll-out plan below.
For non-trivial changes, provide a breakdown of the work and tasks. How long will each phase take? What work is parallelizable? What dependencies on other teams are there?
It’s unusual that you can roll out your project as a single change. In this section, discuss how changes to models and APIs will need to be staged. Will you be rolling out incrementally to your users using feature flags?
Discuss your revert path. If something goes wrong, how will you back out partway through the process while leaving systems in a healthy state? Identify the biggest risks you see, and spell out how you’ll detect and mitigate them.
It’s not enough just to share your chosen solution. By explaining approaches that you rejected you can reduce time handling objections from other stakeholders and focus the discussion on your chosen design. Make sure to explain why other approaches seemed inferior or wouldn’t work.
It’s also not unusual for information to emerge during the design process that escalates an alternative approach to the primary approach. If this happens, try and avoid the sunk cost fallacy.
Are there products — internal or external — that are similar to this project? Are other teams being faced with similar challenges?
As an example, if you are building your own NoSQL database (😱) this section might include a feature matrix comparing your requirements to existing database offerings.
This is where you can help prevent bike-shedding and scope creep. Identify anything you’re not addressing with this particular design but that should happen in the future or that would be a logical follow-on project? This is often a more detailed description of the future goals, or perhaps how some of the non-goals might be addressed in the future.
When you’ve written your first draft, go back and reread it. Question each statement and decision. If the reasoning is not clear, add more clarification.
I’ve seen this template help engineers of all levels — I used it this week to help me think through a solution to a data analysis problem we have here at Range.
I’ve also seen people react negatively to the idea of design docs, and to be fair, for many teams and environments, a lot of projects don’t really need a doc. Unfortunately there’s no hard and fast rule on when a spec is appropriate. It’s a function of complexity, certainty, and risk, and is something you’ll have to feel out for yourself.
But, next time you’re working on a gnarly problem, or juggling multiple stakeholders, try using this template, and let me know how it goes. You can find me on Twitter @dpup.