A low level design interview asks you to turn a vague problem like "design a parking lot" into classes, relationships, and working code within about an hour. The winning approach is to clarify requirements first, model the core entities, isolate the parts that change behind interfaces, and then write a small, runnable skeleton you can extend when the interviewer adds a twist.
This guide walks through a complete parking lot answer and a 5-step framework you can reuse in any machine coding round.
Key Takeaways
- LLD rounds grade modeling and extensibility, not algorithms. A clean class design with one working flow beats a sprawling design that does not run.
- Use a fixed 5-step framework: clarify, identify entities, define relationships, isolate change points, then code and extend.
- For the parking lot, the core entities are ParkingLot, Floor, Spot, Vehicle, Ticket, and Gate, with pricing and spot allocation pulled out as strategies.
- Strategy and Factory patterns handle most parking lot extension questions, as long as you add them for a reason you can state.
- Expect at least one live follow-up: EV charging, dynamic pricing, multiple gates, or concurrency. Plan your interfaces so each one is a new class, not an edit to old ones.
What Do Low-Level Design Rounds Actually Evaluate?
An LLD round evaluates how you structure code, not how fast you find an optimal algorithm. The interviewer wants to see whether a teammate could read, test, and extend what you write.
Low-level design (also called object-oriented design or OOD) is the step between a system design diagram and actual code. A machine coding round is the hands-on version: you get a problem statement and 60 to 120 minutes to produce working, demo-able code. Machine coding rounds are especially common at product companies in India, while US companies more often run LLD as a whiteboard or shared-editor conversation. Our product-based company interview preparation guide for India covers where these rounds show up in the loop.
Here is what interviewers typically score, and what each signal looks like in practice:
| Signal | What strong looks like | Common red flag |
|---|---|---|
| Requirements | Asks 4-6 sharp questions, writes scope down | Starts coding in minute one |
| Modeling | Nouns become classes with clear ownership | One god class with 20 methods |
| Responsibilities | Each class has one reason to change | Pricing logic inside the Spot class |
| Extensibility | New vehicle or price rule = new class | Long if/else chains on type strings |
| Patterns | Used where they remove a real pain | Patterns added to look clever |
| Working code | Core flow runs end to end with a demo | Only interfaces, nothing executes |
| Communication | Explains trade-offs while coding | Silent for 20 minutes |
The last row matters more than most candidates expect. If you tend to go quiet when you code, practice the habits in our guide on how to think out loud in a coding interview.
The 5-Step LLD Framework for Any Machine Coding Round
The 5-step LLD framework is a repeatable order of work that keeps you from over-designing early or under-designing late. Use it for parking lots, elevators, vending machines, splitwise clones, or library systems.
- Clarify and scope (5-8 minutes). List functional requirements, explicitly mark what is out of scope, and confirm the interface: CLI commands, method calls, or a REST-like API.
- Identify entities (5 minutes). Pull nouns from the requirements. Each noun with state or behavior is a class candidate. Each "type of" list (vehicle types, spot sizes) is an enum or a small hierarchy.
- Define relationships (5 minutes). Decide who owns whom (composition), who just references whom (association), and what inherits from what. Sketch a quick class diagram.
- Isolate change points (5 minutes). Ask which rules are most likely to change: pricing, allocation, payment, notifications. Put each behind an interface. This is where patterns earn their place.
- Code the core flow, then extend (remaining time). Build the happy path end to end first, add a demo driver, then handle edge cases and the interviewer's follow-ups.
A useful rule of thumb: if you are 40 minutes into a 90 minute round with no running code, you have spent too long on step 3. Cut scope and get one flow working.
Requirements for a Parking Lot
Good requirements for a parking lot are short, testable, and include an explicit out-of-scope list. Here is a scope that fits a 60 to 90 minute round.
Questions worth asking the interviewer:
- How many floors and entry/exit gates? Is it one lot or many?
- Which vehicle types, and which spot sizes? Can a small vehicle use a larger spot?
- How is the fee calculated: flat, hourly, or tiered by vehicle type?
- Do we need payment processing, or just fee calculation?
- Is the interface a CLI, method calls, or an API?
- Do we need to handle concurrent entries from multiple gates?
Functional requirements (agreed scope):
- The lot has multiple floors, each with spots of type SMALL, MEDIUM, or LARGE.
- Vehicles are MOTORCYCLE, CAR, or TRUCK. A motorcycle fits any spot, a car fits MEDIUM or LARGE, a truck fits only LARGE.
- On entry, the system assigns a spot and issues a ticket with entry time.
- On exit, the system calculates the fee from the ticket, frees the spot, and closes the ticket.
- The system can report free spots per floor and spot type.
Out of scope for v1: real payment gateways, reservations, user accounts, persistence. Saying this out loud shows judgment, and it gives you ready-made extension topics later.
Class Diagram and Relationships
The parking lot class diagram has six core classes and two strategy interfaces. The lot owns floors, floors own spots, and tickets link a vehicle to a spot for a period of time.
ParkingLot 1 ◆── * Floor 1 ◆── * Spot
│ ▲
│ uses │ references
├── SpotAllocationStrategy │
├── PricingStrategy Ticket ── Vehicle
└── 1 ◆── * Gate (ENTRY | EXIT)
Vehicle (plate, type: VehicleType)
Spot (id, floor, type: SpotType, vehicle: Vehicle | None)
Ticket (id, vehicle, spot, entry_time, exit_time, fee)
Key relationship decisions and why they hold up:
- Composition, ParkingLot to Floor to Spot. Floors and spots do not exist outside the lot, so the lot creates and owns them.
- Association, Ticket to Vehicle and Spot. A ticket references both but does not own them. The spot outlives the ticket.
- Enums over inheritance for Vehicle. In v1, vehicle types differ only in data (which spots they fit), not behavior. A
VehicleTypeenum is simpler thanCar extends Vehicle. If the interviewer adds behavior, such as EVs that need chargers, a subclass or a capability field becomes justified. - Strategies as interfaces. Allocation and pricing are the two rules most likely to change, so the lot depends on interfaces, not concrete classes.
Being able to defend "why enum, not subclass" is one of the clearest signals of design maturity in this question. Most weak answers create Car, Bike, and Truck subclasses that add nothing.
Code Skeleton for the Parking Lot
The code skeleton below is a complete, runnable Python version of the core flow, short enough to type in about 25 minutes. The same structure maps directly to Java with interfaces and enums. If you are deciding between languages, our Java interview questions guide and Python interview questions guide cover the OOP features interviewers expect you to know.
Enums and core entities
from __future__ import annotations
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
import itertools
import math
class VehicleType(Enum):
MOTORCYCLE = "motorcycle"
CAR = "car"
TRUCK = "truck"
class SpotType(Enum):
SMALL = 1
MEDIUM = 2
LARGE = 3
FITS: dict[VehicleType, list[SpotType]] = {
VehicleType.MOTORCYCLE: [SpotType.SMALL, SpotType.MEDIUM, SpotType.LARGE],
VehicleType.CAR: [SpotType.MEDIUM, SpotType.LARGE],
VehicleType.TRUCK: [SpotType.LARGE],
}
@dataclass(frozen=True)
class Vehicle:
plate: str
type: VehicleType
@dataclass
class Spot:
id: str
floor: int
type: SpotType
vehicle: Vehicle | None = None
def is_free(self) -> bool:
return self.vehicle is None
@dataclass
class Floor:
number: int
spots: list[Spot] = field(default_factory=list)
def free_spots(self, spot_type: SpotType) -> list[Spot]:
return [s for s in self.spots if s.type == spot_type and s.is_free()]
@dataclass
class Ticket:
id: int
vehicle: Vehicle
spot: Spot
entry_time: datetime
exit_time: datetime | None = None
fee: float | None = None
Strategies for allocation and pricing
class SpotAllocationStrategy(ABC):
@abstractmethod
def find_spot(self, floors: list[Floor], vehicle: Vehicle) -> Spot | None: ...
class NearestFirstAllocation(SpotAllocationStrategy):
def find_spot(self, floors, vehicle):
for spot_type in FITS[vehicle.type]:
for floor in floors:
free = floor.free_spots(spot_type)
if free:
return free[0]
return None
class PricingStrategy(ABC):
@abstractmethod
def calculate(self, ticket: Ticket) -> float: ...
class HourlyPricing(PricingStrategy):
RATES = {VehicleType.MOTORCYCLE: 1.0, VehicleType.CAR: 2.5, VehicleType.TRUCK: 5.0}
def calculate(self, ticket):
hours = (ticket.exit_time - ticket.entry_time).total_seconds() / 3600
return max(1, math.ceil(hours)) * self.RATES[ticket.vehicle.type]
The ParkingLot service and a demo
class ParkingFullError(Exception):
pass
class ParkingLot:
def __init__(self, floors: list[Floor],
allocator: SpotAllocationStrategy,
pricing: PricingStrategy):
self.floors = floors
self.allocator = allocator
self.pricing = pricing
self.active: dict[str, Ticket] = {}
self._ids = itertools.count(1)
def park(self, vehicle: Vehicle, now: datetime | None = None) -> Ticket:
if vehicle.plate in self.active:
raise ValueError(f"{vehicle.plate} is already parked")
spot = self.allocator.find_spot(self.floors, vehicle)
if spot is None:
raise ParkingFullError(f"No spot for {vehicle.type.value}")
spot.vehicle = vehicle
ticket = Ticket(next(self._ids), vehicle, spot, now or datetime.now())
self.active[vehicle.plate] = ticket
return ticket
def unpark(self, plate: str, now: datetime | None = None) -> Ticket:
ticket = self.active.pop(plate)
ticket.exit_time = now or datetime.now()
ticket.fee = self.pricing.calculate(ticket)
ticket.spot.vehicle = None
return ticket
def availability(self) -> dict[int, dict[str, int]]:
return {
f.number: {t.name: len(f.free_spots(t)) for t in SpotType}
for f in self.floors
}
if __name__ == "__main__":
floors = [
Floor(n, [Spot(f"{n}-{i}", n, t) for i, t in enumerate(
[SpotType.SMALL] * 2 + [SpotType.MEDIUM] * 3 + [SpotType.LARGE])])
for n in range(2)
]
lot = ParkingLot(floors, NearestFirstAllocation(), HourlyPricing())
t = lot.park(Vehicle("KA01AB1234", VehicleType.CAR), datetime(2026, 10, 1, 9, 0))
print(t.spot.id, lot.availability())
done = lot.unpark("KA01AB1234", datetime(2026, 10, 1, 11, 20))
print(done.fee)
Running the demo parks the car in spot 0-2 (the first MEDIUM spot) and charges 7.5 for 2 hours 20 minutes, which rounds up to 3 billable hours at 2.5 per hour.
Notice what the ParkingLot class does not know: how spots are chosen and how money is calculated. That is the whole point of the design, and it is what you should say out loud when you finish this section.
Machine coding rounds give you 90 minutes and no second chance to remember how you meant to structure the allocation strategy. TechScreen is an AI interview assistant that can suggest class structures and edge cases in real time. Start with 3 free tokens.
Applying Design Patterns: Strategy, Factory, and When to Stop
Design patterns in an LLD interview should solve a problem you can name in one sentence. If you cannot say what pain a pattern removes, leave it out.
Strategy pattern. Strategy is a pattern where a family of interchangeable algorithms sits behind one interface, and the caller picks one at runtime. In the parking lot, both allocation and pricing are strategies. When the interviewer says "weekends are a flat rate" you write WeekendFlatPricing and inject it. Nothing else changes.
Factory pattern. A factory is a single place that turns raw input into the right object. If the round uses a CLI like park KA01AB1234 car, a factory keeps string parsing out of your domain classes:
class VehicleFactory:
@staticmethod
def create(plate: str, raw_type: str) -> Vehicle:
try:
return Vehicle(plate, VehicleType(raw_type.lower()))
except ValueError:
raise ValueError(f"Unknown vehicle type: {raw_type}")
Singleton. Many candidates make ParkingLot a singleton. It is defensible for "one physical lot," but singletons make testing harder. A stronger answer is: "I'll create one instance in main and inject it. If we need a global, I can wrap it later." Interviewers usually prefer that reasoning to the pattern itself.
Observer. Observer fits display boards at each floor entrance. The lot publishes "spot taken" and "spot freed" events, and boards subscribe. Mention it as an extension rather than building it upfront.
For a broader review of when each pattern fits, including the ones interviewers ask about by name, see our design patterns interview questions guide.
| Pattern | Where it fits in the parking lot | Build in v1? |
|---|---|---|
| Strategy | Spot allocation, pricing | Yes |
| Factory | Vehicle and spot creation from input | Yes, if there is a CLI |
| Singleton | The ParkingLot instance | Mention, prefer injection |
| Observer | Floor display boards, alerts | Extension |
| State | Ticket lifecycle (active, paid, lost) | Extension |
| Decorator | Add-ons like valet or car wash fees | Extension |
Extensions and Follow-Up Questions
Extension questions test whether your design bends or breaks. A good design answers most of them by adding a class rather than editing existing ones. Here are the follow-ups that come up most often, with a short answer for each.
1. "Add electric vehicle charging spots." Add a charger: bool field on Spot, or an EV_LARGE spot type, and an EVFirstAllocation strategy that prefers charger spots for EVs. Pricing gets a ChargingPricing that wraps the base pricing and adds an energy fee, which is a natural use of Decorator.
2. "Pricing changes by time of day." Write a TimeBandPricing strategy that splits the stay into bands and sums each band's rate. The ParkingLot class does not change.
3. "Two gates assign the same spot at once." This is the concurrency follow-up. Make allocation atomic: take a lock around find_spot plus the assignment, or keep a thread-safe free list per spot type and pop from it in one operation. Locking per floor or per spot type reduces contention compared with one global lock. Our concurrency and multithreading interview questions guide covers the locking primitives you should be able to name.
4. "Allocation is slow with 10,000 spots." The skeleton scans lists linearly. Replace it with a min-heap or ordered set of free spots per (floor, spot type), so finding the nearest free spot is O(log n) and freeing is O(log n).
5. "Support reservations." Add a Reservation entity with a time window and a RESERVED spot state. Allocation skips reserved spots unless the arriving vehicle holds a matching reservation.
6. "Handle a lost ticket." Look up the active ticket by plate (already supported by the active dict) and apply a LostTicketPricing penalty strategy.
7. "Now make it a multi-lot service with an API." This shifts the round toward high-level design: a service per region, a database for tickets, and idempotent entry and exit endpoints. If the conversation goes there, the thinking in our system design interview guide applies, and the rate limiter design walkthrough is a good example of pluggable policies at the service level.
If a follow-up stumps you, narrate the trade-off you are weighing rather than going silent. The tactics in what to do when you get stuck in a coding interview apply just as well to design rounds.
Common Mistakes in Parking Lot LLD Answers
Most failed parking lot answers fail for the same handful of reasons, and all of them are avoidable.
- Skipping requirements. Designing for reservations, payments, and valet before confirming scope burns 20 minutes you need for code.
- Subclass explosion.
Car,Bike,Truck,SmallSpot,MediumSpot,LargeSpotwith no behavior differences. Use enums until behavior differs. - Logic in the wrong place. Fee calculation inside
TicketorSpotties data to rules that change often. - Type checks everywhere.
if vehicle.type == "car" and spot.size == "medium"repeated in several methods. Centralize compatibility in one map or method. - No runnable demo. In a machine coding round, code that does not execute usually scores below a simpler design that does.
- No error handling. A full lot, a duplicate plate, and an unknown ticket are the three edge cases interviewers check first.
How to Practice LLD for Your Next Round
Practicing LLD works best as timed, end-to-end builds rather than reading solutions. Set a 90 minute timer, write requirements, sketch the diagram, and build to a running demo. Then ask yourself one extension question and time how long the change takes. If it takes more than 10 minutes, your design has a coupling problem worth finding.
Good next problems that reuse the same framework: elevator system, vending machine, library management, splitwise-style expense sharing, a rate limiter class, an LRU cache, and a tic-tac-toe or snake-and-ladder game. Each one has an obvious Strategy or State seam once you look for what changes.
Finally, remember the round is also a conversation. Interviewers in LLD rounds care about many of the same signals as in algorithm rounds, which we break down in what interviewers look for in coding interviews.
Low-level design rounds reward structure under time pressure, and blanking on a pattern or edge case can cost the round. TechScreen gives you real-time hints on class design, patterns, and follow-up answers in your machine coding round. Try it with 3 free tokens.
Frequently Asked Questions
What is a low level design interview?
A low level design interview asks you to model a small, self-contained system as classes, interfaces, and methods, then write code for the core flows. Instead of drawing load balancers and databases, you decide which objects exist, what each one owns, and how they talk to each other. Interviewers grade object-oriented modeling, clean responsibilities, sensible use of design patterns, and whether your code is easy to extend when requirements change mid-round.
What is the difference between LLD and HLD interviews?
High-level design (HLD) covers distributed architecture: services, storage, caching, queues, and scaling to millions of users. Low-level design (LLD) zooms into a single service or application and covers classes, interfaces, relationships, and method signatures. A parking lot in HLD would discuss multiple garages and a payments service. In LLD it means a ParkingLot class, spot types, a ticket flow, and a pluggable pricing strategy that compiles and runs.
How long is a machine coding round?
Most machine coding rounds run between 60 and 120 minutes, with 90 minutes being a common format at product companies that use them. You usually get a written problem statement, spend a few minutes clarifying, then build working code on your own machine or in a shared editor. Some companies add a 15 to 30 minute review at the end where the interviewer asks you to extend the design live.
Which design patterns should I know for a parking lot LLD question?
Strategy and Factory are the two that matter most. Strategy lets you swap spot allocation rules and pricing rules without editing the ParkingLot class. Factory centralizes creation of vehicles or spots from input strings. Singleton comes up for the lot itself, though many interviewers prefer dependency injection instead. Observer is a useful extension for display boards that show free spots per floor.
Which programming language is best for LLD interviews?
Java is a common choice because interfaces, abstract classes, and enums map directly onto class diagrams, and many interviewers are used to reading it. Python, C++, Kotlin, Go, and TypeScript are all generally accepted. Pick the language where you can write classes and interfaces quickly without looking up syntax. Confirm with your recruiter, since a few companies restrict languages for machine coding rounds.
Do I need to handle concurrency in a parking lot design?
Usually not in the first version, but expect it as a follow-up. The interviewer may ask what happens when two entry gates try to assign the same spot at the same time. A good answer is to make spot allocation atomic, either with a lock per floor or spot type, or by removing the spot from a thread-safe free list in one operation, so two tickets never point at the same spot.
Is the parking lot question still asked in 2026?
Yes. It remains one of the most common LLD prompts because it is small enough to finish in an hour and rich enough to test inheritance, composition, patterns, and extensibility. Interviewers who ask it often add a twist, such as electric vehicle charging, dynamic pricing, or multiple entry gates, so memorizing one answer is less useful than knowing how to extend any design cleanly.
Ready to use AI assistance in your next interview?
TechScreen is the invisible AI assistant trusted by engineers interviewing at Google, Meta, Amazon, and hundreds of other companies. Start with 3 free tokens — no credit card required.
Ace your next interview →