A team starts coding the week after the requirements are agreed. Three months later the client asks for a second currency. The answer: "that means rebuilding checkout".

The requirements were fine; the step in between was missing. The software design phase turns a list of what the software must do into a plan for how it will do it, and that plan decides how expensive every later change will be.

What is the design phase in the software development life cycle?

Software design is the phase of the software development life cycle where the team decides how the system will be built: how it is split into parts, where the data lives, how the parts talk to each other and to other systems, and what users will see on the screen.

It comes straight after the analysis phase in the software development life cycle. Requirements analysis answered "what are we building?". Design answers "how?", and its output is a blueprint the development team can build from and the testers can check against.

The phases of the software development life cycle: planning, requirements, design, development, testing, deployment and maintenance. This article covers design. Requirements, design, testing and maintenance each have a post in this series. previous: requirements; next: testing.THE SOFTWARE DEVELOPMENT LIFE CYCLEPlanningRequirementsDesignDevelopmentTestingDeploymentMaintenanceyou are herea post in this seriesprevious: requirements; next: testing
Design is the third phase of the cycle, between requirements analysis and development.

This post continues our series on the phases of the software development lifecycle. The previous one covered software requirements analysis, which produces the input for this phase; the series also covers testing and maintenance, where the quality of the design shows most.

A useful comparison is a building. Requirements say a family of five needs four bedrooms and a garden. Design is the architect's drawings: where the load-bearing walls go, where the pipes run, which rooms face south. You can move furniture later at little cost. Moving a load-bearing wall is a different matter.

What does good software design buy you?

Is design worth the weeks it takes, or is it paperwork that slows the team down? The honest answer: the time saved by skipping design comes back later, with interest.

Martin Fowler, one of the best-known writers on software development, describes what happens without it. Shortcuts make the code harder to work with, and "developers find poor quality code significantly slows them down within a few weeks" (martinfowler.com). In other words, the payback for good internal design is not years away. It starts within the first release.

The bill adds up across an industry. The Consortium for Information and Software Quality estimated the accumulated technical debt in US software systems at about $1.52 trillion in its 2022 report (CISQ). Technical debt is the cost of all the shortcuts that someone will eventually have to pay for, usually during maintenance.

Good software design pays back in three ways that a business notices: new features cost roughly what you expect, the system copes when usage grows, and new developers can understand it without months of archaeology.

High-level and low-level software design

Software design happens at two levels, and they answer different questions.

High-level designLow-level design
AnswersHow the system is split into parts, and how the parts talk to each other and to the outside worldHow each part works inside
IncludesArchitecture diagrams, technology choices, integrations, hosting, the approach to security and scalingComponents and modules, database tables, API definitions, error handling, screen-by-screen behavior
Who reads itBusiness stakeholders, the architect, the whole development teamSoftware developers and testers
When it happensBefore development startsJust before each part is built, feature by feature in an agile project
Cost of changing it laterHigh: it shapes everything built on topModerate: it stays inside one part

High-level design: the software architecture

High-level design is the big picture. It decides the main parts of the system and how they fit together: one application or several services, which database, which cloud, how the system connects to your ERP, payment provider or CRM, and how it will stay secure and fast as usage grows.

These are the decisions that are hardest to change later, which is why they deserve the most care. A popular way to draw them is the C4 model by Simon Brown, which its site describes as "an easy to learn, developer friendly approach to software architecture diagramming" (c4model.com). It works like a map you can zoom into, from the whole system down to individual classes.

The four levels of the C4 model as nested boxes, each a zoom into the one before. Level 1, system context: the system, its users and the systems it talks to, for everyone. Level 2, containers: the applications and databases inside it, for the whole team. Level 3, components: the building blocks inside each application, for developers. Level 4, code: classes and tables, usually generated from the code. High-level design lives at levels 1 and 2, low-level design at levels 3 and 4.FOUR LEVELS OF ZOOM: THE C4 MODELWHAT IT SHOWS, AND FOR WHOM1 System contextThe system, its users and thesystems around it. For everyone.2 ContainersApplications and databasesinside it. For the whole team.3 ComponentsBuilding blocks inside eachapplication. For developers.4 CodeClasses and tables, usuallygenerated from the code.class InvoiceMatchertable invoiceHigh-level design lives at levels 1 and 2; low-level design at levels 3 and 4.
The C4 model's four levels, each a zoom into the one before. The first two are worth showing to business stakeholders; the last two are for the development team.

