← Articles

Low-Level Design Interview Questions: A Practical Framework

Low-level design interviews ask you to turn a vague prompt like "design a parking lot" or "design a rate limiter" into a working set of classes, with clear responsibilities and room to extend later without a rewrite. The bar isn't a perfect UML diagram. It's whether you can move from requirements to code in a structured way, explain the trade-offs you made, and adapt the design when the interviewer changes a constraint halfway through. This guide covers the framework interviewers expect, the problems that come up most, a full worked example, and the mistakes that cost candidates points.

What Is a Low-Level Design Interview, and How Is It Different From System Design?

A low-level design interview, often shortened to LLD, asks you to design the internal structure of a single service: the classes, their fields and methods, how they relate to each other, and which design patterns fit. A system design interview asks the opposite question at a much bigger scale: how services talk to each other, where data lives, and which infrastructure pieces (load balancers, caches, queues, databases) fit together. If you're asked to design a parking lot's ticketing logic in code, that's LLD. If you're asked how a ride-sharing app routes a trip request across data centers, that's system design.

The two overlap more than the labels suggest. A parking lot problem framed as "design the classes" is LLD, but the same prompt framed as "design a system that handles ten thousand parking garages across a city" pulls in system design concerns like databases and caching. Interviewers usually signal which one they want early on, and the biggest early mistake is answering the wrong question: sketching microservices when the interviewer wanted `ParkingSpot`, `Vehicle`, and `Ticket` classes, or the reverse. If you're not sure which one you're in, ask directly: "should I focus on the class structure, or the system-level architecture?" That single question saves you from spending twenty minutes on the wrong layer. Our system design interview framework covers the system-scale version of this same clarify-first approach, and our OOD interview guide covers the object-modeling instincts LLD draws on directly, since LLD is really object-oriented design under a harder time limit and a more specific prompt.

What Framework Should You Use to Structure Your Answer?

The framework that works under time pressure has five stages, and skipping straight to stage three is the single most common way candidates run out of time before they reach a working design. Spend the first few minutes on requirements: what does the system need to do, what's explicitly out of scope, and what scale or concurrency assumptions matter. A parking lot problem, for instance, needs you to ask whether it should support multiple vehicle types, whether payment is in scope, and whether you need to handle multiple entry and exit points at once.

Once requirements are settled, identify the core entities and their relationships before writing a single method signature. For a parking lot, that's a `ParkingLot`, a `ParkingSpot`, a `Vehicle`, and a `Ticket`: a lot has many spots, a spot holds at most one vehicle at a time, and a ticket links a vehicle to a spot for the duration of its stay. Sketching this out, even as a short list of classes and one-line relationships, gives the interviewer a chance to correct your model before you've invested in code built on the wrong entities.

The third stage is where you actually write the class skeletons: fields, method signatures, and the interfaces or abstract classes that make the design extensible. This is the longest stage and the one interviewers weigh most heavily, since it shows whether your entities from stage two hold up once you implement real behavior. The fourth stage is picking design patterns where they solve a real problem the entities already have, never picking a pattern first and forcing the problem to fit it. The fifth and final stage, easy to skip when time runs short, is talking through trade-offs and extensions: what would change if a new vehicle type showed up, or what would break under concurrent access. A candidate who has only ever written the happy path shows a different level of design maturity than one who can see the edges of what they built.

Which LLD Problems Come Up Most Often?

Most low-level design interviews draw from a fairly small, recurring pool of problems, since the underlying skill (modeling entities, relationships, and state transitions cleanly) transfers across all of them once you've practiced a handful. Parking lot, LRU cache, and elevator system sit at the easier end, since each has a small, well-bounded set of entities and a state machine simple to reason about out loud. Rate limiter, URL shortener, and event ticket booking sit in the middle, adding concurrency, unique code generation, or multi-step booking flows with holds and cancellations. Vending machines and library systems show up at this tier too, since both hinge on getting a state machine right rather than on raw complexity.

At the harder end, interviewers look for how you handle real-world messiness on top of an already-solid base design: a multi-threaded parking lot where two cars might grab the same spot at once, a notification service that has to fan out across email, SMS, and push without a separate design per channel, or a payment processor where a failed step partway through has to leave the system consistent rather than half-charged. The jump from medium to hard isn't a longer list of classes. It's whether your design still holds up once you add concurrency, partial failure, or a channel you didn't originally plan for.

A short list worth practicing deliberately, since they show up across most interview loops in some form:

  • Parking lot (single-threaded, then multi-threaded as a follow-up)
  • LRU cache with get and put in constant time
  • Rate limiter supporting at least one throttling algorithm
  • Elevator system with multiple cars and a dispatch strategy
  • URL shortener with collision handling for generated codes
  • A simple in-memory logging framework with multiple output destinations

Every one of these is in our curated question bank, including the parking lot problem, rate limiter, and LRU cache, pulled from real onsite loops rather than a static public list, so what you practice reflects what's actually being asked right now.

How Do You Design a Parking Lot System, Step by Step?

