What is Low-Level Design?
Low-level design (LLD) is the process of turning a set of requirements into a concrete,laskdfjasldfkjalskdfjalskdfjaslkd;fjasldk;fjaslkdfjasdlk;jf
object-oriented structure — the actual classes, interfaces, methods and relationships that a
developer could sit down and implement. If high-level design answers "what services do we need
and how do they talk to each other over a network," low-level design answers "inside one of those
services, what objects exist, what does each one know, and what does each one do."
A useful way to think about it: high-level design draws the boxes and arrows between systems.
Low-level design draws the boxes and arrows between classes, inside one of those systems.
This course uses the term "low-level design" the way it's used in software engineering
interviews — a class-design exercise, usually solved on a whiteboard or in a shared document,
where you're given a real-world scenario (a parking lot, a vending machine, a ride-sharing
dispatch system) and asked to design the object model that would back it.
Why LLD matters
Three practical reasons this shows up as its own interview round, separate from algorithms and
separate from high-level system design:
- It tests judgement, not memorisation. There's rarely one "correct" class diagram. What's
being evaluated is whether your design choices are defensible — whether you can explain the
trade-off you made and what would change if a requirement changed. - It's close to the actual job. Most engineers spend more time deciding how to structure a
module, a service, or a set of classes than they spend on classic algorithm puzzles. LLD
interviews are one of the few formats that directly rehearses that daily work. - It reveals how you handle ambiguity. LLD prompts are deliberately under-specified. How you
ask clarifying questions and scope the problem is itself part of what's being assessed —
covered in detail in the next lesson on requirement analysis.
Where LLD fits in the development lifecycle
A rough map of where low-level design sits, without pretending every team follows it the same way:
- Requirements gathering — product or business requirements are collected, often incomplete.
- High-level design — the system is broken into services/components and their interactions
are sketched (this is the subject of high-level/system design, covered separately). - Low-level design — inside a component, the classes, interfaces and their responsibilities
are worked out. This is where OOP principles and design patterns get applied. - Implementation — the design is written as actual code.
- Testing and iteration — the design is refined based on what breaks or what changes.
In practice these steps overlap constantly — a good low-level design changes as implementation
reveals problems, and that's normal, not a failure of the process.
What interviewers are actually evaluating
When someone reviews an LLD interview, they are typically not grading against one "ideal" class
diagram. They're looking for:
- Whether you clarified scope before designing (see the next lesson).
- Whether your classes have clear, single responsibilities.
- Whether you used interfaces/abstraction where it genuinely helps flexibility — not everywhere,
which is its own mistake. - Whether you can walk through how a new requirement would change your design.
- Whether the code you'd write from this design would actually compile and behave sensibly.
Interview tip
If you only remember one thing from this lesson: an interviewer would much rather see a simple,
slightly imperfect design that you can clearly justify than a "clever" one full of patterns you
can't explain the reasoning for.
From requirements to classes and interfaces
Here's the general path a requirement takes on its way to becoming code. Suppose a requirement
reads: "Users can pay for their order using different payment methods."
- Identify the nouns — candidates for classes:
Order,User,Payment. - Identify the verbs tied to each noun — candidates for methods: an
Ordercan bepaid; a
payment method canprocessan amount. - Identify what varies — "different payment methods" is a signal that payment processing
should be abstracted behind an interface, so new methods can be added without changing theOrderclass. - Draft the interface — a
PaymentStrategyinterface with a singlepay(amount)method,
implemented by concrete classes likeUpiPaymentorCardPayment.
This is the essence of low-level design: reading requirements carefully enough to notice which
parts are fixed and which parts are expected to change, then modelling the "expected to change"
parts behind an abstraction.
Responsibilities and object collaboration
Every class in a good design should be able to answer two questions clearly: what do I know?
(its state) and what do I do? (its behaviour). A class that can't answer both in a sentence is
usually a sign the responsibility is either too vague or split across too many places.
Objects rarely work alone. An Order collaborates with a PaymentStrategy to get paid, and with
an Inventory to check stock — but the Order shouldn't need to know how a card payment is
processed, only that its collaborator can pay(amount). This separation — knowing who to ask
without knowing how they'll do it — is what makes a design extensible.
A small Java example
public interface PaymentStrategy {
void pay(double amount);
}public class UpiPayment implements PaymentStrategy {
private final String upiId;
public UpiPayment(String upiId) {
this.upiId = upiId;
}
@Override
public void pay(double amount) {
System.out.printf("Paid %.2f via UPI (%s)%n", amount, upiId);
}
}public class Order {
private final double amount;
private final PaymentStrategy paymentStrategy;
public Order(double amount, PaymentStrategy paymentStrategy) {
this.amount = amount;
this.paymentStrategy = paymentStrategy;
}
public void checkout() {
paymentStrategy.pay(amount);
}
}Notice what Order does not contain: no if (paymentMethod.equals("upi")) branching, no
knowledge of UPI IDs or card numbers. Adding a new payment method later means writing one new
class — Order never changes. That's the payoff of the abstraction introduced above, and it's
the same idea behind the Strategy pattern covered later in this course.
Extensibility and maintainability
Two qualities most LLD interviews are implicitly testing for:
- Extensibility — can a new requirement be added by adding code, rather than editing
existing, already-tested code? The payment example above is extensible: a new payment method is
a new class. - Maintainability — can someone unfamiliar with the code understand what a class is
responsible for without reading every method? Clear naming and focused responsibilities do more
for this than any pattern.
Neither quality is free — abstracting too early, for requirements that may never change, adds
complexity without benefit. Part of the skill this course builds is judging when an abstraction
earns its cost this is how we we learningdsfaskdlfjasdlfj.
Common mistakes
Common mistakes
- Designing before scoping. Jumping straight to classes before clarifying what the system actually needs to do — covered in depth in the next lesson.
- One giant class. Putting order validation, payment processing and notification logic all inside Order because it's convenient, rather than splitting responsibilities.
- Abstracting everything. Adding an interface for something that will realistically only ever have one implementation, out of habit rather than need.
- Ignoring relationships. Presenting a list of classes without explaining how they collaborate — interviewers usually care more about the relationships than the class list itself.
Interview questions
Interview questions
- In your own words, how would you explain the difference between high-level and low-level design to someone new to interviews?
- Why might an interviewer prefer a simple design you can justify over a more "impressive" one you can't?
- Take the requirement "users can rate a product from 1 to 5 stars." What classes and methods would you sketch from that single sentence?
Practice assignment
Practice assignment
Take the requirement: "A library should let members borrow and return books, and each book has a maximum number of copies." Without writing full code, list the classes you'd start with, one responsibility for each, and one place you'd consider using an interface. Keep it to five classes or fewer — the goal is practicing scoping, not completeness.
Key takeaways
Key takeaways
- Low-level design turns requirements into the classes, interfaces and relationships that back an implementation — it's the "inside one service" counterpart to high-level system design.
- Interviewers evaluate judgement and justification, not a single "correct" diagram.
- Reading a requirement for what varies versus what's fixed is the core skill — abstract the parts expected to change, keep the rest simple.
- Extensibility and maintainability are the two qualities most LLD feedback ultimately traces back to.
- The most common mistakes are designing before scoping, and abstracting either too little or too much.
Further reading
Further reading
- LLD vs High-Level Design — Continue with to see the two disciplines contrasted directly.
- Requirement Analysis for LLD Interviews — Then for a repeatable scoping process before you design a single class.