The first level is the one to ask for as a client. A system context diagram fits on one page and shows your system, its users and every system it connects to. If nobody can draw it, the design is not finished.

Low-level design: components, data and interfaces

Low-level design zooms in. It describes the building blocks inside each application, the database tables and the interfaces (APIs) through which parts of the system and outside systems exchange data. It is mostly written by and for software developers.

In an agile development process, low-level design is not done all at once. The team designs each part shortly before building it, within the frame the high-level design has set. That keeps the detail close to the moment it is needed, when the team knows the most.

User experience and interface design

The third strand of design is what users see and do. UX designers turn the user requirements into flows and screens, usually as clickable prototypes in a tool such as Figma.

A prototype is the cheapest test there is. Ten minutes of a real accountant clicking through a mockup of the invoice screen will reveal more misunderstandings than a week of reading specifications. Fixing a screen in a prototype takes an afternoon; fixing it after it has been built takes a sprint.

The software design process, step by step

Every software development process handles design a little differently, but the same five steps come up again and again.

1. Start from the requirements, especially the non-functional ones

The architect reads the requirements with one question in mind: which of them will shape the structure of the system? Usually it is the non-functional requirements: how many users, how much data, how fast, how available, which regulations. Two software systems can have the same features and need completely different designs: one for 50 internal users, the other for 5 million customers.

This is also where gaps from the analysis phase surface. If nobody knows the expected data volumes, it is better to find out now than to guess.

2. Choose the architecture and the technology

Next come the big decisions: how to split the system, which programming language, framework and database, where it will run, and how it will connect to the systems around it.

The best choice is rarely the newest. It is the one that fits the requirements, the skills of the team who will maintain the system, and the time it has to run. A system that will run a business for ten years needs technology that will still be supported in ten years. For long-lived business systems we usually choose Java for that reason; our post on the use of Java in software development explains why.

3. Model the data and the interfaces

Data usually outlives the code that handles it, so the data model deserves particular care. Which things does the system keep track of (customers, invoices, contracts), how are they related, and which system is the source of truth for each one?

The same goes for interfaces. Every connection to another system is a contract: what is sent, in which format, and what happens when the other side is slow or down. Agreeing these contracts early lets teams work in parallel and avoids nasty surprises at integration.

4. Design the screens and test them with users

In parallel, the UX designer turns user requirements into flows, wireframes and prototypes, and tests them with real users. Collaborative whiteboards such as Miro help here too, for mapping user journeys with the stakeholders in the room.

5. Review, record the decisions and hand over

Before development starts, the design is reviewed: by the development team, who will build it, by testers, who will check it, and by the client, who should at least see the system context and the key screens.

Then the important decisions are written down. A lightweight format that many teams use is the architecture decision record, proposed by Michael Nygard in 2011: a short note with a title, the context, the decision, its status and its consequences (Cognitect). Here is one, simplified from a real project of ours:

An architecture decision record, simplified from one of our projects. Title: serve availability search from an in-memory data grid. Status: accepted. Context: availability search runs on dozens of SQL Server machines, 99% of queries are reads, and one more machine adds 2% cost and 0.1% throughput. Decision: load the data every availability query needs into an in-memory grid, keep SQL Server as the system of record and send intraday updates by queue. Consequences: queries never touch the database and throughput grows with each node; a fast loader and an update pipeline have to be built, tested and run.ARCHITECTURE DECISION RECORD 07Serve availability search from an in-memory data gridAcceptedContextAvailability search runs on dozens of SQL Server machines. 99% ofqueries are reads; one more machine adds 2% cost and 0.1% throughput.DecisionLoad the data every availability query needs into an in-memory grid.Keep SQL Server as the system of record; send intraday updates by queue.Consequences+ Queries never touch the database; throughput grows with each node.− A fast loader and an update pipeline to build, test and run.
A decision record in Michael Nygard's format, simplified from a design decision on a hotel metasearch engine we rebuilt. The engine now serves 300 million queries a day at 80% lower infrastructure cost.

