How to Write an Effective Software Design Document

(refactoringenglish.com)

166 points | by fagnerbrack 2 hours ago

15 comments

  • Tsarp 3 minutes ago
    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.

  • bob1029 32 minutes ago
    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".

    • mtlynch 17 minutes ago
      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.

      • luc_ 15 minutes ago
        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.
        • GeneralMayhem 6 minutes ago
          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.)

        • mtlynch 9 minutes ago
          > 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?

        • flohofwoe 8 minutes ago
          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.

        • biofox 7 minutes ago
          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.

        • ambicapter 9 minutes ago
          Can you explain in which way they are outdated?
    • 1over137 22 minutes ago
      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.
      • bartread 11 minutes ago
        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.

      • superxpro12 4 minutes ago
        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.

    • tobyjsullivan 24 minutes ago
      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.
    • pif 20 minutes ago
      The software development realm is bigger than web programming.
    • felixgallo 29 minutes ago
      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.
      • phuff 22 minutes ago
        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.

      • fmbb 24 minutes ago
        > you have not optimized for quality, extensibility, customer experience, or maintainability

        A ”software design” document does not optimize for either of those.

        • blanched 3 minutes ago
          Why not? “Customer experience” is arguable, but most design documents I’ve seen involve the others.
    • pydry 15 minutes ago
      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.

    • verdverm 21 minutes ago
      > 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.

    • 0xbadcafebee 19 minutes ago
      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.

  • mtlynch 59 minutes ago
    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.

    • hermitShell 3 minutes ago
      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.

    • verdverm 25 minutes ago
      How are design docs changing in the agentic age?
  • nseskin 15 minutes ago
    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?

    • mtlynch 1 minute ago
      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.

  • zumtrotz 23 minutes ago
    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?

  • randusername 39 minutes ago
    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.

  • baalimago 19 minutes ago
    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
    • mtlynch 10 minutes ago
      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.

  • esposito 34 minutes ago
    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.
  • acrophiliac 21 minutes ago
    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.
  • acrophiliac 22 minutes ago
    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.
  • jimbobimbo 37 minutes ago
    My problem recently is to have people read design docs I'm writing.
  • mjr00 41 minutes ago
    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

    • mtlynch 28 minutes ago
      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.

  • 0gs 1 hour ago
    it would not be "fun" to financially penalize my coworkers for their mistakes, no.
    • bithammerthunde 57 minutes ago
      Not what he meant, but for an outsider it could be hilarious to watch the company tumble because of that rule.
  • 0xbadcafebee 25 minutes ago
    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:

      SLAs & SLOs
        - Interfaces & Logging
          - Monitoring, Alerting
          - Dependencies
        - Security / Privacy / Legal
        - Infrastructure
    
    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.
  • gbrindisi 36 minutes ago
    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?

    • 1over137 19 minutes ago
      >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.