I've never experienced a situation where a software design document meaningfully improved the overall process. At best, it helps to keep the business in sync at the expense of a much longer delivery timetable. Even high level software delivery contracts never seem to stay on rails for very long.
It is often faster to just build the damn thing and see where it lands. Software is not like a nuclear power plant or offshore oil platform. You do not need to prove a whole lot of things in advance of construction. No one actually has to give you permission to do anything. You can email a link of a vertical slice prototype to the business whenever you feel like it. That can be the "design document".
I'll admit a lot of bias because I think design docs are extremely useful, but I find that when people hate design docs, it's almost always for one of two reasons:
1. The developer has worked on teams where design docs are viewed as a pointless ritual, so authors treat them as a pointless requirement and write bad docs and their teammates view them as pointless so they don't bother giving useful feedback, reinforcing everyone's belief that they're a pointless ritual.
2. The developer does not like other people questioning their engineering choices, and they know that it's harder for their teammates to push back on finished code than a design doc. Investing in the implementation before design changes the calculus to bias in favor of whatever's already implemented rather than what would have been the ideal implementation. Plus, it's harder for the team to review design decisions of 10k LOC than a 5-page design doc.
I think your framing is fair here. But I'd like to offer an even more complicated/nuanced take:
Designing in a group can be very difficult, and doing it well is a skill set that most people don't naturally have.
I think this explains your point 1. Why do people view designed docs as pointless? Because they really don't have a vision or model for what and effective and healthy collaborative design process would look like.
> Designing in a group can be very difficult, and doing it well is a skill set that most people don't naturally have
Not only is it a skill every participant needs to have, they also all need to have a similar amount of competence and knowledge about the domain as well as the current implementation, otherwise it's mostly pointless ime.
But if all ven diagram circles overlap ... It is nice.
I can count the times this materialized (in my professional life) on one hand. So I'm generally more towards the "make a prototype, then explain it to the others. Either it's the baseline for the discussion or the illuminating event that clears up wherever this approach works with that team.
YES - and 3 the the assumption that it needs to be a certain length before it can be considered a design document.
Esp. in the age of AI a little guidance to brainstorm on before a random project prompt goes a long way. (Not saying people that don't use design docs just code away thoughtlessly) - experience goes a long way too that's why there's success stories with and without design docs.
Not OP, but I think they're way more essential with AI doing a lot of the coding. The biggest thing that AI, even the frontier models, is not great at is staying on topic and actually finishing a project with reasonable priorities instead of ratholing on insignificant details or claiming it's "finished" when it's half done.
The most important thing that a good design doc does is specify what's in and out of scope. The second most important thing is to precisely define common vocabulary - what are the important concepts in the problem you're solving, and how should they relate to each other? All of that information serves to ground the day-to-day work in what's important. I find myself starting every Claude session with "read this doc and get familiar with the world, then we'll get to work on a part of it".
(The same is true when working with humans, especially but not limited to junior engineers who aren't used to managing a project longer than a week or two. AI coding agents just never grow out of that phase.)
For an entire project? Yes I agree. For a feature or a submodule? I think when you work with claude to develop a plan, it's generally pretty good.
I guess my question stems from being rigid how a design doc should be defined, argued over, and then executed by humans. I think some of the details simply don't matter, and if they do, they often can be changed relatively quickly in order to adhere to the new requirement.
In the age of AI coding, code is cheap. Getting the requirements and high-level architecture nailed down is where the hard engineering challenges remain.
We have debated this a lot in our organization. We are tired of seeing low effort Tech docs that puts the onus on the reader than the writer. I think that the writer should spend at least an order of magnitude of time more than the reader. If not, then the design doc can just be the LLM prompt that generated the document.
I have actually resorted back to hand crafting TDDs and focusing on 1-2 page docs. It is a great way to organize my thoughts and create a shared mind space among other engineers. My 2 cents.
I think we definitely need to have alignment, and documentation to support it. I think this can be at the PRD level, mostly.
For many systems, I'd argue technical documentation to understand how the internals are working can simply be handed off to the robots. Or generated on the fly. And if a requirement on the product level is not met, that can be changed under the hood.
That means you could choose to try three (or more) genuine implementations and explore their tradeoffs, instead of making three proposals in a document with one recommended (and the other two usually only provided for contrast).
I do think the design is important to keep around - in particular, the constraints, the communication points, schema, tacit things that might not be clear in code. I am not certain that the design should precede the implementation for features below a certain size though.
Larger efforts need milestones and collaboration and will have multiple people doing implementation, so there's more need to agree schemas, APIs etc up front there.
Agree, but in my experience that doesn't change much about the design doc.
I think it's helpful to the author to be able to say to an AI agent, "Hey, put together this quick prototype," and that informs the design doc. But if the goal is to review the design decisions with the team, I don't see how you get around the design doc. I don't want a teammate to send me 10 KLOC of AI-generated code and ask me to review the design. Even if you told AI to try 10 different ideas and pick the best, I don't trust AI to make the same decisions as my human teammates.
I'm not suggesting using AI generated code as a proposed design.
I would try and get an understanding of design space by giving a good agent a high level goal and seeing what it does, then getting a summary of the approach.
When you do this several times, especially if you give it a steer on some non-functional requirement, you can compare and contrast different approaches.
The idea isn't to prototype so much as to gather information by doing. Prototype, to my mind, suggests other things; shortcuts, stubs, incompleteness. I would actually ask agents to do the whole thing, and find out the full scope. It can be particularly useful revealing side effects.
Pair it with code auditors wearing different hats, of course.
IME when starting a project from scratch, detailed upfront architecture specs are pretty much required to keep LLMs from flailing around too much (unless of course you build another cookie cutter CRUD webpage, those can simply copy paste from the millions of examples on the internet).
In a way it's a return to waterfall, just with faster implementation phases.
I think it's more important. AI gets a lot right, but sometimes it gets things wrong. The document might be the only human authored piece of text, and it will help future agents see that something is incorrect in the implementation.
Software is in nuclear plants, cars, oil platforms, pacemakers, everywhere. If one is writing more ‘disposable’ stuff like flashlight apps for smartphones, then sure, as you say. Others are writing serious stuff, and design docs are invaluable.
Same goes for highly regulated financial environments. If you work in banking you generally can't just FTX-and-hope your prototype, which is very much what GP sounds like they're advocating.
For starters you're going to have traceability requirements that can only be satisfied if you have a product requirements document and then often a software design document. Now you might well choose to manage all of that in JIRA and Confluence (or whatever) rather than sitting down and writing an actual document intended to be laid out and printed on paper but the fact remains the documentation exists and, indeed, is a must to satisfy compliance and regulatory frameworks.
As always, the domain you're working in and the organisation you're working for make a huge difference but, as much as there are plenty of places where none of this stuff matters at all, there are also plenty of places where it's incredibly important and that isn't going to change anytime soon.
at least where i work the onus of "who creates the design doc" ends up on the developer.. who also builds the thing.. and thats just like a 2.5x translation tax on the developer who's realistically putting it together to appease business heads who want to feel involved.
i can think of... zero times where a business-coded person even a technical PM (which is a role i do appreciate btw) has ever come up with an official design doc or specification that didnt suck. creating a good design doc is either going to require an architect/staff or senior engineer to sit down and just do it. the overworked architect or staff engineer inevitably gets dragged in if the developers hands are full, or they just beat the shit out of the developer and fill their calendar up with meetings and make them do it... then they beat the shit out of them again and make them build it.. then they beat the shit out of them repeatedly doing fast follows for months and say "no not like that"
i think everyone wants to take some pride in the org they work at and maybe they feel like they've got the formula for sucess, but i personally haven't seen it. there's always going to be an additional translation tax required of the developer(s) who is/are also building the damn thing at the end of it. cover it in poorly run agile/jira shenanigans and this just slows down the possibility of getting to a super stable state back soooo far.
i actually agree with the guy a couple posts up: do some loose design work, friggen dropkick/prototype and see where it lands and go from there. i like facepalm when i hear that our project guys were planning a project for a year and when it was finally time to move on it every specification they planned out missed all the details. this is totally so much worse now with AI writing everything everyone is putting together.
I reflected upon a consumer product I worked on the other day, in the power tools market, and the damn thing had 3 processors in it.
I mean... when i was golfing, the cart had a gps enabled, cloud connected display that showed the golfers positions in front of us. I had a smart phone and a smartwatch with meter-accurate positioning to take a shot.
It sounds like you’re defining design as UI/UX design. I think most people include (prioritize, even) things like system architecture, performance bounds, etc.
It's mixed for me because there are certain things that I clearly think are needed. For example I'm building a custom network architecture and it's to the point where I'm using frontier models to reverse engineer game clients (while battling against the cyber safety system) for the sole purpose of validating that the network architecture I'm making is, if not "useful" (cause there's the game itself), at least different and superior. And to me the designs out there clearly are evidence of things not designed well and thought through ahead of time and instead a patchwork of hacks.
But then there are aspects I'm missing because while I've thought about the network protocol deeply, I'm not, say, a game developer who's ever gone through the whole game dev lifecycle. There's common patterns with software dev but it ain't it. There are probably so many things I have not thought about w.r.t. the whole deployment process that I'm not sure if letting AI vibe design+code it out is good or if I need to sit down and deeply work out the things I don't even know I don't know.
It's been quite helpful when your project needs expertise from other people, and you want them to vet your approach and find gaps. Doing the up-front work of explaining the context and structuring the project in an easy to understand way makes it more likely for busy people to engage with it and help you out. Of course, it's helpful as a rubber-duck exercise on its own, so I would err on creating one, even if just for myself, for anything high-risk or hard to change later.
> At best, it helps to keep the business in sync at the expense of a much longer delivery timetable.
If you're writing a software design document that slows down your delivery timetable, you're doing it wrong. (Or, more charitably, your business is doing it wrong.) If your design document is to keep the business in sync, you're doing it wrong. That's not what a design document is for. It's for keeping you in sync.
> It is often faster to just build the damn thing and see where it lands.
What are you building? If you don't know, then sure, it's really hard to write a design document. At that point, you're doing exploration, research, not development.
But even when it's an exploration project... once you've found something worth doing, take a day or two and document what you're doing and how you're doing it. Think through all the places in the code you're going to have to touch, all the other things it has to interface with. Make sure you're not going to leave a gaping hole in functionality or, worse, in security.
> Software is not like a nuclear power plant or offshore oil platform.
As others have said, sometimes software is a nuclear power plant or offshore oil platform or airplane or medical device, or even just medical informatics. If you mess up people can die. Sometimes it trades financial instruments, and if you mess up it can destroy the company.
> No one actually has to give you permission to do anything.
On your own time, sure. If you own the company, sure. Otherwise, you need their permission to spend their time on things that they're willing to pay for.
Now, look, it's true that many places go too far overboard on "process". But YOLOing and cowboying isn't the answer either. They aren't even the answer if your single goal is to go as fast as possible. You go faster by spending the appropriate amount of time thinking through what you're building, how you're building it, and making sure you're not missing any of the big things that often trip projects up.
Instead of thinking through all the places in the code the AI is going to have to touch, why not kick off three parallel agents implementing the thing and finding out what they did and the tradeoffs they found?
Planning is essential but it doesn't survive contact with reality. However, AI makes contact with reality cheap! Why not use it to improve designs, by writing the design after a few implementations have already been made?
I'm looking for the places that need to be touched, but that wouldn't occur to me (and maybe not to an AI either) while I'm knee-deep in the code. Seeing where the AI touched isn't going to solve that.
If the feature works, and passes AI auditor agents with various hats (thinking of auth and security in particular), did that code you're not thinking of need to be touched? What effect did it have that cannot be captured in side effects, tests or audits?
If what you said doesn't make the AI think of changing that code, why is it going to make the AI auditor think of testing that code? That's what a gap looks like: Nobody changed it, nobody tested it, but some business constraint is now left in an inconsistent state because some piece got updated and another piece did not.
Here's an example. You updated the code that interfaced with the database. But you forgot to update the stored procedures within the database. As a result, the database is now being put in an inconsistent state with every transaction that uses your new code. That is the kind of thing that a software design doc can help you remember, because it is supposed to make you think through all the stuff.
And if you're going to say "Your business stuff shouldn't be able to get into an inconsistent state", well, there's a lot of businesses that have potential landmines laying around. You can say they shouldn't. You're right, in an ideal world. But in this world, they do, and you have to live and work in the world that we have.
Now, in fairness, a good AI check might turn up that the database was left in an inconsistent state... if it understood the constraints well enough. If. I wouldn't want to gamble my production database on the AI's understanding and testing of all the constraints, though.
You have successfully optimized for fast, but you have not optimized for quality, extensibility, customer experience, or maintainability. Fast can be a great thing to optimize for, but there are many other situations where other optimizations are preferable.
Welcome both of you to the agile vs waterfall arguments of 25+ years ago. :)
The agilists I think ended up having pretty good answers for finding a sweet spot between small iterations that maintained quality while minimizing Big Design Upfront to prevent spending a lot of time preplanning the software, allowing a well functioning agile team to maintain reasonably high quality, extensibility, maintainability and satisfaction of actual customer needs while keeping velocity high and not getting bogged down in design heavy tar pits which were ended up not fully anticipating problems encountered during actual execution.
If that doesn't sound like a buzzword filled sentence I never expected to come out my mouth... But. The bottom line is: if you can keep your execution goals small and focused enough, you can iterate quickly towards a design with better information than you would have if you were to do a design study because you'll be better informed by the actual needs of the execution process than by what you _think_ the execution process will require at design time.
100%. I find it's generally used as a waterfall practice - i.e. BDUF first with a design document, then implement instead of "implement following conservative assumptions, revisit and refactor aggressively".
The latter being vastly more effective at honing good design because more decisions are made in retrospect.
I find that a spike or a spike PR to demonstrate a new approach (if a software design decision is controversial) is 10x as valuable.
> implement following conservative assumptions, revisit and refactor aggressively
> The latter being vastly more effective at honing good design because more decisions are made in retrospect.
Only if people actually do that.
I've joined a project where a design doc should've been written before the first line of code (as per the agreed upon dev process). Developers disregarded that and yolo'd their way to a first prototype. No documentation whatsoever. Then someone else was tasked with writing a design doc for that big ball of mud. You can imagine how that went.
I've joined the project only much later. At every corner I'm dumbfounded by the "design decisions". Refactoring now is a herculean task and kept to the minimum required.
I'm certainly not advocating for waterfall-like "make a plan and stick to it no matter the cost". But looking at the requirements and drafting a coarse design from those goes a long way. At least you can get idea if whatever you have though up is in agreement with the requirements.
Treat the design document as a living document. Do a coarse draft first. Implement. Refine the doc with stuff you've found out, ditch the stuff that didn't work. As a bonus you get a relatively neat on-boarding doc for people joining later.
> No one actually has to give you permission to do anything.
For now, in the current context (with ai), it seems like a non-ignorable portion of society now wants to limit what kind of code people can write, Ai is apparently sufficiently like nuclear science that regulation may come to the act of producing code.
> It is often faster to just build the damn thing and see where it lands.
Part of documentation is figuring out if you're building the RIGHT thing. It give the opportunity to get feedback from more than one party.
The usability of most modern (complex) application is deplorable. I see things that a paper prototype with 5 people on the street should have stop dead in its tracks being rolled out with banners and trumpets.
And then no one ever wants to remove an unused or unprofitable feature. There is no bonus for it, no one puts that on their resume. But the feature you launched that really did enshitify the product gets put on there with 3 gold stars.
Your second paragraph is the impetus behind Agile Software, and we've all seen how fantastically that failed. Lots of code pushed out quickly, but also a lot of really shitty products, uncertainty, never-complete projects, dysfunction between teams, etc.
> Software is not like a nuclear power plant or offshore oil platform
No, but it does impact people's lives significantly. How many times has your personal information been leaked by a company making products by people who didn't care? Who would have predicted that a security company's terrible QA would lead to 8.5 million crashed systems, 42,000 delayed flights, 10,000 cancelled flights, and over $10B in economic losses? I'm sure the developers just said "not our problem". But their lack of concern, and "just throw shit at production" mentality, had real world consequences.
Have you never encountered code that you thought was designed fundamentally incorrectly, but was too entrenched to change? That's what design review is for.
Author here. Happy to take any feedback about this post.
I learned to write design docs at Microsoft and Google, and I thought they both had good culture around docs that hasn't percolated out as well as other engineering practices at those orgs. I haven't seen a thorough explanation of how to write design docs, so this is my attempt to externalize what I've learned about writing them.
The documentation became the bible, and although I tried to keep the design goals at the conceptual/logical level the following would happen the moment the implementation started:
1. This is ambigous the docs need updating, please refactor your design
2. This doesn't work as the doc stated why did you get this wrong
3. The requirements have changed you need to update it
The burden to get "everything right" was absolutely lumbered of me, and the document became an easy finger pointing exercise, even if blame wasn't intended by those launching the critique the burden of "owning" the doc and the consequences of the doc was real.
Now there's a good chance that I am just a shit documentation writer, I can accept that, but honestly I feel like for the vast majority of organisations this just falls into another step of the waterfall pattern, which just doesn't work.
What you're describing sounds like toxic team dynamics rather than something specific to design docs. Do you work effectively with your teammates outside of design docs, or is there similar tension/hostility everywhere?
What you're describing sounds like the design process working as intended (modulo the finger-pointing). The design doc should be unambiguous, and the implementation should match it.
Assuming this isn't just symptoms of a sick team, my other explanation is that your teammates find your deviations from the design doc unexpected. It sounds like you're running into situations where you can't implement the design doc as written, so you're proactively making your own design choices and showing your teammates the implementation. Could you loop your teammates in earlier on before you've implemented the code? Like, "The design docs says we're supposed to use SQLite, but I realized that SQLite doesn't support types the way we expected, so I think we should switch to Postgres for X, Y, and Z reasons."
This is good guidance, but what do you have to say about convincing your team of developers to live it out?
I've found that developers usually like writing code and avoid contributing to documentation. For some, it's actually scary because (edit: for them,) high quality writing is harder than high quality coding, and it can be avoided quite a bit.
On the project side, it's rare for the implementation and verification stages to not consume all the budget and more, and delivery creeping past the original optimistic date. So there's no time or money to spend on documentation.
The combination is that even with your great advice in hand, it's hard to navigate to really solid and comprehensive design documentation underpinning the products.
This is a good question, and I have a super long answer that's been in my head for like 8 years about how to influence your teammates to adopt good engineering practices.
The short answer is that most useful software engineering practices are a risk to the first person on the team to adopt them. For example, if everyone on your team thinks automated testing is stupid and you adopt automated testing, it will look like your work is worse because you're slower in the short-term, and maybe you have to do even more work when teammates break your tests.
It comes down to accruing social currency with your team. Your teammates don't want to take a risk for you if you have a history of bad ideas that wasted everyone's time. But if, for example, you implemented automated deploys to replace a tedious workflow developers had to do manually, people would see how your ideas have payoff, and they're more willing to invest a little bit if they expect ROI long-term.
When I've convinced my teammates to invest in design docs, I made sure I had some wins under my belt before I started pushing for everyone to write design docs. I invested a lot in docs myself so my teammates could see the value before I asked them to start writing.
This is also a place where you have to think about politics a bit. Documentation has a much better shot if it has support from the top, so think about the pitch to your manager or dev lead about how design docs make their jobs easier.
1) Add a section called "Potential Changes". This is broader than "missing features", and can include other items too, such as new hardware that might become avaliable, customer requirement changes you might anticipate, possible new technology (e.g. a new database or cloud service that might be useful), multilingual support, etc. Listing some of these often causes reviewers to think of others as well.
Ensuring the design is modular around such changes means implementing any of them will be far easier than if assumptions are hard-coded throughout the codebase.
2) Security and privacy are two aspects of a more general category of "compliance assurance". Those two are worthy of their own categories, but you should have a section covering any other legal, regulatory, or corporate requirements. The plan for auditing these compliances should be listed too.
Often, of course, there are none beyond security and privacy.
Lot of this is outdated. Including stuff that made a lot of sense in the past like diataxis and the google guidance.
I've started to build docs structured as a skill. Since every model/harness is trained to handle skills well today. The entire docs of a project or modeled as a skill.
I also have additional frontmatter on the md files. Specifically 2 keys -> when should you read, when you should not read this doc. This with a simple cli to help parse this has made the docs experience much quicker and nicer.
You can also generate svgs, mermaids etc on the fly now when you are really stuck on something.
I think it's worth more scrutiny today, rather than less. Your claude code can barf out "a rewrite" but is it any good? So far the answer is "no" (see anthropic's C compiler, or a more recent port of bun).
Software is still the best specification for existing behavior..
I'm not following because a) The bun rewrite was a success b) the C compiler wasn't a rewrite and c) "Software is still the best specification for existing behavior" seems to imply that rewrites are achievable because we already have a working version that functions as a spec?
It reads more like a CONOPS or a software architecture document, but its not detailed enough from a high level perspective, and too detailed at a low level perspective (ie. it has implementation details in a few places you wouldnt expect in a higher level design doc).
In that light, I'm not sure who the audience would be in a corporate environment. Is it for architects, other developers, or yourself?
I think they're valuable, both because they get you to think through the actual functionality (and underlying implementation) of the software, and the make sure that you and the [person you're developing for] are roughly on the same page. Plus, every edge case or design issue you catch while writing the spec saves you a ton of time.
That said, I think a big weakness of specs is that it's just not possible to write a perfect spec that doesn't have any blind spots and covers all the edge cases and issues you'll run into when actually developing. This makes it more difficult to hold the customer accountable to the spec, since you (the designer and devs) can't really be accountable to the spec unless you want to deliver some overly literal, not-actually-helpful product.
Fun piece of trivia, Joel published one of his functional specs.[0]
As a huge fan of Joel's writing and engineering ideas, I was actually underwhelmed by his spec. It wasn't bad but it also felt like he missed a lot of opportunities to articulate design decisions to the reader more quickly or clearly.
One obvious mistake is that there's over a page (in a 20-page spec) just dedicated to coding conventions and what prefixes variable names will have. I think Joel later conceded that it was a mistake to cover naming conventions in a spec, though I can't find a link now.
I definitely agree that it's not perfect. I think he's a great starting point though, because when trying to get engineers to document stuff (something typically approached with similar enthusiasm to having their teeth removed with a hammer) it really helps if the "how to write a spec" doc is somewhat fun to read.
Unrelated - I really dig your "my [x]th year as a bootstraped founder" series.
> A good design doc can save you years of development time.
I only have a few years of experience in this business, but I have seen numerous cases where none of any of this matters. Your perfectly drafted plan could easily be derailed by technical limitations, customer request or company reorg. You are better off use that planning time for something else.
I have worked on DO-178C (aerospace) and IEC 62304 (medical device) software design documents and they are much narrower in scope.
OP's design document is comprehensive enough to cover much of ground of the full documentation package for regulated software submissions. Basically all that's left is tracing requirements to design to verification method to verification result.
I’m curious how you handle design docs when requirements change significantly during implementation. At some point, updates and corrections can start describing a somewhat different project from the one that originally went through review.
Is there a rule of thumb for when it’s enough to update the existing document, and when the design has changed enough to justify a new design doc and another review?
My rule of thumb is to ask myself, "Is there a chance my reviewers would not have signed off had this been in the design doc they reviewed?" If the answer is yes, I send it out for a follow-up and explain why I had to change the design.
In my experience, the response from my reviewers is generally, "Yeah, that's fine." It's a combination of (1) the practical limitations that it's hard for them to get the whole design back into mental context to argue about it and (2) they trust that I'm taking the design seriously and have thought this through. I think occasionally, I've sent a post-approval change out and someone points out something
It's common to encounter a curveball nobody anticipated at design time, but if you just go rogue and unilaterally make design decisions, it degrades trust and undermines the review process, so I want my reviewers to know that I'm taking their feedback seriously.
I've found the design doc itself is relatively useless once it has been created, but that the act of creating the design doc is an indispensable part of the process. Spending time and getting your thoughts organized before diving into the team, the management and the editor makes a huge difference.
The real question is "How to keep a software design document up-to-date". I have never seen this done in an efficient way. The first version is ok and over time it deviates more and more from reality.
So far my best experience has been to feed the whole thing into AI and get an overview of the project. That together with a few quick bullet points about the overall purpose of the system is pretty workable.
I answered this in another comment,[0] and I don't think there's widespread agreement on this, but I think design docs should be a short-term doc that lives until the design implementation is complete. I don't think design docs are the right format for a document that has to evolve alongside the code forever.
No feedback on the design doc, except to say it's a good template and very helpful for someone who hasn't worked in a world where design docs have been critical. But can I say we use tinybeans and have a similar complaint (and others), and we would happily jump ship if there was an alternative like that laid out in your example.
I think specs are incredibly valuable for who's writing/developing the software as a thought exercise, and pretty much useless for anyone else, especially after you ship it as it'll always get outdated very quickly.
Isn't much of this made redundant by being part of an existing system? Also, this level of detail is a recipe for being outdated once the issues and compromises starts coming in
> Isn't much of this made redundant by being part of an existing system?
I haven't found that to be true in my work. If you're only making a minor change to an existing system, then you may not need a design doc, but a significant change to an existing system has as much, if not more, complexity and ambiguity than greenfield development.
> Also, this level of detail is a recipe for being outdated once the issues, compromises and compromises starts coming in
I think this is what people typically get wrong about design docs.
I don't think design docs are a good medium for being the perpetual, living description of the system. I think design docs should capture the design at the time of implementation. You should modify the design docs while you implement the work called for in the design document, but once you're done with that work, you freeze the document and preserve it for posterity only.
The design doc is about a specific change to the system. If you need a doc to describe the high-level architecture of the system as it evolves, that should be a different doc.
Start with a single reviewer who is invested in the topic has been helpful for me. Occasionally it is hard to even find one person with how scatter brained everyone seems to have become lately, but depends on who you work with I guess...
I think getting people to read design documentation was always the challenge; this is not a new thing.
I've both produced documentation and consumed it. When I consume documentation, I don't expect much. And to be honest, I don't like the low signal to noise ratio in typical design documentation. That was always a problem. Any sufficiently complex thing is just hard into a power point friendly diagram. And anything involving boxes and arrows where the number of boxes is 5 at best, is probably not that interesting to think about.
It certainly feels like this is an intrinsic friction point in a world where more and more of the actual code is written by AI. I know in my workflows, reading a design doc of any length is a big tradeoff of time that could be spent building. Which isn't a new problem to have, of course, but as the time from plan->code->review->deploy keeps racing downward, "reading design docs" feels like it's ripe for disruption as far as how much time and attention it takes.
I've never been much for design docs. But I have some projects that are on again/off again and I can lose my train of thought. It seems like having one of these could help a lot with that.
Some of the items in your document seem more like non-functional requirements that I would expect to find in a specification, not a design document,e.g., security, privacy, legal.
Some items in your doc seem more like non-functional requirements that I would expect to see in a specification, not a design document: e.g., security, privacy, legal.
> A good design doc can save you years of development time
Brainstorm with your agent in a new session, ask a thousand questions, at the end ask for a detailed prompt.md to develop an app then tell it to comply
Really nice read. I'll add that it's effective to scope design docs up and down as needed, both in terms of how big your project is and how big your company is. A 50-person startup doesn't need a full design doc with multiple approvers. But a one-pager explaining what you're doing and having some documentation is really helpful even with an engineering team of 5. I'll also still write design docs for code changes that only touch a handful of files, if I feel it's important enough. The process of writing in a concise and precise way for other people to consume also has the positive side effect of making things more clear for yourself, too.
> Interfaces section
Only real criticism I have here, is I would not include any code in a design doc, unless it is really really vitally important. I've seen a lot of design docs (especially in the LLM age, written by more junior staff) which are effectively just an English summary of code. The point of a design doc is (generally) not to explain that you're going to have a WidgetManager and WidgetFactory class and what specific properties and methods they have, it's to explain how the widget creation workflow works and maybe you have the WidgetManager/WidgetFactory in an architecture diagram. As a general rule, if you're starting to include actual code, you've gone too low-level, IMO.
> Not all design decisions are equally important. Some choices are more permanent than others.
At AWS one of the corporate culture memes was calling a decision either a "one-way door" or "two-way door". Just asking yourself the question, if we had to walk this back, is it truly irreversible or just an inconvenience? Turns out most day-to-day decisions are two-way doors, particularly engineering ones. Even if the choice made is wrong and a bunch of work needs to be done to switch back, it's still preferable to what a lot of companies end up in, which is decision paralysis where every change needs approval from multiple committees, resulting in months or years before work can start. Note that this doesn't meaningfully increase the odds the decisions made are the right ones; it just delays the implementation and diffuses responsibility if the wrong decision was made.
> A from-scratch rewrite would never work, and even if you manage to write new code in Rails, you’re still maintaining code in two wildly different languages.
Orthogonal to the article, but this line of thinking (including the link to the classic 2000 "Things You Should Never Do, Part I" article[0]) may be worth reviewing in the post-LLM world; for all their flaws, LLMs are spectacular at language-to-language translation, and we already have one major project released[1] that shows porting a relatively large and mature project from one language to another is possible. Not to say that it's the best use of your time, or that you shouldn't do your due diligence and pick the right language up front, or even that the original 2000 article was about a language-to-language rewrite (the Netscape rewrite was an architectural redesign).
Thanks for reading and for the thoughtful feedback!
> Only real criticism I have here, is I would not include any code in a design doc, unless it is really really vitally important.;
Yeah, that's fair. If I were setting guidelines for a large org, I'd maybe discourage code snippets in design docs, as it's hard to know when is too much. At my last company, the dev team was just 3-4 people, and I found it helpful to have little snippets in design docs especially when we're talking about semantics of a new library or how to migrate existing code to a new system.
> Orthogonal to the article, but this line of thinking (including the link to the classic 2000 "Things You Should Never Do, Part I" article[0]) may be worth reviewing in the post-LLM world; for all their flaws, LLMs are spectacular at language-to-language translation, and we already have one major project released[1] that shows porting a relatively large and mature project from one language to another is possible.
Yeah, I agree this could change with LLMs, but I think Joel is still correct up to today. Bun is an interesting case because it's friendliest possible conditions for an LLM rewrite (self-contained inputs and outputs, easy to test old implementation and new implementation side by side, huge test corpus w/ third-party tests). I haven't followed it closely, but it seems like the jury's still kind of out as to whether the rewrite was a good idea.
- One of the things about design you notice as you get older, is the bigger a software application is, the worse your options are later on. The design doc can be considered a proxy for the application: the bigger your design doc, the bigger the application will be. You should still try to think about as much of the app as you can in your design doc (don't intentionally try to make it small and miss things). But if you start to notice this doc is getting pretty heavy, that may be a hint that the application is trying to do too much.
- Next suggestion: make C4 diagrams and split up your design doc by each level. You don't need to make perfect C4s, or even have a good handle on how to define them. You just need four levels of abstraction by which you'll give the reader a picture of how your application works and fits into larger concepts. This will help you and the reviewers understand it better, and will likely also elicit more questions, which helps you better define the design.
SLOs encompass everything else because they're the objective of your product/service/application. Monitoring & Alerting comes from the Interfaces & Logging because the purpose of the Monitoring & Alerting is to "consume" your Interfaces & Logging, in order to meet your SLOs. Security / Privacy / Legal are under SLOs because the extent to which you perform all those things again comes from SLAs (which are basically a bunch of SLOs combined with legal stuff). Infrastructure comes from SLOs because you can't meet your SLOs/SLAs without Infrastructure built to fit them.
Claude, write a skill to create design docs as per this blog post /s
In all seriousness a big chunk of my work is reviewing docs and 100% of the design docs I read these days are generated and there is a lot of slop. I have to parse them with AI to make sense of them, contributing to the problem. I wish people would follow a sensible set of rules like this one.
Did anyone have any solution to this dread? Or cracked the code on how to write docs that have other agents as their primary audience?
I’d say don’t bother trying to parse it alone. Have a meeting where the person that created it presents it, and drill into anything weird.
If you can back them into a corner and force them to admit they don’t even understand something they supposedly wrote, use that as an opportunity to remind people it’s not acceptable to generate design documents that you don’t understand and then push them off onto other people.
I've never experienced a situation where a software design document meaningfully improved the overall process. At best, it helps to keep the business in sync at the expense of a much longer delivery timetable. Even high level software delivery contracts never seem to stay on rails for very long.
It is often faster to just build the damn thing and see where it lands. Software is not like a nuclear power plant or offshore oil platform. You do not need to prove a whole lot of things in advance of construction. No one actually has to give you permission to do anything. You can email a link of a vertical slice prototype to the business whenever you feel like it. That can be the "design document".
OP here!
I'll admit a lot of bias because I think design docs are extremely useful, but I find that when people hate design docs, it's almost always for one of two reasons:
1. The developer has worked on teams where design docs are viewed as a pointless ritual, so authors treat them as a pointless requirement and write bad docs and their teammates view them as pointless so they don't bother giving useful feedback, reinforcing everyone's belief that they're a pointless ritual.
2. The developer does not like other people questioning their engineering choices, and they know that it's harder for their teammates to push back on finished code than a design doc. Investing in the implementation before design changes the calculus to bias in favor of whatever's already implemented rather than what would have been the ideal implementation. Plus, it's harder for the team to review design decisions of 10k LOC than a 5-page design doc.
I think your framing is fair here. But I'd like to offer an even more complicated/nuanced take:
Designing in a group can be very difficult, and doing it well is a skill set that most people don't naturally have.
I think this explains your point 1. Why do people view designed docs as pointless? Because they really don't have a vision or model for what and effective and healthy collaborative design process would look like.
> Designing in a group can be very difficult, and doing it well is a skill set that most people don't naturally have
Not only is it a skill every participant needs to have, they also all need to have a similar amount of competence and knowledge about the domain as well as the current implementation, otherwise it's mostly pointless ime.
But if all ven diagram circles overlap ... It is nice. I can count the times this materialized (in my professional life) on one hand. So I'm generally more towards the "make a prototype, then explain it to the others. Either it's the baseline for the discussion or the illuminating event that clears up wherever this approach works with that team.
YES - and 3 the the assumption that it needs to be a certain length before it can be considered a design document. Esp. in the age of AI a little guidance to brainstorm on before a random project prompt goes a long way. (Not saying people that don't use design docs just code away thoughtlessly) - experience goes a long way too that's why there's success stories with and without design docs.
I think in the age of AI coding, these rationales are a bit outdated. And if you think they're not - I'm curious to know why you think so.
Not OP, but I think they're way more essential with AI doing a lot of the coding. The biggest thing that AI, even the frontier models, is not great at is staying on topic and actually finishing a project with reasonable priorities instead of ratholing on insignificant details or claiming it's "finished" when it's half done.
The most important thing that a good design doc does is specify what's in and out of scope. The second most important thing is to precisely define common vocabulary - what are the important concepts in the problem you're solving, and how should they relate to each other? All of that information serves to ground the day-to-day work in what's important. I find myself starting every Claude session with "read this doc and get familiar with the world, then we'll get to work on a part of it".
(The same is true when working with humans, especially but not limited to junior engineers who aren't used to managing a project longer than a week or two. AI coding agents just never grow out of that phase.)
For an entire project? Yes I agree. For a feature or a submodule? I think when you work with claude to develop a plan, it's generally pretty good.
I guess my question stems from being rigid how a design doc should be defined, argued over, and then executed by humans. I think some of the details simply don't matter, and if they do, they often can be changed relatively quickly in order to adhere to the new requirement.
Try the claude-mem plugin.
In the age of AI coding, code is cheap. Getting the requirements and high-level architecture nailed down is where the hard engineering challenges remain.
Enter... documentation.
We have debated this a lot in our organization. We are tired of seeing low effort Tech docs that puts the onus on the reader than the writer. I think that the writer should spend at least an order of magnitude of time more than the reader. If not, then the design doc can just be the LLM prompt that generated the document.
I have actually resorted back to hand crafting TDDs and focusing on 1-2 page docs. It is a great way to organize my thoughts and create a shared mind space among other engineers. My 2 cents.
Can you summarize your thoughts into a single prompt that, with the context of the codebase, gets expanded to something that makes sense?
> I think in the age of AI coding, these rationales are a bit outdated. And if you think they're not - I'm curious to know why you think so.
Can you share more about how you think AI invalidates these rationales?
I think we definitely need to have alignment, and documentation to support it. I think this can be at the PRD level, mostly.
For many systems, I'd argue technical documentation to understand how the internals are working can simply be handed off to the robots. Or generated on the fly. And if a requirement on the product level is not met, that can be changed under the hood.
As the other commenter said, "code is cheap" now.
The biggest thing AI enables is cheap code.
That means you could choose to try three (or more) genuine implementations and explore their tradeoffs, instead of making three proposals in a document with one recommended (and the other two usually only provided for contrast).
I do think the design is important to keep around - in particular, the constraints, the communication points, schema, tacit things that might not be clear in code. I am not certain that the design should precede the implementation for features below a certain size though.
Larger efforts need milestones and collaboration and will have multiple people doing implementation, so there's more need to agree schemas, APIs etc up front there.
> The biggest thing AI enables is cheap code.
Agree, but in my experience that doesn't change much about the design doc.
I think it's helpful to the author to be able to say to an AI agent, "Hey, put together this quick prototype," and that informs the design doc. But if the goal is to review the design decisions with the team, I don't see how you get around the design doc. I don't want a teammate to send me 10 KLOC of AI-generated code and ask me to review the design. Even if you told AI to try 10 different ideas and pick the best, I don't trust AI to make the same decisions as my human teammates.
I'm not suggesting using AI generated code as a proposed design.
I would try and get an understanding of design space by giving a good agent a high level goal and seeing what it does, then getting a summary of the approach.
When you do this several times, especially if you give it a steer on some non-functional requirement, you can compare and contrast different approaches.
The idea isn't to prototype so much as to gather information by doing. Prototype, to my mind, suggests other things; shortcuts, stubs, incompleteness. I would actually ask agents to do the whole thing, and find out the full scope. It can be particularly useful revealing side effects.
Pair it with code auditors wearing different hats, of course.
Why do you need to review design decisions with a team anymore?
I get the impression that Fable, when well directed, is better than maybe 80% of SWEs. Maybe more.
[edit: Yes, I'm maybe baiting other users, but I want to know your honest opinions on this.]
IME when starting a project from scratch, detailed upfront architecture specs are pretty much required to keep LLMs from flailing around too much (unless of course you build another cookie cutter CRUD webpage, those can simply copy paste from the millions of examples on the internet).
In a way it's a return to waterfall, just with faster implementation phases.
I think it's more important. AI gets a lot right, but sometimes it gets things wrong. The document might be the only human authored piece of text, and it will help future agents see that something is incorrect in the implementation.
Can you explain in which way they are outdated?
Software is in nuclear plants, cars, oil platforms, pacemakers, everywhere. If one is writing more ‘disposable’ stuff like flashlight apps for smartphones, then sure, as you say. Others are writing serious stuff, and design docs are invaluable.
Same goes for highly regulated financial environments. If you work in banking you generally can't just FTX-and-hope your prototype, which is very much what GP sounds like they're advocating.
For starters you're going to have traceability requirements that can only be satisfied if you have a product requirements document and then often a software design document. Now you might well choose to manage all of that in JIRA and Confluence (or whatever) rather than sitting down and writing an actual document intended to be laid out and printed on paper but the fact remains the documentation exists and, indeed, is a must to satisfy compliance and regulatory frameworks.
As always, the domain you're working in and the organisation you're working for make a huge difference but, as much as there are plenty of places where none of this stuff matters at all, there are also plenty of places where it's incredibly important and that isn't going to change anytime soon.
In every single one of those, you are more concerned with the validation data than with high-level visions of your software.
Documentation is important for platform, and probably nothing else.
at least where i work the onus of "who creates the design doc" ends up on the developer.. who also builds the thing.. and thats just like a 2.5x translation tax on the developer who's realistically putting it together to appease business heads who want to feel involved.
i can think of... zero times where a business-coded person even a technical PM (which is a role i do appreciate btw) has ever come up with an official design doc or specification that didnt suck. creating a good design doc is either going to require an architect/staff or senior engineer to sit down and just do it. the overworked architect or staff engineer inevitably gets dragged in if the developers hands are full, or they just beat the shit out of the developer and fill their calendar up with meetings and make them do it... then they beat the shit out of them again and make them build it.. then they beat the shit out of them repeatedly doing fast follows for months and say "no not like that"
i think everyone wants to take some pride in the org they work at and maybe they feel like they've got the formula for sucess, but i personally haven't seen it. there's always going to be an additional translation tax required of the developer(s) who is/are also building the damn thing at the end of it. cover it in poorly run agile/jira shenanigans and this just slows down the possibility of getting to a super stable state back soooo far.
i actually agree with the guy a couple posts up: do some loose design work, friggen dropkick/prototype and see where it lands and go from there. i like facepalm when i hear that our project guys were planning a project for a year and when it was finally time to move on it every specification they planned out missed all the details. this is totally so much worse now with AI writing everything everyone is putting together.
I reflected upon a consumer product I worked on the other day, in the power tools market, and the damn thing had 3 processors in it.
I mean... when i was golfing, the cart had a gps enabled, cloud connected display that showed the golfers positions in front of us. I had a smart phone and a smartwatch with meter-accurate positioning to take a shot.
Software is beyond everywhere at this point.
It sounds like you’re defining design as UI/UX design. I think most people include (prioritize, even) things like system architecture, performance bounds, etc.
It's mixed for me because there are certain things that I clearly think are needed. For example I'm building a custom network architecture and it's to the point where I'm using frontier models to reverse engineer game clients (while battling against the cyber safety system) for the sole purpose of validating that the network architecture I'm making is, if not "useful" (cause there's the game itself), at least different and superior. And to me the designs out there clearly are evidence of things not designed well and thought through ahead of time and instead a patchwork of hacks.
But then there are aspects I'm missing because while I've thought about the network protocol deeply, I'm not, say, a game developer who's ever gone through the whole game dev lifecycle. There's common patterns with software dev but it ain't it. There are probably so many things I have not thought about w.r.t. the whole deployment process that I'm not sure if letting AI vibe design+code it out is good or if I need to sit down and deeply work out the things I don't even know I don't know.
It's always a set of tradeoffs between things.
It's been quite helpful when your project needs expertise from other people, and you want them to vet your approach and find gaps. Doing the up-front work of explaining the context and structuring the project in an easy to understand way makes it more likely for busy people to engage with it and help you out. Of course, it's helpful as a rubber-duck exercise on its own, so I would err on creating one, even if just for myself, for anything high-risk or hard to change later.
The software development realm is bigger than web programming.
> At best, it helps to keep the business in sync at the expense of a much longer delivery timetable.
If you're writing a software design document that slows down your delivery timetable, you're doing it wrong. (Or, more charitably, your business is doing it wrong.) If your design document is to keep the business in sync, you're doing it wrong. That's not what a design document is for. It's for keeping you in sync.
> It is often faster to just build the damn thing and see where it lands.
What are you building? If you don't know, then sure, it's really hard to write a design document. At that point, you're doing exploration, research, not development.
But even when it's an exploration project... once you've found something worth doing, take a day or two and document what you're doing and how you're doing it. Think through all the places in the code you're going to have to touch, all the other things it has to interface with. Make sure you're not going to leave a gaping hole in functionality or, worse, in security.
> Software is not like a nuclear power plant or offshore oil platform.
As others have said, sometimes software is a nuclear power plant or offshore oil platform or airplane or medical device, or even just medical informatics. If you mess up people can die. Sometimes it trades financial instruments, and if you mess up it can destroy the company.
> No one actually has to give you permission to do anything.
On your own time, sure. If you own the company, sure. Otherwise, you need their permission to spend their time on things that they're willing to pay for.
Now, look, it's true that many places go too far overboard on "process". But YOLOing and cowboying isn't the answer either. They aren't even the answer if your single goal is to go as fast as possible. You go faster by spending the appropriate amount of time thinking through what you're building, how you're building it, and making sure you're not missing any of the big things that often trip projects up.
Instead of thinking through all the places in the code the AI is going to have to touch, why not kick off three parallel agents implementing the thing and finding out what they did and the tradeoffs they found?
Planning is essential but it doesn't survive contact with reality. However, AI makes contact with reality cheap! Why not use it to improve designs, by writing the design after a few implementations have already been made?
Only slightly tongue in cheek.
I'm looking for the places that need to be touched, but that wouldn't occur to me (and maybe not to an AI either) while I'm knee-deep in the code. Seeing where the AI touched isn't going to solve that.
If the feature works, and passes AI auditor agents with various hats (thinking of auth and security in particular), did that code you're not thinking of need to be touched? What effect did it have that cannot be captured in side effects, tests or audits?
If what you said doesn't make the AI think of changing that code, why is it going to make the AI auditor think of testing that code? That's what a gap looks like: Nobody changed it, nobody tested it, but some business constraint is now left in an inconsistent state because some piece got updated and another piece did not.
Here's an example. You updated the code that interfaced with the database. But you forgot to update the stored procedures within the database. As a result, the database is now being put in an inconsistent state with every transaction that uses your new code. That is the kind of thing that a software design doc can help you remember, because it is supposed to make you think through all the stuff.
And if you're going to say "Your business stuff shouldn't be able to get into an inconsistent state", well, there's a lot of businesses that have potential landmines laying around. You can say they shouldn't. You're right, in an ideal world. But in this world, they do, and you have to live and work in the world that we have.
Now, in fairness, a good AI check might turn up that the database was left in an inconsistent state... if it understood the constraints well enough. If. I wouldn't want to gamble my production database on the AI's understanding and testing of all the constraints, though.
You have successfully optimized for fast, but you have not optimized for quality, extensibility, customer experience, or maintainability. Fast can be a great thing to optimize for, but there are many other situations where other optimizations are preferable.
Welcome both of you to the agile vs waterfall arguments of 25+ years ago. :)
The agilists I think ended up having pretty good answers for finding a sweet spot between small iterations that maintained quality while minimizing Big Design Upfront to prevent spending a lot of time preplanning the software, allowing a well functioning agile team to maintain reasonably high quality, extensibility, maintainability and satisfaction of actual customer needs while keeping velocity high and not getting bogged down in design heavy tar pits which were ended up not fully anticipating problems encountered during actual execution.
If that doesn't sound like a buzzword filled sentence I never expected to come out my mouth... But. The bottom line is: if you can keep your execution goals small and focused enough, you can iterate quickly towards a design with better information than you would have if you were to do a design study because you'll be better informed by the actual needs of the execution process than by what you _think_ the execution process will require at design time.
> you have not optimized for quality, extensibility, customer experience, or maintainability
A ”software design” document does not optimize for either of those.
Why not? “Customer experience” is arguable, but most design documents I’ve seen involve the others.
The absence of a software design document can definitely harm quality, extensibility, and maintainability.
100%. I find it's generally used as a waterfall practice - i.e. BDUF first with a design document, then implement instead of "implement following conservative assumptions, revisit and refactor aggressively".
The latter being vastly more effective at honing good design because more decisions are made in retrospect.
I find that a spike or a spike PR to demonstrate a new approach (if a software design decision is controversial) is 10x as valuable.
> implement following conservative assumptions, revisit and refactor aggressively > The latter being vastly more effective at honing good design because more decisions are made in retrospect.
Only if people actually do that.
I've joined a project where a design doc should've been written before the first line of code (as per the agreed upon dev process). Developers disregarded that and yolo'd their way to a first prototype. No documentation whatsoever. Then someone else was tasked with writing a design doc for that big ball of mud. You can imagine how that went.
I've joined the project only much later. At every corner I'm dumbfounded by the "design decisions". Refactoring now is a herculean task and kept to the minimum required.
I'm certainly not advocating for waterfall-like "make a plan and stick to it no matter the cost". But looking at the requirements and drafting a coarse design from those goes a long way. At least you can get idea if whatever you have though up is in agreement with the requirements.
Treat the design document as a living document. Do a coarse draft first. Implement. Refine the doc with stuff you've found out, ditch the stuff that didn't work. As a bonus you get a relatively neat on-boarding doc for people joining later.
It's really great just to force thinking through the problem.
Throw the document away, it doesn't have any value.
But thinking through what you are going to do, in some detail, is valuable.
> No one actually has to give you permission to do anything.
For now, in the current context (with ai), it seems like a non-ignorable portion of society now wants to limit what kind of code people can write, Ai is apparently sufficiently like nuclear science that regulation may come to the act of producing code.
> It is often faster to just build the damn thing and see where it lands.
Part of documentation is figuring out if you're building the RIGHT thing. It give the opportunity to get feedback from more than one party.
The usability of most modern (complex) application is deplorable. I see things that a paper prototype with 5 people on the street should have stop dead in its tracks being rolled out with banners and trumpets.
And then no one ever wants to remove an unused or unprofitable feature. There is no bonus for it, no one puts that on their resume. But the feature you launched that really did enshitify the product gets put on there with 3 gold stars.
Your second paragraph is the impetus behind Agile Software, and we've all seen how fantastically that failed. Lots of code pushed out quickly, but also a lot of really shitty products, uncertainty, never-complete projects, dysfunction between teams, etc.
> Software is not like a nuclear power plant or offshore oil platform
No, but it does impact people's lives significantly. How many times has your personal information been leaked by a company making products by people who didn't care? Who would have predicted that a security company's terrible QA would lead to 8.5 million crashed systems, 42,000 delayed flights, 10,000 cancelled flights, and over $10B in economic losses? I'm sure the developers just said "not our problem". But their lack of concern, and "just throw shit at production" mentality, had real world consequences.
Have you never encountered code that you thought was designed fundamentally incorrectly, but was too entrenched to change? That's what design review is for.
Author here. Happy to take any feedback about this post.
I learned to write design docs at Microsoft and Google, and I thought they both had good culture around docs that hasn't percolated out as well as other engineering practices at those orgs. I haven't seen a thorough explanation of how to write design docs, so this is my attempt to externalize what I've learned about writing them.
So I tried this and it failed miserably.
The documentation became the bible, and although I tried to keep the design goals at the conceptual/logical level the following would happen the moment the implementation started:
1. This is ambigous the docs need updating, please refactor your design 2. This doesn't work as the doc stated why did you get this wrong 3. The requirements have changed you need to update it
The burden to get "everything right" was absolutely lumbered of me, and the document became an easy finger pointing exercise, even if blame wasn't intended by those launching the critique the burden of "owning" the doc and the consequences of the doc was real.
Now there's a good chance that I am just a shit documentation writer, I can accept that, but honestly I feel like for the vast majority of organisations this just falls into another step of the waterfall pattern, which just doesn't work.
How do you handle this? What did I miss?
Thanks for reading!
What you're describing sounds like toxic team dynamics rather than something specific to design docs. Do you work effectively with your teammates outside of design docs, or is there similar tension/hostility everywhere?
What you're describing sounds like the design process working as intended (modulo the finger-pointing). The design doc should be unambiguous, and the implementation should match it.
Assuming this isn't just symptoms of a sick team, my other explanation is that your teammates find your deviations from the design doc unexpected. It sounds like you're running into situations where you can't implement the design doc as written, so you're proactively making your own design choices and showing your teammates the implementation. Could you loop your teammates in earlier on before you've implemented the code? Like, "The design docs says we're supposed to use SQLite, but I realized that SQLite doesn't support types the way we expected, so I think we should switch to Postgres for X, Y, and Z reasons."
This is good guidance, but what do you have to say about convincing your team of developers to live it out?
I've found that developers usually like writing code and avoid contributing to documentation. For some, it's actually scary because (edit: for them,) high quality writing is harder than high quality coding, and it can be avoided quite a bit.
On the project side, it's rare for the implementation and verification stages to not consume all the budget and more, and delivery creeping past the original optimistic date. So there's no time or money to spend on documentation.
The combination is that even with your great advice in hand, it's hard to navigate to really solid and comprehensive design documentation underpinning the products.
Thanks for reading!
This is a good question, and I have a super long answer that's been in my head for like 8 years about how to influence your teammates to adopt good engineering practices.
The short answer is that most useful software engineering practices are a risk to the first person on the team to adopt them. For example, if everyone on your team thinks automated testing is stupid and you adopt automated testing, it will look like your work is worse because you're slower in the short-term, and maybe you have to do even more work when teammates break your tests.
It comes down to accruing social currency with your team. Your teammates don't want to take a risk for you if you have a history of bad ideas that wasted everyone's time. But if, for example, you implemented automated deploys to replace a tedious workflow developers had to do manually, people would see how your ideas have payoff, and they're more willing to invest a little bit if they expect ROI long-term.
When I've convinced my teammates to invest in design docs, I made sure I had some wins under my belt before I started pushing for everyone to write design docs. I invested a lot in docs myself so my teammates could see the value before I asked them to start writing.
This is also a place where you have to think about politics a bit. Documentation has a much better shot if it has support from the top, so think about the pitch to your manager or dev lead about how design docs make their jobs easier.
How are design docs changing in the agentic age?
Two suggestions, based on my experience:
1) Add a section called "Potential Changes". This is broader than "missing features", and can include other items too, such as new hardware that might become avaliable, customer requirement changes you might anticipate, possible new technology (e.g. a new database or cloud service that might be useful), multilingual support, etc. Listing some of these often causes reviewers to think of others as well.
Ensuring the design is modular around such changes means implementing any of them will be far easier than if assumptions are hard-coded throughout the codebase.
2) Security and privacy are two aspects of a more general category of "compliance assurance". Those two are worthy of their own categories, but you should have a section covering any other legal, regulatory, or corporate requirements. The plan for auditing these compliances should be listed too.
Often, of course, there are none beyond security and privacy.
Lot of this is outdated. Including stuff that made a lot of sense in the past like diataxis and the google guidance.
I've started to build docs structured as a skill. Since every model/harness is trained to handle skills well today. The entire docs of a project or modeled as a skill.
I also have additional frontmatter on the md files. Specifically 2 keys -> when should you read, when you should not read this doc. This with a simple cli to help parse this has made the docs experience much quicker and nicer.
You can also generate svgs, mermaids etc on the fly now when you are really stuck on something.
Referencing Joel Spolsky's article about how you should never do a rewrite is starting to feel outdated as well.
I think it's worth more scrutiny today, rather than less. Your claude code can barf out "a rewrite" but is it any good? So far the answer is "no" (see anthropic's C compiler, or a more recent port of bun).
Software is still the best specification for existing behavior..
I'm not following because a) The bun rewrite was a success b) the C compiler wasn't a rewrite and c) "Software is still the best specification for existing behavior" seems to imply that rewrites are achievable because we already have a working version that functions as a spec?
Why is diataxis outdated; don't your engineers ever read the code? Don't you think it helps the agents too?
Its just far easier to ask an agent to do the first past ( with references to actual code ) and then start to dig in.
A good implementation of something like this is https://deepwiki.com/ for OSS projects.
The code doesn't usually capture the whys; that is what documentation is good for.
Why do you think diataxis and the google guidance is outdated now?
Sorry for being pedantic.
It reads more like a CONOPS or a software architecture document, but its not detailed enough from a high level perspective, and too detailed at a low level perspective (ie. it has implementation details in a few places you wouldnt expect in a higher level design doc).
In that light, I'm not sure who the audience would be in a corporate environment. Is it for architects, other developers, or yourself?
I was initially turned on to the idea of using specs by Joel Spolsky [https://www.joelonsoftware.com/2000/10/02/painless-functiona...]
I think they're valuable, both because they get you to think through the actual functionality (and underlying implementation) of the software, and the make sure that you and the [person you're developing for] are roughly on the same page. Plus, every edge case or design issue you catch while writing the spec saves you a ton of time.
That said, I think a big weakness of specs is that it's just not possible to write a perfect spec that doesn't have any blind spots and covers all the edge cases and issues you'll run into when actually developing. This makes it more difficult to hold the customer accountable to the spec, since you (the designer and devs) can't really be accountable to the spec unless you want to deliver some overly literal, not-actually-helpful product.
Fun piece of trivia, Joel published one of his functional specs.[0]
As a huge fan of Joel's writing and engineering ideas, I was actually underwhelmed by his spec. It wasn't bad but it also felt like he missed a lot of opportunities to articulate design decisions to the reader more quickly or clearly.
One obvious mistake is that there's over a page (in a 20-page spec) just dedicated to coding conventions and what prefixes variable names will have. I think Joel later conceded that it was a mistake to cover naming conventions in a spec, though I can't find a link now.
[0] https://web.archive.org/web/20051028171624/https://www.joelo...
I definitely agree that it's not perfect. I think he's a great starting point though, because when trying to get engineers to document stuff (something typically approached with similar enthusiasm to having their teeth removed with a hammer) it really helps if the "how to write a spec" doc is somewhat fun to read.
Unrelated - I really dig your "my [x]th year as a bootstraped founder" series.
> A good design doc can save you years of development time.
I only have a few years of experience in this business, but I have seen numerous cases where none of any of this matters. Your perfectly drafted plan could easily be derailed by technical limitations, customer request or company reorg. You are better off use that planning time for something else.
I have worked on DO-178C (aerospace) and IEC 62304 (medical device) software design documents and they are much narrower in scope.
OP's design document is comprehensive enough to cover much of ground of the full documentation package for regulated software submissions. Basically all that's left is tracing requirements to design to verification method to verification result.
I’m curious how you handle design docs when requirements change significantly during implementation. At some point, updates and corrections can start describing a somewhat different project from the one that originally went through review.
Is there a rule of thumb for when it’s enough to update the existing document, and when the design has changed enough to justify a new design doc and another review?
Yeah, this is difficult.
My rule of thumb is to ask myself, "Is there a chance my reviewers would not have signed off had this been in the design doc they reviewed?" If the answer is yes, I send it out for a follow-up and explain why I had to change the design.
In my experience, the response from my reviewers is generally, "Yeah, that's fine." It's a combination of (1) the practical limitations that it's hard for them to get the whole design back into mental context to argue about it and (2) they trust that I'm taking the design seriously and have thought this through. I think occasionally, I've sent a post-approval change out and someone points out something
It's common to encounter a curveball nobody anticipated at design time, but if you just go rogue and unilaterally make design decisions, it degrades trust and undermines the review process, so I want my reviewers to know that I'm taking their feedback seriously.
I've found the design doc itself is relatively useless once it has been created, but that the act of creating the design doc is an indispensable part of the process. Spending time and getting your thoughts organized before diving into the team, the management and the editor makes a huge difference.
The real question is "How to keep a software design document up-to-date". I have never seen this done in an efficient way. The first version is ok and over time it deviates more and more from reality.
So far my best experience has been to feed the whole thing into AI and get an overview of the project. That together with a few quick bullet points about the overall purpose of the system is pretty workable.
I answered this in another comment,[0] and I don't think there's widespread agreement on this, but I think design docs should be a short-term doc that lives until the design implementation is complete. I don't think design docs are the right format for a document that has to evolve alongside the code forever.
[0] https://news.ycombinator.com/item?id=49698580
No feedback on the design doc, except to say it's a good template and very helpful for someone who hasn't worked in a world where design docs have been critical. But can I say we use tinybeans and have a similar complaint (and others), and we would happily jump ship if there was an alternative like that laid out in your example.
I think specs are incredibly valuable for who's writing/developing the software as a thought exercise, and pretty much useless for anyone else, especially after you ship it as it'll always get outdated very quickly.
Isn't much of this made redundant by being part of an existing system? Also, this level of detail is a recipe for being outdated once the issues and compromises starts coming in
Thanks for reading!
> Isn't much of this made redundant by being part of an existing system?
I haven't found that to be true in my work. If you're only making a minor change to an existing system, then you may not need a design doc, but a significant change to an existing system has as much, if not more, complexity and ambiguity than greenfield development.
> Also, this level of detail is a recipe for being outdated once the issues, compromises and compromises starts coming in
I think this is what people typically get wrong about design docs.
I don't think design docs are a good medium for being the perpetual, living description of the system. I think design docs should capture the design at the time of implementation. You should modify the design docs while you implement the work called for in the design document, but once you're done with that work, you freeze the document and preserve it for posterity only.
The design doc is about a specific change to the system. If you need a doc to describe the high-level architecture of the system as it evolves, that should be a different doc.
My problem recently is to have people read design docs I'm writing.
I found this article posted here a while back insightful: https://refactoringenglish.com/blog/useful-feedback-on-desig...
Start with a single reviewer who is invested in the topic has been helpful for me. Occasionally it is hard to even find one person with how scatter brained everyone seems to have become lately, but depends on who you work with I guess...
I think getting people to read design documentation was always the challenge; this is not a new thing.
I've both produced documentation and consumed it. When I consume documentation, I don't expect much. And to be honest, I don't like the low signal to noise ratio in typical design documentation. That was always a problem. Any sufficiently complex thing is just hard into a power point friendly diagram. And anything involving boxes and arrows where the number of boxes is 5 at best, is probably not that interesting to think about.
It certainly feels like this is an intrinsic friction point in a world where more and more of the actual code is written by AI. I know in my workflows, reading a design doc of any length is a big tradeoff of time that could be spent building. Which isn't a new problem to have, of course, but as the time from plan->code->review->deploy keeps racing downward, "reading design docs" feels like it's ripe for disruption as far as how much time and attention it takes.
I've never been much for design docs. But I have some projects that are on again/off again and I can lose my train of thought. It seems like having one of these could help a lot with that.
Some of the items in your document seem more like non-functional requirements that I would expect to find in a specification, not a design document,e.g., security, privacy, legal.
If they constrain design they're relevant. Doesn't mean every legal detail should be in the doc.
Some items in your doc seem more like non-functional requirements that I would expect to see in a specification, not a design document: e.g., security, privacy, legal.
> A good design doc can save you years of development time
Brainstorm with your agent in a new session, ask a thousand questions, at the end ask for a detailed prompt.md to develop an app then tell it to comply
There, saved years of development time in AI era
Really nice read. I'll add that it's effective to scope design docs up and down as needed, both in terms of how big your project is and how big your company is. A 50-person startup doesn't need a full design doc with multiple approvers. But a one-pager explaining what you're doing and having some documentation is really helpful even with an engineering team of 5. I'll also still write design docs for code changes that only touch a handful of files, if I feel it's important enough. The process of writing in a concise and precise way for other people to consume also has the positive side effect of making things more clear for yourself, too.
> Interfaces section
Only real criticism I have here, is I would not include any code in a design doc, unless it is really really vitally important. I've seen a lot of design docs (especially in the LLM age, written by more junior staff) which are effectively just an English summary of code. The point of a design doc is (generally) not to explain that you're going to have a WidgetManager and WidgetFactory class and what specific properties and methods they have, it's to explain how the widget creation workflow works and maybe you have the WidgetManager/WidgetFactory in an architecture diagram. As a general rule, if you're starting to include actual code, you've gone too low-level, IMO.
> Not all design decisions are equally important. Some choices are more permanent than others.
At AWS one of the corporate culture memes was calling a decision either a "one-way door" or "two-way door". Just asking yourself the question, if we had to walk this back, is it truly irreversible or just an inconvenience? Turns out most day-to-day decisions are two-way doors, particularly engineering ones. Even if the choice made is wrong and a bunch of work needs to be done to switch back, it's still preferable to what a lot of companies end up in, which is decision paralysis where every change needs approval from multiple committees, resulting in months or years before work can start. Note that this doesn't meaningfully increase the odds the decisions made are the right ones; it just delays the implementation and diffuses responsibility if the wrong decision was made.
> A from-scratch rewrite would never work, and even if you manage to write new code in Rails, you’re still maintaining code in two wildly different languages.
Orthogonal to the article, but this line of thinking (including the link to the classic 2000 "Things You Should Never Do, Part I" article[0]) may be worth reviewing in the post-LLM world; for all their flaws, LLMs are spectacular at language-to-language translation, and we already have one major project released[1] that shows porting a relatively large and mature project from one language to another is possible. Not to say that it's the best use of your time, or that you shouldn't do your due diligence and pick the right language up front, or even that the original 2000 article was about a language-to-language rewrite (the Netscape rewrite was an architectural redesign).
[0] https://www.joelonsoftware.com/2000/04/06/things-you-should-...
[1] https://bun.com/blog/bun-in-rust
OP here.
Thanks for reading and for the thoughtful feedback!
> Only real criticism I have here, is I would not include any code in a design doc, unless it is really really vitally important.;
Yeah, that's fair. If I were setting guidelines for a large org, I'd maybe discourage code snippets in design docs, as it's hard to know when is too much. At my last company, the dev team was just 3-4 people, and I found it helpful to have little snippets in design docs especially when we're talking about semantics of a new library or how to migrate existing code to a new system.
> Orthogonal to the article, but this line of thinking (including the link to the classic 2000 "Things You Should Never Do, Part I" article[0]) may be worth reviewing in the post-LLM world; for all their flaws, LLMs are spectacular at language-to-language translation, and we already have one major project released[1] that shows porting a relatively large and mature project from one language to another is possible.
Yeah, I agree this could change with LLMs, but I think Joel is still correct up to today. Bun is an interesting case because it's friendliest possible conditions for an LLM rewrite (self-contained inputs and outputs, easy to test old implementation and new implementation side by side, huge test corpus w/ third-party tests). I haven't followed it closely, but it seems like the jury's still kind of out as to whether the rewrite was a good idea.
it would not be "fun" to financially penalize my coworkers for their mistakes, no.
Not what he meant, but for an outsider it could be hilarious to watch the company tumble because of that rule.
These are some great tips! I have some notes:
- One of the things about design you notice as you get older, is the bigger a software application is, the worse your options are later on. The design doc can be considered a proxy for the application: the bigger your design doc, the bigger the application will be. You should still try to think about as much of the app as you can in your design doc (don't intentionally try to make it small and miss things). But if you start to notice this doc is getting pretty heavy, that may be a hint that the application is trying to do too much.
- Next suggestion: make C4 diagrams and split up your design doc by each level. You don't need to make perfect C4s, or even have a good handle on how to define them. You just need four levels of abstraction by which you'll give the reader a picture of how your application works and fits into larger concepts. This will help you and the reviewers understand it better, and will likely also elicit more questions, which helps you better define the design.
Example C4 layout:
SLOs encompass everything else because they're the objective of your product/service/application. Monitoring & Alerting comes from the Interfaces & Logging because the purpose of the Monitoring & Alerting is to "consume" your Interfaces & Logging, in order to meet your SLOs. Security / Privacy / Legal are under SLOs because the extent to which you perform all those things again comes from SLAs (which are basically a bunch of SLOs combined with legal stuff). Infrastructure comes from SLOs because you can't meet your SLOs/SLAs without Infrastructure built to fit them.This is not levels of abstraction, it's a dependency graph.
Claude, write a skill to create design docs as per this blog post /s
In all seriousness a big chunk of my work is reviewing docs and 100% of the design docs I read these days are generated and there is a lot of slop. I have to parse them with AI to make sense of them, contributing to the problem. I wish people would follow a sensible set of rules like this one.
Did anyone have any solution to this dread? Or cracked the code on how to write docs that have other agents as their primary audience?
>Did anyone have any solution to this
Yes. Don’t “write” your design docs with AI. If you can’t personally enforce that, get your manager to.
I’d say don’t bother trying to parse it alone. Have a meeting where the person that created it presents it, and drill into anything weird.
If you can back them into a corner and force them to admit they don’t even understand something they supposedly wrote, use that as an opportunity to remind people it’s not acceptable to generate design documents that you don’t understand and then push them off onto other people.
Yeah, this. If it's slop, reject it, and tell them why.