Every design problem is solved twice, at two different heights.
The first pass is flown high. You name the services, draw the arrows between them, decide where state lives, and fix the boundaries, all so the team can agree on the shape of the thing before anyone commits a line of code. The second pass is flown low. You drop into one box on that diagram and specify it down to the classes, the method signatures, the schema, the locking, the algorithm, until it is detailed enough that two engineers would build it the same way.
That is the whole of it. High-level design is the map. Low-level design is the blueprint for one building on the map. Everything people argue about when they argue about HLD versus LLD is really an argument about altitude, and almost every freeze in a design interview is a candidate answering at the wrong height for the room they are in.
This piece is about the two altitudes, why the order between them is not negotiable, and the one skill that separates a staff engineer from a competent one: moving between the heights without being asked, rather than getting comfortable at either. It is the companion to the system design interview framework, which gives you the phases; this gives you the heights those phases move through.
The split is in the standard, not just the folklore
It is tempting to treat "HLD" and "LLD" as interview slang, two acronyms a YouTuber invented to sell a course. They are not. The split is written into the international standard for how you describe a software design.
IEEE Std 1016, the Software Design Description standard, says plainly that it "can be applied to the description of high-level and detailed designs." One document, two altitudes, recognized formally. And the idea is older than the standard. It descends from Yourdon and Constantine's Structured Design in 1979, the book that gave us coupling and cohesion as the criteria for a good boundary. The reason you can blueprint one box in isolation is that a good map minimizes the coupling between boxes and maximizes the cohesion inside each one. When someone asks "why did you draw the service boundaries there," the staff-grade answer is coupling and cohesion, not vibes.
The standard goes further and gives you a non-arbitrary way to decide what belongs at each height. IEEE 1016 defines twelve design viewpoints, and they sort cleanly:
The high-altitude viewpoints are about how the system fits together: context (what is outside the system), composition (what services exist), dependency (how they connect), interface (the contracts between them), interaction (how data flows), and resource (what they run on). These are the map.
The low-altitude viewpoints are about what happens inside one box: logical (the classes), information (the schema), structure (how the classes relate), state-dynamics (the state machine), algorithm (the core logic), and patterns-use (the design patterns applied). These are the blueprint.
You do not need to memorize twelve viewpoints. The point is that "what goes at each altitude" has a citable backbone, and it is not a matter of taste. Context, composition, and data flow are map work. Classes, schema, and state machines are blueprint work.
Why the order is mechanical, not stylistic
People sometimes treat "HLD first" as a polite convention, like reading the introduction before the chapter. It is sturdier than that. The reason HLD comes first is mechanical: the input to the LLD is the HLD.
Lay the canonical comparison next to itself and the load-bearing rows jump out. The high-level design takes the requirements (the software requirement spec) as its input and is produced first. The low-level design takes the reviewed high-level design as its input and is produced second. That second row is the whole argument. You cannot write the blueprint for a box that is not on the map yet, because until the box exists you do not know its responsibilities, its neighbors, or its boundaries. The schema you would design, the locking you would choose, the algorithm you would reach for, all of it depends on what the box is responsible for, and that is decided one altitude up.
This is why "jumping into class definitions and exact schemas" is the most-cited freeze in an HLD round. It is not that detail is bad. It is that you are trying to pour the foundation of a building before anyone has agreed on where the building goes. You burn the clock blueprinting a box that the next two minutes of conversation might delete.
The same logic plays out in real teams, not just interviews. Decide the service boundaries wrong on the map, and every blueprint underneath inherits the mistake. The boundary is the expensive decision; the contents of each box are cheap by comparison, because a well-bounded box can be rebuilt in isolation. That is the original Yourdon and Constantine payoff, low coupling, restated as a project-management fact: get the map right and the blueprints become independent work.
The interview splits the altitudes on purpose
Most companies that take design seriously run the two altitudes as separate rounds, and they grade them on different rubrics. This is not redundancy. It is two different instruments measuring two different things.
The high-level round, the one most people mean by "system design," grades scalability, trade-offs, and distributed-systems reasoning: load balancing, caching, sharding, replication, the consistency model. It is deliberately code-free. Writing a class in a system design round is a category error.
The low-level round, often called the object-oriented design or OOD round, grades the opposite skills: OOP, the SOLID principles, design patterns, clean code, and concurrency-awareness. It expects actual class code and method signatures. Hand-waving "and then a service handles it" in an LLD round is the mirror-image category error.
Companies run both because they are probing for engineering maturity, the ability to design maintainable systems beyond writing isolated functions. And the failure they are watching for is altitude confusion. A candidate who brings distributed-systems vocabulary to an LLD round, or class diagrams to an HLD round, reads as someone who does not understand which altitude they are being tested at. That mismatch is a primary freeze trigger, more than ignorance ever is. You can be smart and still answer the wrong question because you misread the height of the room.
So the first discipline is simply knowing which round you are in, and refusing to leave its altitude until the interviewer pushes you. Bound the problem at the high level first. Descend only when asked, or when you choose to lead the descent.
The seam: where the two altitudes touch
There is one artifact that belongs to both altitudes at once, and it is worth naming because it is where most of the design hinges.
The API, the interface contract, is the last thing you draw on the map and the first thing you build in the blueprint. A method signature is simultaneously a boundary between two boxes and the entry point into one of them. parkVehicle(Vehicle): ParkingTicket is a line on the map (the allocation service exposes this) and the first line of a blueprint (here is what the allocation service does). It is the seam.
This is why good frameworks force you to commit to the API early, before the box-drawing rather than after. Pinning the contract first is what lets the two altitudes be developed independently: once the signatures are fixed, the team building the box and the team consuming it can work without colliding. That independence is the entire purpose of the boundary, and the contract is what enforces it. Spend disproportionate care here. A sloppy box can be fixed quietly inside its own walls; a sloppy contract leaks the mess into every neighbor.
The same problem, flown at both altitudes
The cleanest way to feel the difference is to take one problem small enough to hold in your head and fly it twice. "Design a parking lot" is perfect, because it is a canonical low-level problem that also has a legitimate, if rarely drawn, map.
At the high altitude, the parking lot is a handful of services. Entry and exit gates (stateless). An allocation service that decides which spot a vehicle gets. A pricing service, pluggable, so the pricing rules can change without touching the gates. A state store that holds spot availability and is the single source of truth. The data flow is one line: a vehicle arrives at a gate, the gate calls the allocation service, the allocation service reads and writes the state store, a ticket comes back. The most important sentence on the whole map is "state lives in the availability store," because that one decision will dictate everything at the next altitude down.
At the low altitude, you drop into the allocation box and it explodes into detail. The nouns become classes: ParkingLot, ParkingFloor, ParkingSpot, an abstract Vehicle with Car, Motorcycle, and Truck underneath it, a ParkingTicket, a VehicleSize enum. The verbs become methods: parkVehicle(Vehicle): ParkingTicket, unparkVehicle(ParkingTicket), getAvailableSpots(VehicleSize): int. You reach for patterns, but judiciously: Strategy so the spot-assignment and pricing rules can be swapped without touching gate logic, maybe Observer for availability notifications. And then the part that actually separates the candidates: the concurrency model.
Here is where a high-level claim has to be cashed out. The map said "the allocation service owns spot state." Fine, but how? Lock at the lot level and the design is simple and slow, because two cars on opposite floors block each other for no reason. Lock at the spot level and throughput goes up, but now you can deadlock if one thread holds a floor lock and waits on a spot lock, so you have to order lock acquisition. And if assignVehicle is not synchronized at all, two gates can hand the same spot to two cars. The junior answer is "add synchronized and move on." The senior answer names the granularity, names the hazard it creates, and names the mitigation: "spot-level locking for throughput, with a fixed lock-acquisition order to prevent the floor-then-spot deadlock."
Even the error surface is a design decision at this altitude. Return null when the lot is full and you have built a silent failure the caller will forget to check. Throw ParkingLotFullException and the failure is loud and impossible to ignore. The blueprint owes you the unhappy paths, not just the happy one.
Most people have only ever seen the blueprint for this problem. They do not realize a map exists above it. Drawing the map first, then the blueprint, is the physical demonstration of the zoom, and it is the move worth practicing until it is reflexive.
Cashing the claim: HLD promises, LLD pays
Here is the sentence that, if you internalize nothing else, is the article: a high-level claim is a promissory note, and the low-level mechanism is you making good on it.
The most quotable rule in all of the interview literature puts it bluntly. Do not say "I am going to use Kafka" unless you are very familiar with it, because the next question will be "why Kafka and not something else." Do say "I will use a queue, because I need durable, ordered delivery with back-pressure." The difference is not humility. It is that the second version names the property you actually need, and the property is the decision. The brand is just one implementation of it. (This is exactly the move worked through in Kafka vs queues: pick the delivery semantics first, then argue the broker.)
The failure mode is one line of real hiring-manager feedback: "He described components but never discussed trade-offs." That is the entire thesis as an epitaph. Naming the box without being able to open it fails you at senior level, because anyone can name boxes. The map is cheap. The blueprint is what you are actually being paid for.
So practice the cash-out as a reflex. Every high-level claim has a low-level mechanism waiting behind it, and the interviewer will ask for it:
"It scales horizontally" pays out as a shard key, chosen specifically to avoid hot partitions, which is a decision deep in the consistency and partitioning trade-offs and the replication strategy underneath.
"Retries are safe" pays out as an idempotency key plus a unique constraint and an upsert, the exact mechanism dissected in idempotency and the exactly-once lie. This is the canonical claim-to-mechanism bridge, and it is worth keeping in your pocket as a template for the whole skill.
"Reads are fast" pays out as a number. The word "fast" is worth nothing on its own; the payout is "this path is memory-resident at about 100 nanoseconds versus roughly 150 microseconds from SSD, a difference near 1,500 times, so the cache is load-bearing, not optional." That descent, from an adjective to a measured ratio built out of known constants, is precisely what makes a claim credible. The relevant constants are few and worth memorizing: an L1 cache reference is about half a nanosecond, a mutex lock and unlock around 25 nanoseconds, a main-memory reference around 100 nanoseconds, an SSD random read around 150 microseconds, a spinning-disk seek around 10 milliseconds. A staff engineer reaches for these without thinking, because they are what turn a hand-wave into an estimate. The tail behavior behind those averages, why p99 is the number that actually pages you, is its own topic, covered in latency and the tail.
"Writes are consistent under contention" pays out as an isolation level and a concrete locking choice, the territory of MVCC and isolation levels and, when the contention crosses machines, distributed locks and the leader-election machinery in consensus and Raft.
The pattern is always the same. The map states the property; the blueprint produces the mechanism that delivers it. If you can do that on demand, in both directions, you are zooming fluidly. If a box cannot be opened, you have a map without a blueprint. If a blueprint detail serves no requirement on the map, you have a blueprint without a map. Either gap is a loss of altitude discipline.
The loop runs both ways
One misconception is worth killing directly: that you do HLD once, then descend and never climb back. The arrow does not only point down.
The feedback runs upward too. You drop into a box, start the blueprint, and discover something the map could not have known. The schema you need will not index efficiently. The concurrency model you chose cannot hit the latency target the requirements demanded. A downstream call you assumed was cheap turns out to be the bottleneck. Each of those is a legitimate reason to climb back up and redraw the map. Maybe that box needs to split. Maybe state needs to live somewhere else. Discovering at the blueprint level that an architecture cannot meet its own targets, and saying so, is a staff-grade move, not a confession of failure.
In standards language, this is just "viewpoints over one model." The map and the blueprints are views of a single design, kept consistent with each other, and a change in one view can force a change in another. The waterfall mental model, design top to bottom and never look up, is wrong about how real design works. The altitude switching is bidirectional, and the senior behavior is treating a blueprint-level discovery as permission to revisit the map rather than something to quietly work around.
What staff-level altitude control actually looks like
Pull the threads together and a specific behavior emerges, one you can watch for in yourself.
A junior gets stuck at one altitude and waits. Handed a design problem, they expect the interviewer to jump in and point out where it could be improved. A senior identifies those places themselves and leads the discussion toward them. That single difference, who initiates the descent, is the skill stated as a grading criterion. The senior volunteers: "at a high level this is three services; the interesting one is the matching engine, because that is where the hard concurrency lives, so let me zoom in there." They pick the hardest box on purpose, descend without being asked, harden it, and then climb back out to re-check the system invariant the box has to preserve.
It shows up as a refusal to decorate. Generic name first, brand on demand, always with the property attached. It shows up as deciding, not just listing: "I chose strong consistency here; if read latency became the dominant SLO, I would relax to read-your-writes." A trade-off you list but do not resolve is half an answer. The senior names the trade-off, makes the call, and states what would change the call. It even shows up as not flinching at the silence. At senior level, an awkward pause reads as an inability to pick an altitude and move. The recovery is not to say more; it is to choose a height and commit.
You can see the same discipline in production systems, not just interviews. Audex is a financial-statement engine where the high-level claim is "the output is reproducible to the byte," and the low-level mechanism that cashes it out is a golden hash that locks every run against a known-good fingerprint: a map promise made good by a blueprint primitive. IntelliFill, Aladeen, and NomadCrew each have the same structure underneath, a handful of services on a map and a few boxes where the real difficulty concentrates. The skill is the same one the interview is testing: knowing which box is hard, and being able to open it.
The one test, and the cure
There is a single question that tells you whether you are flying both altitudes well. Can every box on your map be opened into a blueprint, and does every detail in your blueprint trace back to a requirement on the map? If yes, you are zooming fluidly. If a box cannot be opened, you have made a high-level claim you cannot back. If a blueprint detail serves no requirement, you are detailing for its own sake.
People freeze in design interviews for one of two reasons, and both are altitude failures. They over-detail the map, pouring concrete on a foundation no one has agreed to, and the clock eats them alive. Or they name a box they cannot open, and the follow-up question they cannot answer exposes the gap. The first is a junior who confuses thoroughness with progress. The second is a mid-level engineer who confuses vocabulary with understanding.
The cure for both is the same, and it is the only thing in this article worth carrying into a real interview or a real design review. High-level design and low-level design are not two jobs and not two documents. They are two altitudes of the same act of designing. Fly high first to agree on the shape. Descend to build each box. Remember that the input to the blueprint is the map, which is why order matters, and remember that the loop runs both ways, which is why you climb back up when the blueprint teaches you something. And above all, make sure every high-level claim you ever state, it scales, retries are safe, reads are fast, can be cashed out, on demand, in a low-level mechanism you can name. That is altitude discipline. It is the whole game.
FAQ
What is the difference between HLD and LLD?
High-level design is the map: the services, the data flow, where state lives, and the boundaries between components, drawn to scope the system before anyone writes code. Low-level design is the blueprint for one box on that map: its classes, exact method signatures, database schema, concurrency model, and core algorithm, detailed enough that two engineers would implement it the same way. HLD answers what the system looks like; LLD answers how each component is built. They are two altitudes of one act of designing, not two separate jobs.
Why does HLD come before LLD?
Because the input to the blueprint is the map. The formal artifact (IEEE 1016, the Software Design Description standard) and every interview framework agree on the order: requirements feed the HLD, and the reviewed HLD feeds the LLD. You cannot detail the locking and schema of a box that has not been placed on the diagram yet, because you do not yet know its responsibilities or its boundaries. The order is mechanical, not stylistic.
Are HLD and LLD separate interview rounds?
Often yes, and they are graded on different rubrics. The HLD round (the system design round) tests scalability, trade-offs, and distributed-systems reasoning like sharding, caching, and load balancing, and it is deliberately code-free. The LLD round (also called the object-oriented design or OOD round) tests OOP, SOLID principles, design patterns, clean code, and concurrency-awareness, and it expects actual class code and method signatures. Bringing class diagrams to the HLD round, or distributed-systems vocabulary to the LLD round, signals you do not know which altitude you are being tested at.
What does it mean to zoom fluidly between altitudes?
It means every high-level claim can be cashed out, on request, in a low-level mechanism. "It scales horizontally" becomes a shard key chosen to avoid hot partitions. "Retries are safe" becomes an idempotency key plus a unique constraint. "Reads are fast" becomes a 100-nanosecond in-memory reference instead of a 150-microsecond SSD read. A staff engineer volunteers the descent into the hardest box, hardens it, then climbs back out to re-check the system invariant. The tell of a junior is freezing when pushed off their one comfortable altitude.
Should I name specific technologies like Kafka in a design interview?
Name the property first, the brand on demand. Say "I will use a durable, ordered queue because I need back-pressure and replay," not "I will use Kafka," unless you can immediately defend Kafka over the alternatives. The most common senior-level trap is naming a box you cannot open: the next question is always "why this and not that," and a brand name with no property behind it reads as decoration rather than a decision.