Walking through one problem in full shows how the five-stage framework actually plays out, rather than staying abstract. Start with requirements: the lot has multiple floors, each floor has spots sized for motorcycles, cars, and buses, a vehicle can only park in a spot sized for it or larger, and the system needs to track availability in real time and calculate a fee when a vehicle exits.

From there, the entities fall out fairly directly. A `ParkingLot` owns a collection of `Floor` objects, each of which owns a collection of `ParkingSpot` objects with a size and an occupied flag. A `Vehicle` has a type and a license plate. A `Ticket` gets created when a vehicle enters, holding a reference to the vehicle and the spot it's assigned, and it gets closed out with an exit timestamp and a calculated fee when the vehicle leaves.

class ParkingSpot:
    def __init__(self, spot_id, size):
        self.spot_id = spot_id
        self.size = size
        self.vehicle = None

    def is_available(self):
        return self.vehicle is None

    def assign(self, vehicle):
        self.vehicle = vehicle

    def free(self):
        self.vehicle = None


class Ticket:
    def __init__(self, vehicle, spot, entry_time):
        self.vehicle = vehicle
        self.spot = spot
        self.entry_time = entry_time
        self.exit_time = None
        self.fee = None


class ParkingLot:
    def __init__(self, floors):
        self.floors = floors
        self.active_tickets = {}

    def find_spot(self, vehicle):
        for floor in self.floors:
            for spot in floor.spots:
                if spot.is_available() and spot.size >= vehicle.size:
                    return spot
        return None

    def park(self, vehicle, entry_time):
        spot = self.find_spot(vehicle)
        if spot is None:
            raise Exception("Lot is full for this vehicle size")
        spot.assign(vehicle)
        ticket = Ticket(vehicle, spot, entry_time)
        self.active_tickets[vehicle.license_plate] = ticket
        return ticket

Notice what this skeleton leaves out on purpose: pricing and fee calculation live outside `ParkingLot`, in a separate `PricingStrategy` interface with different implementations for hourly versus flat-rate lots. That separation is the extensibility payoff of stage four. If the interviewer asks "now support a lot that charges differently on weekends," you swap in a new `PricingStrategy` implementation instead of touching `ParkingLot` at all, and saying that before you're asked is exactly the kind of forward-looking signal that separates a strong answer from a merely correct one.

The natural follow-up is concurrency: what happens when two vehicles try to claim the same spot at once. The honest answer is that `find_spot` and `assign` need to happen atomically, behind a lock scoped to the spot, since checking availability and claiming it as two separate steps is a race condition waiting to happen under real traffic. Naming that risk before the interviewer points it out is worth more than getting there only after a hint.

How Do You Ask Clarifying Questions Without Stalling the Interview?

Clarifying questions in an LLD interview aren't a formality before the "real" work starts. They shape the scope of the problem to something you can finish in the time you have, and a design built on the wrong assumptions rarely recovers even if the code itself is clean. The trap is asking too many questions with no direction, which reads as stalling rather than scoping.

A tighter approach is to ask three or four questions that each rule out a real design fork, not questions with an obvious answer. For the parking lot problem, "does the lot need to support multiple vehicle types with different spot sizes?" changes whether `ParkingSpot` needs a size field at all. "Should the system handle concurrent access from multiple entry points, or can I assume single-threaded access for the first pass?" changes whether locking belongs in the first design or a follow-up. "Is payment part of this problem, or just tracking who's parked where?" changes whether you need a `PricingStrategy` at all. Each of these, once answered, removes a branch from the design space, and asking them one at a time, rather than as a checklist read off a memorized script, is what makes them land as genuine scoping rather than a rehearsed opener.

If the interviewer says "use your judgment," that's a signal to state the assumption you're making and move on. Saying "I'll assume single-threaded for now and note where locking would go if we extend it" keeps the interview moving while still showing you saw the concern.

Which Design Patterns Actually Show Up in LLD Interviews?

A handful of patterns solve most of the problems in this style of interview, and picking the right one for the entity that actually needs it matters more than knowing a long list of pattern names. Strategy fits any problem where one piece of behavior needs to swap out cleanly, like the parking lot's pricing logic or a payment processor's choice between credit card, wallet, and bank transfer. State fits problems built around a small number of well-defined states with clear transitions, like a vending machine's idle-to-dispensing-to-out-of-stock cycle or an elevator's idle-to-moving-to-doors-open cycle. Observer fits anything with a publish-and-subscribe shape, like a notification service alerting multiple channels without the event source knowing which channels exist. Factory fits problems where object creation itself has logic worth isolating, like a vehicle factory that returns the right subclass based on a type string instead of scattering `if` statements everywhere.

The mistake interviewers actually flag isn't using too few patterns. It's forcing one in where the problem doesn't need it, wrapping a single, never-changing piece of logic in a Strategy interface because Strategy is the pattern you practiced most recently. A clean design with zero named patterns beats one where every class implements an interface for a variation that will never happen. If a pattern doesn't map onto a real "this behavior needs to vary independently" need, leave it out and say why, since naming the trade-off is more convincing than reaching for complexity that isn't earned.

