Build a Parking Lot System

Difficulty: Medium · Category: Parking System · Languages: Java 17, Python 3.11, Go 1.22, Node.js 20, TypeScript 5.x

Parking Lot System

Background

A parking lot is one of the most classic Low-Level Design problems. It tests your ability to model real-world entities (floors, spots, vehicles, tickets), handle concurrent access, compute duration-based fees, and maintain accurate occupancy statistics.

Production parking systems must handle thousands of vehicles per day, track every entry and exit, support multiple vehicle sizes, and provide real-time availability — all while keeping data consistent under concurrent operations.

Recommended infrastructure: PostgreSQL — gives you relational > integrity for spot allocation, transactional consistency for > concurrent park/unpark, and indexed queries for history lookups.

How It Works

The platform injects your chosen infrastructure SDK(s) via constructor. For example, if you select PostgreSQL:

public class MyParkingLot implements ParkingLotContract {
    private final PostgresClient pg;

    public MyParkingLot(PostgresClient pg) {
        this.pg = pg;
    }
}

See the SDK Docs tab for the full API reference of your chosen system.

Your Task

Implement the ParkingLotContract interface. Your implementation must:

  1. Persist all state externally — spots, tickets, fee rates, and history must be stored in your chosen system (no in-process-only data structures).
  2. Support three vehicle types: CAR (1 spot), MOTORCYCLE (1 spot), and TRUCK (2 consecutive spots).
  3. Issue a unique ticket ID on every successful park operation.
  4. Calculate duration-based fees: ceil(hours) × hourlyRate.
  5. Be thread-safe: concurrent park/unpark must not double-book spots.
  6. Track parking history per vehicle number.
  7. Provide real-time occupancy statistics including per-type breakdowns.

Interface

public interface ParkingLotContract {
    void initialize(int floors, int spotsPerFloor);
    String parkVehicle(String vehicleNumber, String vehicleType);
    double unparkVehicle(String ticketId);
    Map<String, Object> getVehicleLocation(String ticketId);
    int getAvailableSpots(int floor, String vehicleType);
    int getTotalAvailableSpots();
    boolean isFull(String vehicleType);
    double getFeeRate(String vehicleType);
    void setFeeRate(String vehicleType, double ratePerHour);
    List<Map<String, Object>> getVehicleHistory(String vehicleNumber);
    Map<String, Object> getLotStats();
}

Method Details

MethodDescription
initializeCreate the lot with N floors × M spots. Clears any existing data.
parkVehicleAllocate spot(s) on the lowest available floor. Return ticket ID or null if full.
unparkVehicleFree the spot(s), compute fee based on duration × rate. Return fee or -1 for invalid ticket.
getVehicleLocationReturn {floor, spotNumber, vehicleType} for a parked vehicle. null if unparked/invalid.
getAvailableSpotsCount of available spots (or consecutive pairs for TRUCK) on a floor.
getTotalAvailableSpotsTotal free individual spots across all floors.
isFulltrue if no spot can accommodate the given vehicle type.
getFeeRate / setFeeRateGet or set the hourly rate for a vehicle type.
getVehicleHistoryFull entry/exit history for a vehicle number, including fees.
getLotStatsOverall stats: totalSpots, occupiedSpots, occupancyPercent, byType breakdown.

Constraints

Examples

initialize(3, 10)             // 3 floors, 10 spots each = 30 total
setFeeRate("CAR", 20.0)
setFeeRate("MOTORCYCLE", 10.0)
setFeeRate("TRUCK", 40.0)

parkVehicle("KA-01-1234", "CAR")        → "TKT-abc123"
parkVehicle("KA-02-5678", "TRUCK")       → "TKT-def456"

getVehicleLocation("TKT-abc123")         → {floor=1, spotNumber=1, vehicleType="CAR"}
getAvailableSpots(1, "CAR")              → 7  (1 car + 1 truck taking 2 spots)
getTotalAvailableSpots()                 → 27

isFull("CAR")                            → false
getLotStats()                            → {totalSpots=30, occupiedSpots=3, occupancyPercent=10.0, byType={...}}

// After 2 hours...
unparkVehicle("TKT-abc123")              → 40.0  (2 hours × $20/hr)
unparkVehicle("TKT-abc123")              → -1    (already unparked)

getVehicleHistory("KA-01-1234")          → [{ticketId="TKT-abc123", floor=1, ...}]

Hints

Infrastructure your code runs against

How your solution is graded

Your score combines functional correctness (40%), performance (40%) and code quality (20%).

Practice this problem

Related LLD problems