Facebook Pixel

What Is Low-Level Design

Low-level design (LLD) is the work of turning a one-sentence prompt — "design a parking lot," "design a food-delivery order" — into concrete classes, the responsibilities each one owns, and the way they talk to each other. The interview that tests this skill is sometimes called object-oriented design (OOD); the two names describe the same thing.

The focus is code organization, not algorithms and not architecture. An interviewer wants to see which objects you create, what state each one holds, what methods it exposes, and whether your design can absorb a new requirement without a rewrite. You are judged on the shape of the code a real team would have to live with.

The pipeline below shows how an LLD interview moves from a one-line prompt to working code.

How LLD differs from algorithms

A data-structures-and-algorithms (DSA) question has a single correct answer hiding behind a clever insight. "Find the longest substring without repeating characters" wants one function, the right data structure, and the optimal time complexity. Once you find the trick, the code is short and there is little left to discuss.

LLD has no trick and no single right answer. "Design a food-delivery order" wants a handful of classes that cooperate, and two strong candidates will produce different designs that are both acceptable. The difficulty is in assigning responsibilities so the system stays easy to change. You are optimizing for clarity and maintainability, not for a Big-O bound.

How LLD differs from system design

System design (often called high-level design, or HLD) operates one level up. It is about architecture at scale: services, data stores, queues, caching, sharding, and the trade-offs between them. You sketch boxes and arrows on a whiteboard and talk through how the system handles millions of users. There is no code, and almost no discussion of individual classes or methods.

Low-level design is the blueprint for a single building on that map. Instead of services and arrows, you work with classes, methods, fields, and state transitions for one self-contained feature. The same prompt pulls in opposite directions depending on which interview you are in. Asked to "design ride-sharing," a system-design interview has you draw the services and the data flow between them:


A low-level design interview throws all of that away and asks for the code structure of one piece — say, the Trip itself: what it stores, the states it moves through, and the objects it collaborates with.


System design is the map. Low-level design is the blueprint for one building on it.

What a good design actually looks like

The clearest way to see the difference between a weak and a strong LLD answer is to look at the same feature built two ways. Consider a food-delivery Order that moves through a fixed lifecycle: placed, preparing, en route, delivered.

A common weak answer crams everything into one class and exposes its state as a plain field. Any code anywhere can reach in and change it, so nothing guarantees the order moves through its lifecycle correctly.

1# Bad: one class owns everything and status is a public string.
2# Any caller can jump the order straight to "DELIVERED".
3class DeliveryOrder:
4    def __init__(self, items):
5        self.status = "PLACED"
6        self.items = items
7        self.driver = None
8
9# scattered across the codebase, with nothing to stop it:
10order.status = "DELIVERED"   # skipped PREPARING and EN_ROUTE

A strong answer keeps the state private and routes every change through a method that enforces the rules. The order can only move to the next valid stage, and the class itself is the single place that decides what "valid" means.

1from enum import Enum, auto
2
3class OrderStatus(Enum):
4    PLACED = auto()
5    PREPARING = auto()
6    EN_ROUTE = auto()
7    DELIVERED = auto()
8
9# Good: state is private; the only way to advance is a guarded method.
10class DeliveryOrder:
11    def __init__(self, items: list["Item"]):
12        self._items = items
13        self._status = OrderStatus.PLACED
14        self._driver: "Driver | None" = None
15
16    def dispatch(self, driver: "Driver") -> None:
17        if self._status is not OrderStatus.PREPARING:
18            raise ValueError(f"cannot dispatch from {self._status}")
19        self._driver = driver
20        self._status = OrderStatus.EN_ROUTE

Neither version uses a clever algorithm. The second is better because of where the rules live and what the class refuses to let callers do. That distinction — state hidden behind behavior, with rules living next to the data they govern — is what LLD evaluates.

How LLD interviews are graded

Companies use their own rubrics, but the dimensions are remarkably consistent. Knowing them tells you where to spend your forty-odd minutes.

DimensionWhat the interviewer is checking
Problem analysisDid you pull out the core entities and clarify scope before writing code?
Class designAre responsibilities split cleanly, with sensible state and method signatures?
Code qualityEncapsulation, clear naming, composition over inheritance, separation of concerns
ExtensibilityCan the design absorb a follow-up requirement without being rewritten?
CommunicationDid you talk through your reasoning and adjust when probed?

The pattern across all five is the same: structure and judgment matter more than raw output. A candidate who writes modest code but reasons clearly about responsibilities and trade-offs scores higher than one who fills the screen with a tangled god class. The next lesson introduces the six-step delivery framework that the rest of this course applies to each case study.

Invest in Yourself
Your new job is waiting. 83% of people that complete the program get a job offer. Unlock unlimited access to all content and features.
Go Pro