What Mistakes Cost Candidates Points in LLD Interviews?

Jumping straight to code before settling on entities is the most common one, and it's usually invisible to the candidate making it, since the code that comes out often still runs. The cost shows up later, when the interviewer asks for an extension and the class boundaries drawn in the first five minutes have nowhere clean to put the new behavior, forcing an awkward bolt-on instead of a natural extension.

Overloading a single class with responsibilities that belong to separate objects is the second. A `ParkingLot` class that also handles pricing, payment, and confirmation emails is doing the job of four classes, and an interviewer watching for single-responsibility violations will notice immediately. The fix isn't complicated: if you can't describe a class's job in one sentence without using "and," split it.

Ignoring concurrency entirely, even when the interviewer never explicitly asks about it, is the third. Most classic LLD problems involve some resource that multiple actors might contend for at once, and at least naming where a race condition could occur, even without fully solving it, shows an awareness that a design working for only one caller doesn't reflect how these systems run in production.

The fourth is treating the interview as a solo exercise instead of a conversation. Interviewers give hints and sometimes change a requirement on purpose to see how you adapt an existing design rather than start over. A candidate who narrates their reasoning and updates the design cleanly when a constraint changes reads as someone who has actually worked on a real codebase with other people, which is exactly what the interview measures.

How Should You Practice for a Low-Level Design Interview?

Practicing LLD well means building full designs end to end rather than reading someone else's finished class diagram and nodding along, since the skill being tested is getting from a vague prompt to a working structure. Pick one problem, set a forty-five minute timer to match real interview conditions, and force yourself through all five stages without skipping to code early. Try the same problem again a week later. If the two attempts land on similar structures, the pattern has stuck; if not, that tells you which stage needs more repetition.

Rotate through problems at different tiers rather than grinding the same one repeatedly. A parking lot, an LRU cache, and a rate limiter each stress a different skill (spatial modeling, cache eviction, and time-window logic), so working across all three teaches you to recognize which tools a new prompt needs rather than pattern-matching one memorized solution onto everything. Our OOD question bank groups problems this way, so you can move deliberately from the easier state-machine problems to the concurrency-heavy ones instead of practicing at random.

Once you can complete a design cleanly under time pressure, add the follow-ups interviewers actually ask after the base design: "now support multiple parking lots across a city," or "now two users might book the same seat at once." These follow-ups are where interviews are actually won or lost, since most candidates produce a correct first pass but far fewer extend it cleanly on the spot, and practicing the extension step closes that gap faster than doing ten more first-pass designs from scratch.

Where Does LLD Fit Into Your Broader Interview Prep?

Low-level design sits between coding interviews and system design on most companies' interview loops, close enough to object-oriented design that the two get taught together, and close enough to system design that some companies blur the line between them. If your loop includes a dedicated LLD round, treating it as "OOD with a stricter time budget and a heavier expectation of working code" is a more accurate mental model than treating it as a smaller version of system design.

Our guide to approaching OOD interviews covers the requirements-to-classes instinct this guide builds on, and our system design interview framework picks up exactly where LLD problems stop being about a single service and start being about how multiple services and data stores work together at scale. Practicing all three in sequence, coding patterns, then LLD, then system design, matches how most onsite loops are structured.

Frequently Asked Questions

What is the difference between LLD and OOD interview questions?

They test the same underlying skill: modeling a problem with classes, relationships, and clean responsibilities. LLD is typically the more code-heavy, time-boxed version, often expecting working class skeletons or even runnable code, while OOD questions sometimes stop at a class diagram and a verbal discussion of the relationships.

How long does a typical low-level design interview last?

Most run forty-five minutes to an hour, with the first five to ten spent on requirements and entity identification, twenty to thirty on class design and implementation, and the remainder on design pattern choices, trade-offs, and follow-up extensions.

Do I need to write fully working code in an LLD interview?

Most interviewers expect class skeletons with correct method signatures and the core logic filled in for the main operations, rather than a complete, compiling program. What matters more is that the structure is sound and extensible, since an interviewer can usually tell within minutes whether the entities will hold up under a follow-up question.

Which programming language should I use for low-level design interviews?

Whichever language you're fastest and most comfortable in, since the interview evaluates your design decisions, not your fluency in a specific syntax. Python and Java are the most common choices because their class syntax is compact and their standard libraries express interfaces and abstract classes quickly under time pressure.

What are the most common low-level design interview questions?

Parking lot, LRU cache, rate limiter, elevator system, URL shortener, and vending machine cover the bulk of what shows up across most interview loops, since each teaches a transferable skill (state machines, concurrency, or clean separation of responsibilities) rather than being a one-off puzzle.

How is a low-level design interview scored?

Interviewers typically weigh problem analysis and requirement clarification, the quality of the class design and relationships, code quality once you start implementing, how well the design extends to follow-up changes, and how clearly you communicate your reasoning throughout, rather than scoring on whether you reached one single "correct" answer.