What system design is (and is not)
35 min · Beginner
System design is deciding which big parts a software system needs, how they talk to each other and how they keep working as users grow. You write down what the system must do and how well it must do it, then choose boxes and arrows that meet those numbers.
High-level design vs low-level design
High-level design (HLD) shows the boxes of a system and the data flowing between them: the app, the servers, the database, and how many users they must serve. Low-level design (LLD) zooms into one box and shows its classes, methods and patterns.
High-level design (boxes and arrows): [Customer's phone] --HTTPS--> [ShopLite server] --SQL--> [(MySQL database)]Low-level design (classes inside one box): ShopLite server: OrderController -> OrderService -> OrderRepositorySection 19 was low-level design: OrderService, the Strategy pattern, a parking lot class diagram. This section is high-level design: how many ShopLite servers, where the data lives, what happens when one part fails. Both are needed, but an HLD question is answered with boxes and numbers, not with class names.
[Name] is a running program ([Name x3] means three copies), [(Name)] is a data store and [[Name]] is a queue; in a quick sketch a plain [MySQL] is fine. A --> B means A calls B and waits for the answer, A ..> B means A hands work off and does not wait, and a label inside an arrow (--SQL-->) says what is sent. Every later module uses this notation; the lesson on drawing architecture diagrams in the last module practises it.Functional requirements: what the system does
A functional requirement is one thing a user can do with the system, written as "who does what": "a customer places an order". Together they define the features.
For ShopLite version 1, the core list is short: browse and search products, place an order, track the order, and an admin who manages products. Writing an out of scope list is just as useful. It tells everyone, including the interviewer, what you are deliberately not building today.
Example 1 · ShopLite functional requirements with a scope list
import java.util.List;
record Feature(String id, String actor, String action, boolean inScope) {}
public class FunctionalRequirementsDemo { public static void main(String[] args) { List<Feature> features = List.of( new Feature("FR1", "Customer", "browses products by category and searches by name", true), new Feature("FR2", "Customer", "places an order for the products in the cart", true), new Feature("FR3", "Customer", "tracks an order: PLACED, SHIPPED, DELIVERED", true), new Feature("FR4", "Admin", "adds products and changes price and stock", true), new Feature("-", "Customer", "writes product reviews with photos", false), new Feature("-", "Seller", "lists their own products (marketplace)", false));
System.out.println("In scope for version 1:"); for (Feature f : features) { if (f.inScope()) { System.out.println(" " + f.id() + ": " + f.actor() + " " + f.action()); } }
System.out.println("Out of scope for now:"); for (Feature f : features) { if (!f.inScope()) { System.out.println(" " + f.actor() + " " + f.action()); } } }}In scope for version 1: FR1: Customer browses products by category and searches by name FR2: Customer places an order for the products in the cart FR3: Customer tracks an order: PLACED, SHIPPED, DELIVERED FR4: Admin adds products and changes price and stock Out of scope for now: Customer writes product reviews with photos Seller lists their own products (marketplace)
What this code does
- Each
Featureis one "who does what" line. TheinScopeflag splits version 1 from later ideas, so the list doubles as a scope agreement. - Reviews and a seller marketplace are real features, but leaving them out keeps the first design small enough to finish and explain.
Non-functional requirements: how well it must work
A non-functional requirement (NFR) describes a quality of the whole system, not a feature: how fast, how reliable, how big. Two shops can have the same features and very different NFRs.
Six NFRs come up again and again:
- Latency: how long one request takes ("under 300 ms"). Availability: how much of the time the system works ("99.9% of a month").
- Consistency: every user sees correct, agreed data (stock never below zero). Durability: saved data is never lost.
- Scalability: the system can handle more users by adding resources.
- Cost: what the servers and services cost each month.
Example 2 · ShopLite NFRs, each with a target
import java.util.List;
record Quality(String name, String target) {}
public class NonFunctionalDemo { public static void main(String[] args) { List<Quality> qualities = List.of( new Quality("Latency", "product page answers in under 300 ms for 95% of requests"), new Quality("Availability", "checkout works 99.9% of the time in a month"), new Quality("Consistency", "stock never goes below 0; a paid order is never shown as unpaid"), new Quality("Scalability", "handles 10x normal traffic on sale day by adding servers"), new Quality("Durability", "a confirmed order is never lost; daily backups kept 30 days"), new Quality("Cost", "servers cost under Rs 20,000 a month in year 1"));
System.out.println("ShopLite non-functional requirements"); for (Quality q : qualities) { System.out.printf(" %-13s %s%n", q.name(), q.target()); } }}ShopLite non-functional requirements Latency product page answers in under 300 ms for 95% of requests Availability checkout works 99.9% of the time in a month Consistency stock never goes below 0; a paid order is never shown as unpaid Scalability handles 10x normal traffic on sale day by adding servers Durability a confirmed order is never lost; daily backups kept 30 days Cost servers cost under Rs 20,000 a month in year 1
What this code does
- Every line names a quality and a target you can measure or check, such as
300 ms,99.9%orRs 20,000. - Notice that none of these is a feature. The same four features could have a target of 3 seconds or 300 ms, and that choice changes the design.
From a vague prompt to a requirements list with numbers
A design prompt is usually vague on purpose: "Design a shop." Your first job is to ask questions and write the answers down as a short list: functional requirements, then NFRs with numbers. "Fast" cannot be checked; "under 300 ms for 95% of requests" can.
When the interviewer does not give a number, assume one and say it aloud: "I'll assume 1 lakh daily users and 5% of them order." Simple arithmetic on those assumptions then tells you how big the problem is, for example how many page views each order brings.
Example 3 · Spotting vague requirements that have no number
import java.util.List;
public class VagueRequirementCheck { static final List<String> VAGUE_WORDS = List.of("fast", "scalable", "always", "many", "quick", "secure");
static boolean hasNumber(String text) { for (char c : text.toCharArray()) { if (Character.isDigit(c)) { return true; } } return false; }
static String check(String requirement) { String lower = requirement.toLowerCase(); for (String word : VAGUE_WORDS) { if (lower.contains(word) && !hasNumber(requirement)) { return "VAGUE: \"" + word + "\" with no number"; } } return "OK"; }
public static void main(String[] args) { List<String> requirements = List.of( "The site should be fast", "Product page loads in under 300 ms for 95% of requests", "The system must be scalable", "Take 2,000 orders per minute on sale day", "It should always be up", "Checkout is available 99.9% of each month");
for (String r : requirements) { System.out.printf("%-56s %s%n", r, check(r)); } }}The site should be fast VAGUE: "fast" with no number Product page loads in under 300 ms for 95% of requests OK The system must be scalable VAGUE: "scalable" with no number Take 2,000 orders per minute on sale day OK It should always be up VAGUE: "always" with no number Checkout is available 99.9% of each month OK
What this code does
checkflags a requirement that uses a word like "fast" or "always" but contains no digit. Those are the lines an interviewer will push back on.- The fixed versions say exactly what "fast" or "available" means, so you can later check whether a design meets them.
Example 4 · Turning "design a shop" into numbers
public class ShopNumbersDemo { public static void main(String[] args) { // Assumptions, written down and said aloud in the interview long dailyUsers = 100_000; double buyerShare = 0.05; // 5 in 100 visitors place one order int pagesPerUser = 20; // product and search pages per visit int peakFactor = 5; // busiest hour vs the daily average long secondsPerDay = 86_400;
long ordersPerDay = Math.round(dailyUsers * buyerShare); long viewsPerDay = dailyUsers * pagesPerUser; double ordersPerSecond = (double) ordersPerDay / secondsPerDay; double viewsPerSecond = (double) viewsPerDay / secondsPerDay;
System.out.println("Orders per day: " + ordersPerDay); System.out.println("Page views per day: " + viewsPerDay); System.out.printf("Orders per second: %.2f on average%n", ordersPerSecond); System.out.printf("Views per second: %.1f on average, %.1f at peak%n", viewsPerSecond, viewsPerSecond * peakFactor); System.out.println("Reads per write: " + viewsPerDay / ordersPerDay + " page views per order"); }}Orders per day: 5000 Page views per day: 2000000 Orders per second: 0.06 on average Views per second: 23.1 on average, 115.7 at peak Reads per write: 400 page views per order
What this code does
- Four written assumptions give the size of the problem: about 116 page views a second at the busiest hour and fewer than one order a second on average.
- The last line is the most useful: 400 reads for every write. A system that is read far more than written points the design towards fast reads, which later modules build on.
How interviewers judge a fresher's design answer
For a fresher, the interviewer is not checking whether you know every tool. They watch how you think: do you ask before drawing, do you state numbers, can you explain why you chose each box and what it costs.
Weak: "I will use microservices, Kafka and Redis so it scales."Strong: "First the requirements: browse, order, track. I'll assume 1 lakh users a day, so about 115 page views a second at peak. One server plus MySQL handles that. I'd add a cache for product pages later; the cost is data that can be a few seconds old."Names like Kafka or Kubernetes with no reason behind them count against you. A simple design with clear reasons and one honest trade-off is a strong answer.
Next step
Check your understanding
10 quick questions