← All articles
13 min read

Low-Level Design Interview: Design a Parking Lot (2026 Guide)

The parking lot is the most common low-level design interview question. Here is a complete answer, from requirements to running code, plus a 5-step framework you can reuse in any machine coding round.

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:

SignalWhat strong looks likeCommon red flag
RequirementsAsks 4-6 sharp questions, writes scope downStarts coding in minute one
ModelingNouns become classes with clear ownershipOne god class with 20 methods
ResponsibilitiesEach class has one reason to changePricing logic inside the Spot class
ExtensibilityNew vehicle or price rule = new classLong if/else chains on type strings
PatternsUsed where they remove a real painPatterns added to look clever
Working codeCore flow runs end to end with a demoOnly interfaces, nothing executes
CommunicationExplains trade-offs while codingSilent 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.

  1. 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.
  2. 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.
  3. Define relationships (5 minutes). Decide who owns whom (composition), who just references whom (association), and what inherits from what. Sketch a quick class diagram.
  4. 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.
  5. 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 VehicleType enum is simpler than Car 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.

Get started free →

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.

PatternWhere it fits in the parking lotBuild in v1?
StrategySpot allocation, pricingYes
FactoryVehicle and spot creation from inputYes, if there is a CLI
SingletonThe ParkingLot instanceMention, prefer injection
ObserverFloor display boards, alertsExtension
StateTicket lifecycle (active, paid, lost)Extension
DecoratorAdd-ons like valet or car wash feesExtension

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, LargeSpot with no behavior differences. Use enums until behavior differs.
  • Logic in the wrong place. Fee calculation inside Ticket or Spot ties 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.

Get started free →

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 →