How to approach an LLD interview
The shape of an LLD interview
LLD (Low Level Design) interviews focus on object-oriented design: classes, interfaces, design patterns, concurrency primitives, and code-level structure. The output is typically a class diagram + key method signatures, sometimes with brief code snippets. Sessions run 45-75 minutes.
The contrast with HLD (High Level Design): HLD asks "what services and data stores make up this system?" — LLD asks "what classes and interfaces implement this component?" An HLD interview for Twitter might focus on push-vs-pull fanout; an LLD interview for the same product might focus on the class hierarchy of a Tweet, the strategy pattern for ranking, and the observer pattern for notification delivery.
Most companies do both interviews. For senior+ roles, candidates need to be fluent in both. The skills overlap (clarifying scope, naming abstractions, articulating tradeoffs) but the artifacts are different.
The 5-stage approach
A reliable structure for any LLD problem:
- Clarify requirements (5-10 min): what features, what scope, what user types, what edge cases matter. Do this before drawing a single class. Same discipline as HLD.
- Identify core entities (5-10 min): the "nouns" from the problem statement. Parking Lot, Vehicle, ParkingSpot, Ticket, etc. List them. These become your classes.
- Define relationships (5-10 min): how do entities relate? Is-a (inheritance), has-a (composition/aggregation), depends-on (association). Sketch a class diagram.
- Design behavior (15-20 min): for each class, what does it do? What methods does it expose? Where does state live? When you encounter a complex behavior (varying payment methods, multiple vehicle types, etc.), reach for a design pattern.
- Stress test & extend (10-15 min): walk through scenarios — happy path, edge cases, concurrent access, future extensions. Identify weaknesses; refine.
What interviewers look for
| Skill | What it looks like |
|---|---|
| Clarifying scope | Asking "do we support X" before drawing — same as HLD. Junior candidates jump straight to coding. |
| Naming abstractions well | Class names reflect the domain (Vehicle, ParkingSpot) not implementation (VehicleManager, SpotHelper). Methods named for what they do (park(), exit()), not how they do it. |
| Right level of abstraction | An interface where it matters (PaymentMethod), a concrete class where over-abstraction would add complexity. |
| Recognising design patterns | Saying "this is a state machine; let me use the State pattern" — and then implementing it correctly. Not name-dropping patterns where they don't fit. |
| Articulating tradeoffs | "I could use inheritance here, but composition lets me change behavior at runtime — picking composition because..." |
| Handling concurrency | For multi-user systems: thinking about locks, atomicity, deadlock. Not assuming single-threaded. |
| Anticipating extension | Designing so a new payment method or vehicle type doesn't require modifying existing code (Open-Closed Principle). |
Common failure modes
- Diving into code immediately — skipping requirements and entity identification. Results in a confused design that can't be defended.
- Over-engineering — using 8 design patterns where 2 would suffice. Patterns serve the design, not the other way around.
- Under-engineering — one massive class doing everything. No separation of concerns.
- Ignoring concurrency — assuming the system has one user. Real LLD problems almost always involve multiple actors.
- God objects — a ParkingLot class with 30 methods that does everything. Refactor into focused classes (TicketIssuer, SpotAllocator, PaymentProcessor).
- Anemic domain — classes with only getters/setters, no behavior. Behavior should live with the data that informs it.