Imagine a small appointment-booking service. A customer sees available times, chooses one and receives a confirmation. The screen is only one part of the service: something must check availability, save the booking and make sure another customer cannot take the same time.
System design decides how these parts work together to meet the user’s needs. It includes where information lives, how requests travel, how failures are handled and how the system is operated. The design may be one application and one database; it does not need to begin with many services.
The customer’s screen is only the starting point. The application, data store and follow-up work must cooperate so the booking result is reliable.
What you’ll learn
Follow a booking request across the parts of a service.
Identify where durable data and important decisions belong.
Explain a design choice using requirements and failure behaviour.
Trace one action from start to finish
Begin with a user action: “book Tuesday at 10:00.” The browser or app sends a request to an application. The application checks who may book, validates the time and asks the database to save the reservation.
A database stores records the service needs later. A request asks another component to do something; a response reports its result. These names describe roles, not mandatory separate machines.
Draw arrows and label what moves along them. “Save booking” is more useful than an unexplained line. Mark which step must succeed before the user sees a confirmation. A good diagram explains behaviour, not just a collection of product logos.
A request journey is easier to reason about when each step has a clear responsibility and the “must succeed before confirmation” point is visible.
Decide which result is authoritative
Two customers can both see the same available time before either booking finishes. Checking availability on the screen is therefore not enough. The saved reservation needs a rule that prevents both requests from owning that time.
For this example, a database uniqueness rule and a correctly handled transaction can enforce one booking for one slot. A transaction groups related data changes under the database’s guarantees. The application must handle a conflict and tell the second customer the slot is no longer available.
Keep the booking in durable storage before reporting success. A process’s memory can disappear on restart. Confirmation emails and convenient cached lists can be derived from the saved booking, but are not substitutes for the booking record.
When two people race for the same slot, the reliable decision must come from the authoritative write path, not from whichever screen looked available first.
Choose the order of the booking flow
◇
Build a small decision record
Compare the visible consequences. With JavaScript enabled, choose an option in each scenario to assemble your decision record.
This is an exploratory design exercise. It does not run infrastructure, measure capacity or replace the lesson’s quiz.
All choices and their consequences are visible. Select one choice in each scenario to assemble a design note; revise it as assumptions change.
Explore two choices for the same small service. The cards show what each choice implies. Select an option in both scenarios and read the combined design note.
For this lesson, a confirmed reservation must survive an application restart. Email delivery may happen later, but the user must receive an honest booking result. The exercise changes a design note, not a running database.
Ask what happens when a step fails
A database failure, a slow network or an unavailable email provider can interrupt the journey. State what the user sees, which work has already happened and how the service recovers.
A missing response does not prove the operation failed. If the booking committed but the response was lost, repeating the request needs to recognise the same intended action or safely check the saved result. This is part of retry and duplicate-handling design.
Look beyond the happy path. A service needs deployment, logs and metrics, backups and a way to investigate incorrect behaviour. More components add more relationships to understand; add them when a requirement justifies the work.
Failure handling becomes clearer when you separate “did the booking commit?” from “did the user see the result?” and “did the follow-up action complete?”
Use tools to express a decision
A notebook, a diagram tool and a short decision record are enough to begin. Write the problem, assumptions, chosen approach, alternatives and the main cost or limitation. Someone else should be able to follow the reasoning without hearing the original conversation.
The C4 model offers diagram views at different levels of detail. Azure’s architecture guidance connects requirements with architecture choices. These are references for communicating and evaluating designs, rather than instructions to use every cloud component. Official sources checked 6 October 2026.
Use capacity estimation when volume matters, and measure actual behaviour when choosing software or hardware. A box labelled “database” does not state its guaranteed throughput.
You do not need a huge tool stack to begin. Clear notes, a readable diagram and a short decision record already support a useful review.
Check your design reasoning
Check your design reasoning
Connect responsibilities with the pattern group
Use the design-pattern guide to distinguish local object structure from service-level coordination. The difference matters when a diagram promises durable or cross-process behaviour.
Begin with one honest request journey
System design connects a user’s action with the components, data and operations that make it work. Trace one request, choose where the authoritative result lives and describe failures as carefully as success.
Start with the simplest arrangement that meets the requirements. Explain the choices, validate their assumptions and add complexity when it solves a concrete problem.
Reaching the recap and completing the quizzes are separate milestones.