A year from now, someone will ask why the system works the way it does. A record like this answers the question in two minutes, and it shows which decisions were deliberate and which were accidents.

Diagrams belong in the same place. Tools such as draw.io or Structurizr, which builds C4 diagrams from a text model, let the team keep them next to the code, where they have a chance of staying current.

Who takes part in the design phase

Design is led by the people who will build the system, with the people who asked for it close by:

  • The architect owns the high-level design and the big technical decisions.
  • Software developers from the development team review the design and often write the low-level parts themselves. A design the developers have not seen is a design they will work around.
  • The UX designer owns flows, screens and prototypes.
  • The business analyst keeps the design honest against the requirements and answers the questions that come up.
  • A tester checks early that every important requirement can actually be tested in the planned design.
  • On the client side, the product owner or system owner reviews the key decisions and the prototypes, and makes the calls when a requirement turns out to be expensive.

How long it takes, and what you should get at the end

For a first release of moderate scope, design and architecture usually take two to four weeks in our projects, overlapping with the end of discovery and the start of development (see the timeline in our guide to custom software development). Many integrations or a regulator's review add to it.

At the end of this stage of the software development life cycle you should have, at a minimum:

  • A one-page system context diagram and an architecture overview you can understand without a developer in the room.
  • The main technology choices, with the reasons for each.
  • A data model and a list of integrations, with who owns each interface.
  • Prototypes of the key screens, tested with real users.
  • A plan for the non-functional requirements: performance targets, security approach, hosting and backups.
  • Decision records for the choices that will be expensive to change.
  • A first test strategy, so the testing phase knows what "working" means.

If a team cannot show you these, ask what the developers are building from.

Common software design mistakes

Most software design problems fall into a few familiar patterns, and each of them costs more the later in the software development life cycle it is found.

  • Over-engineering. Designing for millions of users when you have thousands, or splitting a simple system into dozens of services. It adds cost and complexity on day one for benefits that may never arrive.
  • Under-designing. The opposite mistake: no design at all, just "we'll figure it out as we code". It feels fast for the first few weeks.
  • Choosing technology by fashion. A tool that looked impressive at a conference may have few people who can maintain it in five years.
  • Ignoring the non-functional requirements. Performance and security added at the end usually means redesigning the parts that were already built.
  • Designing once and never again. Design is not a document you file. As the team learns during the development process, the design should be updated, and the decision records tell everyone what changed and why.
  • Designing without the people who build. A design handed down from an architect who will not be on the project rarely survives contact with the code.

Design decisions in our projects

Most of our work is on systems that have to run for years, so we spend real time on design: in our experience it is the phase of the software development life cycle where an hour of thinking saves the most work later. A few examples of what that looks like in practice:

The hotel metasearch engine in the decision record above had reached a point where adding a database server raised cost by about 2% and throughput by about 0.1%. No amount of coding would have fixed that; it took a design decision. After the redesign the engine absorbed 50% more traffic, to 300 million queries a day, at 80% lower infrastructure cost (case study).

For a real estate management company we built a construction project management system with the map inside the data model, not added on top as a widget, so the system can identify the stakeholders affected by a project from the infrastructure itself (case study). That was a design decision made in the first weeks, and the whole product rests on it.

FastPost, the accounting platform we built for Legerity, was designed from the start around in-memory processing and a modular architecture, so each new feature was a natural extension rather than a rework. It processes a billion financial transactions in under an hour, and we kept evolving it for nearly ten years (case study).

A design is only as good as the evidence that the built system matches it. That is the subject of the next post in our series on the software development lifecycle, on software testing. If you are planning a system and want an architect's view of the design before you commit, book a thirty-minute scoping call: you get a written view of scope and price model within a week, and an honest answer if we are not the right team for it.