Common LLD Interview Questions Tutorial from Scratch (2026)
Low-level design interviews assess your ability to translate requirements into class hierarchies, design patterns, and clean abstractions. Common problems include designing a parking lot system, elevator controller, vending machine, chess game, and other real-world systems that test your OOP skills.
This tutorial walks through the most frequently asked LLD interview questions, explains the expected design approach for each, and highlights the key design patterns and principles that interviewers look for in your solution.
Parking Lot Design
Design a parking lot with multiple floors, different spot types (compact, large, handicapped, motorcycle), ticketing system, and fee calculation. Key classes include ParkingLot, Floor, Spot, Ticket, and Payment. Use the strategy pattern for fee calculation and observer pattern for spot availability notifications.
class ParkingSpot {
constructor(id, type) {
this.id = id;
this.type = type;
this.isAvailable = true;
this.vehicle = null;
}
park(vehicle) {
if (!this.isAvailable) throw new Error("Spot occupied");
this.vehicle = vehicle;
this.isAvailable = false;
}
leave() {
this.vehicle = null;
this.isAvailable = true;
}
}
class ParkingFloor {
constructor(level, spots) {
this.level = level;
this.spots = spots;
}
findAvailableSpot(type) {
return this.spots.find(s => s.isAvailable && s.type === type);
}
}
class ParkingLot {
constructor(floors) { this.floors = floors; }
parkVehicle(vehicle) {
for (const floor of this.floors) {
const spot = floor.findAvailableSpot(vehicle.type);
if (spot) { spot.park(vehicle); return new Ticket(vehicle, floor.level, spot.id); }
}
throw new Error("No spots available");
}
}
Elevator System Design
Design an elevator control system that handles multiple elevators, floor requests, door operations, and scheduling algorithms. Core classes include Elevator, ElevatorController, Button, Door, and Request. Implement algorithms like SCAN (elevator algorithm), FCFS, or SSTF for efficient dispatching.
class Elevator {
constructor(id, capacity) {
this.id = id;
this.capacity = capacity;
this.currentFloor = 0;
this.direction = "idle";
this.requests = [];
this.doorsOpen = false;
}
addRequest(floor) {
this.requests.push(floor);
if (this.direction === "idle") {
this.direction = floor > this.currentFloor ? "up" : "down";
}
}
move() {
if (this.requests.length === 0) { this.direction = "idle"; return; }
const target = this.direction === "up"
? Math.min(...this.requests.filter(f => f >= this.currentFloor))
: Math.max(...this.requests.filter(f => f <= this.currentFloor));
this.currentFloor = target;
this.requests = this.requests.filter(f => f !== target);
}
}
class ElevatorController {
constructor(elevators) { this.elevators = elevators; }
requestElevator(floor, direction) {
const best = this.elevators
.filter(e => e.direction === "idle" || e.direction === direction)
.reduce((a, b) =>
Math.abs(a.currentFloor - floor) < Math.abs(b.currentFloor - floor) ? a : b
);
best.addRequest(floor);
}
}
Vending Machine and Chess Design
Design a vending machine with inventory management, coin/bill acceptance, item selection, and change dispensing. For chess, model pieces with movement rules, board state, turn management, check/checkmate validation, and special moves like castling and en passant. Both problems test your ability to model state machines and rule engines.
class VendingMachine {
constructor() {
this.inventory = new Map();
this.balance = 0;
this.selectedItem = null;
}
selectItem(code) {
const item = this.inventory.get(code);
if (!item || item.quantity === 0) throw new Error("Item unavailable");
this.selectedItem = item;
return item.price;
}
insertCoin(amount) { this.balance += amount; }
dispense() {
if (!this.selectedItem) throw new Error("No item selected");
if (this.balance < this.selectedItem.price) throw new Error("Insufficient funds");
this.selectedItem.quantity--;
const change = this.balance - this.selectedItem.price;
this.balance = 0;
this.selectedItem = null;
return { item: this.selectedItem.name, change };
}
}
class Board {
constructor() {
this.grid = this.initializeBoard();
this.currentTurn = "white";
}
movePiece(from, to) {
const piece = this.grid[from.row][from.col];
if (!piece || piece.color !== this.currentTurn) throw new Error("Invalid move");
this.grid[to.row][to.col] = piece;
this.grid[from.row][from.col] = null;
piece.hasMoved = true;
this.currentTurn = this.currentTurn === "white" ? "black" : "white";
}
}
Frequently Asked Questions
How should I approach an LLD interview problem?
Start by clarifying requirements and identifying core entities. Define the key classes with their attributes and methods, establish relationships between classes, then discuss design patterns that solve the problem elegantly. Always consider extensibility and edge cases.
What design patterns are most commonly used in LLD?
Strategy pattern (algorithm selection), Observer pattern (event notification), Factory pattern (object creation), Singleton pattern (shared resources), State pattern (state-dependent behavior), and Command pattern (request encapsulation) are the most frequently applied.
How much detail should I include in my class design?
Focus on the essential attributes, methods, and relationships that demonstrate your design thinking. You do not need to implement every getter/setter or trivial method. Highlight the design patterns, relationships (inheritance, composition), and how the system handles edge cases.
Do I need to write working code in LLD interviews?
Most LLD interviews expect working or near-working code for the core functionality. Focus on clean class structures, proper method signatures, and logical correctness. Interviewers value readability, extensibility, and appropriate use of OOP principles over covering every edge case.
Originally published on Ayodhyyya. Last updated June 1, 2026.