LLD vs HLD
High-level design (HLD) and low-level design are two altitudes of the same job: building a system that works. HLD decides the shape of the system as a whole. LLD decides the shape of one piece of it. Neither one is optional - a beautifully decomposed set of services with badly designed internals is just as broken as one well-designed service that talks to nothing.
Where each one lives
| High-level design | Low-level design | |
|---|---|---|
| Unit of thought | Services, databases, queues | Classes, interfaces, methods |
| Typical question | "How do we shard this database?" | "Does Order own its TaxCalculator, or does it borrow one?" |
| Output | An architecture diagram: boxes, arrows, data stores | A class diagram: fields, methods, relationships |
| Concerns | Scalability, availability, load balancing, API contracts between services | Cohesion, coupling, SOLID, design patterns, concurrency within one service |
| Interview name | System design | OOD / machine coding |
HLD asks how many machines you need and what happens when one of them dies. LLD asks what a single request does once it lands inside one of those machines - which objects get created, which methods get called, in what order.
Try it yourself: for a food-delivery app, sort these into HLD or LLD - (1) whether
order data lives in one database or is sharded by region, (2) whether Order owns its
own DeliveryFee calculation or delegates to a separate class, (3) how many
replicas of the notification service to run, (4) whether a Courier and an Order
are linked by composition or by a looser aggregation.
Sort those same four decisions here, one at a time:
Whether order data lives in one database or is sharded by region.
They are not independent
A service boundary drawn at the HLD level becomes a set of classes at the LLD level,
and a bad class design can force a service to be split or merged later - the two
levels leak into each other constantly. Deciding that "rate limiting" is a separate
service (HLD) still leaves you needing to design the RateLimiter class that
implements it (LLD). This site treats system design itself as a companion topic rather
than folding it in here; the two are meant to be read together, not confused for one
another.
The line is fuzzy in practice
Don't expect a clean cutoff. A "design a URL shortener" prompt routinely mixes both in
the same forty-five minutes: how hashing distributes across servers is an HLD
question, and whether the UrlShortener class hides its hashing algorithm behind an
interface is an LLD question, and a good candidate moves between the two without
announcing which hat they are wearing. Interviewers who label a round "LLD" are mostly
signaling where they want the bulk of the depth - actual class design, not just
service boxes - not promising that HLD questions never come up.