HLD vs LLD: High-Level vs Low-Level Design
The difference between high-level design (HLD) and low-level design (LLD): a side-by-side table, one system designed at both levels, and interview tips.

HLD (high-level design) is the architecture of a whole system: the major components, how they communicate, where data lives, and how the system scales and survives failure.
LLD (low-level design) is the detailed design of one component: its classes, interfaces, methods, data structures and algorithms.
They are two zoom levels of the same system. HLD is the map of a city; LLD is the blueprint of one building on it. You move from HLD to LLD as you zoom in from "what are the boxes and arrows" to "what's inside this one box." Confusing them — answering an HLD question with class diagrams, or an LLD question with hand-waving — is one of the most common ways to lose a system design interview.
What High-Level Design covers
- Major services/components and their responsibilities
- Communication between them (request/response, events, async)
- Data stores and the high-level data model
- Cross-cutting infrastructure: load balancers, caches, queues, CDN
- Scaling strategy and failure/redundancy at the system level
An HLD answer to "design a chat app" names clients, a gateway, a messaging service, a presence service, a database and a push pipeline — and explains how a message flows through them.
What Low-Level Design covers
- Classes and interfaces, and how they collaborate
- Method signatures and responsibilities
- The concrete data structures chosen and why
- Algorithms, edge cases and concurrency concerns
- Applicable design patterns (factory, observer, strategy…)
An LLD answer to "design the rate limiter inside that gateway" defines the RateLimiter interface, a token-bucket implementation, the data structure holding buckets, and how it behaves under concurrent requests.
HLD vs LLD at a glance
| HLD | LLD | |
|---|---|---|
| Zoom level | Whole system | One component |
| Written by | Architects and senior engineers | The engineers who will build the component |
| Read by | Engineering leads, other teams, stakeholders | Implementers and code reviewers |
| When it's produced | First, before the work is split into components | After the HLD, before or while the component is built |
| Level of detail | Boxes and arrows — no code | Down to method signatures, data structures and table schemas |
| Deliverables | Architecture and data-flow diagrams, component responsibilities, technology choices, scaling plan | Class and sequence diagrams, interfaces and method signatures, database schema, edge-case handling |
| Concerns | Scale, availability, communication | Correctness, structure, algorithms |
| Tools | Whiteboard or architecture diagrams (boxes, arrows, data stores) | UML class and sequence diagrams, schema definitions, code |
| Typical question | "Design a news feed" | "Design the feed-ranking module" |
| How interviews test it | System design round: requirements, estimates, components, trade-offs | LLD or machine-coding round: classes, interfaces, clean structure, often working code |
One system at both levels: a URL shortener
The clearest way to see the difference is to design the same thing twice.
The HLD
Requirements: turn a long URL into a short code, and redirect anyone who opens the code to the original URL. Redirects vastly outnumber new links, so the design is read-heavy.
POST /shorten → Load balancer → App server → ID generator (next ID → base62 code)
└─────→ Database (save code → long URL)
GET /{code} → Load balancer → App server → Cache ──miss──→ Database
└─────→ 302 redirect to the long URL
- Load balancer in front of stateless app servers, so capacity grows by adding servers.
- ID generator hands out unique numbers, encoded in base62 (0–9, a–z, A–Z). Seven characters cover about 3.5 trillion codes. Each app server takes a block of IDs at a time, so no two servers ever issue the same code.
- Database stores code → long URL. The access pattern is a lookup by key, so a key–value store or a single indexed table both work.
- Cache in front of the database for popular codes, because most traffic is redirects.
- Trade-off to state out loud: a 301 (permanent) redirect lets browsers cache it and cuts load; a 302 (temporary) sends every click through you, which you need if you count clicks.
No classes, no method names — that's the point.
The LLD
Now zoom into the shortening service on the app server and design its internals:
interface IdGenerator {
nextId(): Promise<bigint>;
}
interface UrlRepository {
save(code: string, longUrl: string, expiresAt?: Date): Promise<void>;
findByCode(code: string): Promise<string | null>;
}
class ShortenerService {
constructor(
private readonly ids: IdGenerator,
private readonly repo: UrlRepository,
) {}
async shorten(longUrl: string): Promise<string> {
const url = new URL(longUrl); // throws on anything that isn't a URL
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error('Only http and https links can be shortened');
}
const code = toBase62(await this.ids.nextId());
await this.repo.save(code, url.toString());
return code;
}
resolve(code: string): Promise<string | null> {
return this.repo.findByCode(code);
}
}
const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
function toBase62(n: bigint): string {
let out = '';
do {
out = ALPHABET[Number(n % 62n)] + out;
n /= 62n;
} while (n > 0n);
return out;
}
CREATE TABLE short_urls (
code VARCHAR(10) PRIMARY KEY,
long_url TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NULL
);
The LLD also has to answer the questions the HLD skipped:
- Invalid input: reject anything that isn't an http(s) URL before spending an ID on it.
- Duplicates: if the same long URL is shortened twice, return the existing code or issue a new one? Reusing needs an index on
long_url. - Expiry: an expired code should return "not found", not a stale redirect.
- Guessable codes: sequential IDs make codes predictable, so anyone can step through them and find other people's links. If that matters, shuffle or encode the ID before converting it to base62.
- Testability:
IdGeneratorandUrlRepositoryare interfaces, so the service can be tested with in-memory fakes.
Notice what changed: the HLD never mentions a class, and the LLD never mentions a load balancer.
Where frontend fits
Frontend system design has its own HLD/LLD split. HLD: how the app is structured — rendering strategy (SSR/CSR/SSG), data fetching and caching, state management, the module boundaries, and how it talks to the backend. LLD: the design of a specific widget — say an accessible, virtualised, debounced autocomplete, with its component API, internal state machine and edge cases.
How they show up in interviews
Most "system design" rounds are HLD-first: scope the problem, estimate load, draw the components, discuss trade-offs. Some companies add a dedicated LLD/"machine coding" round that is pure LLD — build a working component with clean structure. Read the room: if they ask you to code it, they want LLD; if they ask you to design it at scale, they want HLD.
A strong candidate states which level they're operating at and moves between them deliberately: "At the high level, these are the services; let me zoom into the ranking service and design its internals."
Common mistakes
- Jumping straight to classes in an HLD question (or staying vague in an LLD one).
- Never naming the level you're working at, so the interviewer can't follow your zoom.
- Treating them as separate skills — they're one continuous design conversation.
Practice both levels
You can explore the HLD, service and LLD views of the same architecture interactively in Generate System Design — start from a prompt, then drill from the whole system into a single subsystem. For interview drilling across concepts, coding and system design together, use Frontend Interview Prep.
Frequently asked questions
What is HLD and LLD?
HLD (high-level design) is the architecture of a whole system — its major components, how they communicate, where data lives and how it scales. LLD (low-level design) is the detailed design of one component — its classes, interfaces, methods, data structures and algorithms. HLD decides what the boxes are; LLD decides what goes inside one box.
What do HLD and LLD stand for?
HLD stands for high-level design and LLD for low-level design. Both describe the same system, at different levels of detail: HLD the whole architecture, LLD the internals of one part of it.
Which comes first, HLD or LLD?
HLD. You settle the components and how they interact before designing any one of them in detail, because a component's LLD depends on the responsibilities the HLD gave it. In practice it is iterative: a problem found during LLD can send you back to adjust the HLD.
Is LLD asked in system design interviews?
Often, as its own round. The "system design" round is usually HLD, and many companies add a low-level design or machine-coding round where you design the classes and interfaces for something like a parking lot, a rate limiter or an LRU cache — sometimes with working code.
Is HLD or LLD more important?
Neither — they answer different questions. Interviews usually start with HLD (shape and scale) and some add an LLD/machine-coding round (component internals). Strong engineers move fluidly between them.
Does frontend have HLD and LLD?
Yes. Frontend HLD covers rendering strategy, data fetching/caching, state management and module boundaries; frontend LLD covers the design of a specific component — its API, internal state and edge cases. See our frontend system design interview guide.
What tools help me practise HLD and LLD?
Drawing beats reading. Generate System Design lets you produce and drill into HLD, service and LLD views of an architecture from a single prompt, then edit and export it. For the interview framing, see the frontend architecture questions.
Explore HLD, service and LLD views of any architecture, free.
Free to start. AI features send only what they need to an AI provider, and the tool says when.
See how it plays out in interviews — read the guide.