Back to Tech Interviews

Low-Level Design (LLD) Interview Questions

Master Object-Oriented Design (OOD), UML Modeling, SOLID Principles, Design Patterns, and Real-World Machine Coding Systems

Total: 12 QuestionsLearned: 0 / 12 (0%)
Difficulty Filters

Tools & Options
Showing 12 of 12 questions
Beginner
How do you structure a 45-Minute Low-Level Design (LLD) Interview step-by-step?

A structured 6-step framework to crack LLD / Object-Oriented Design interviews:

1. Clarify Requirements (5-7 mins):

- Identify Functional Requirements (e.g. Parking Lot: park vehicle, unpark vehicle, calculate fee) and Non-Functional Requirements (e.g. thread-safety, extensibility).

- Define scope boundaries (What to include vs exclude).

2. Identify Core Domain Entities & Enums (5 mins):

- Identify Nouns in requirement statements (e.g. Vehicle, Spot, Ticket, Payment, ParkingFloor).

- Define Enums for fixed states (VehicleType: CAR, BIKE, TRUCK; SpotType: COMPACT, LARGE, ELECTRIC; TicketStatus: ACTIVE, PAID).

3. Define Class Diagrams & UML Relationships (8-10 mins):

- Establish relationships: Inheritance (Is-A), Composition (Has-A strict life cycle), Aggregation (Has-A weak relationship), Association (Uses-A).

4. Apply Appropriate Design Patterns (5 mins):

- Identify extension points (e.g. Pricing Strategy -> Strategy Pattern; Vehicle Creation -> Factory Pattern; State transitions -> State Pattern).

5. Write Clean Object-Oriented Code (15 mins):

- Use Interfaces, Abstract Classes, Dependency Injection, and Encapsulation. Follow SOLID principles.

6. Address Concurrency & Edge Cases (5 mins):

- Handle thread-safety for shared mutable state (e.g. double booking, spot allocation race conditions using Mutex/Locks or Atomic operations).

/* Standard LLD Class Architecture Template
Domain Models -> Enums -> Strategy Interfaces -> Service Controllers -> Repository/Store */

// 1. Enum Definition
const VehicleType = Object.freeze({
  CAR: 'CAR',
  BIKE: 'BIKE',
  TRUCK: 'TRUCK'
});

// 2. Base Entity (Abstraction)
class Vehicle {
  constructor(licensePlate, type) {
    this.licensePlate = licensePlate;
    this.type = type;
  }
}

// 3. Subclass (Inheritance)
class Car extends Vehicle {
  constructor(licensePlate) {
    super(licensePlate, VehicleType.CAR);
  }
}
Beginner
Explain UML Class Diagram Relationships: Association, Aggregation, Composition, and Generalization.

UML Class Diagram relationships describe how classes interact:

1. Association (Uses-A):

- A loose relationship between two independent classes where one object uses the services of another (e.g. `Driver` uses `Car`). Both can exist independently.

2. Aggregation (Has-A Weak):

- A whole-part relationship where the child can exist independently of the parent container (e.g. `Department` has `Professors`. If `Department` is deleted, `Professors` still exist).

3. Composition (Has-A Strict):

- A strong whole-part relationship where the child CANNOT exist without the parent container. The child's lifecycle is bound to the parent (e.g. `House` has `Rooms`. If `House` is destroyed, `Rooms` cease to exist).

4. Generalization (Is-A / Inheritance):

- A subclass inherits attributes and methods from a superclass (e.g. `Dog` extends `Animal`).

5. Realization (Implements):

- A concrete class implements the contract defined by an interface.

/* UML Relationships Code Representation

1. Composition (Strict Ownership) */
class House {
  constructor() {
    this.rooms = [new Room('Living Room'), new Room('Bedroom')]; // Created inside House
  }
}

/* 2. Aggregation (Weak Ownership) */
class Department {
  constructor(professors = []) {
    this.professors = professors; // Injected from outside
  }
}

/* 3. Association (Uses-A) */
class Driver {
  drive(car) {
    car.startEngine(); // Uses car transiently
  }
}
Intermediate
Design a Parking Lot System (Object-Oriented Design).

Design Requirements:

- Multi-floor parking lot supporting Vehicle Types: Bike, Car, Truck.

- Spot Types: Small, Medium, Large, EV Spot.

- Features: Issue Parking Ticket upon entry, Assign nearest available spot, Calculate parking fee dynamically upon exit (Hourly vs Flat pricing), Process Payment.

- Design Patterns Used: Strategy Pattern (PricingStrategy, SpotAssignmentStrategy), Factory Pattern (VehicleFactory).

// Enums
const VehicleType = { BIKE: 'BIKE', CAR: 'CAR', TRUCK: 'TRUCK' };
const SpotType = { SMALL: 'SMALL', MEDIUM: 'MEDIUM', LARGE: 'LARGE' };

// Entities
class ParkingSpot {
  constructor(id, type, floor) {
    this.id = id;
    this.type = type;
    this.floor = floor;
    this.isOccupied = false;
    this.vehicle = null;
  }

  assignVehicle(vehicle) {
    this.vehicle = vehicle;
    this.isOccupied = true;
  }

  removeVehicle() {
    this.vehicle = null;
    this.isOccupied = false;
  }
}

class Ticket {
  constructor(id, vehicle, spot) {
    this.id = id;
    this.vehicle = vehicle;
    this.spot = spot;
    this.entryTime = new Date();
    this.exitTime = null;
    this.fee = 0;
  }
}

// Strategy Pattern for Pricing
class PricingStrategy {
  calculateFee(ticket) {
    const hours = Math.ceil((new Date() - ticket.entryTime) / (1000 * 60 * 60));
    const rates = { BIKE: 10, CAR: 20, TRUCK: 50 };
    return hours * (rates[ticket.vehicle.type] || 20);
  }
}

// Main Parking Lot Manager
class ParkingLot {
  constructor(name, pricingStrategy) {
    this.name = name;
    this.spots = [];
    this.tickets = new Map();
    this.pricingStrategy = pricingStrategy;
  }

  addSpot(spot) { this.spots.push(spot); }

  parkVehicle(vehicle) {
    const spot = this.spots.find(s => !s.isOccupied && this._isCompatible(vehicle.type, s.type));
    if (!spot) throw new Error("No available spot for vehicle type: " + vehicle.type);

    spot.assignVehicle(vehicle);
    const ticket = new Ticket("TICK-" + Date.now(), vehicle, spot);
    this.tickets.set(ticket.id, ticket);
    return ticket;
  }

  unparkVehicle(ticketId) {
    const ticket = this.tickets.get(ticketId);
    if (!ticket) throw new Error("Invalid Ticket ID");

    ticket.exitTime = new Date();
    ticket.fee = this.pricingStrategy.calculateFee(ticket);
    ticket.spot.removeVehicle();
    return ticket;
  }

  _isCompatible(vType, sType) {
    if (vType === VehicleType.BIKE) return true;
    if (vType === VehicleType.CAR) return sType === SpotType.MEDIUM || sType === SpotType.LARGE;
    if (vType === VehicleType.TRUCK) return sType === SpotType.LARGE;
    return false;
  }
}
Intermediate
Design an Elevator Control System (State & Strategy Patterns).
Intermediate
Design a Rate Limiter (Token Bucket Algorithm with Thread-Safety).
Intermediate
Design a Vending Machine using the State Pattern.
Intermediate
Design Tic-Tac-Toe Game with O(1) Move Validation.
Advanced
Design BookMyShow (Movie Ticket Booking System with Temporary Seat Locking).
Intermediate
Design an E-Commerce Shopping Cart & Checkout System (Strategy Pattern for Discounts).
Intermediate
Design a Multi-Channel Notification Service (Factory & Observer Patterns).
Advanced
Design a Logger Framework (Chain of Responsibility Pattern).
Advanced
Design an In-Memory File System (Composite Pattern for Files and Directories).

Technical Interview Mastery Blueprint

Proven methodologies and frameworks to succeed in technical and architecture rounds.

1. The Engineering STAR Technique

When responding to architectural or situational questions, structure your answer using Situation, Technical Constraint, Action, and Measurable Result. Rather than jumping straight to syntax, articulate the business problem, why certain patterns (e.g. caching, queuing, immutability) were selected over alternatives, and what latency or throughput improvements were achieved.

2. Defending Architectural Trade-Offs

Senior interviewers evaluate how you weigh trade-offs. Always explain why you chose an approach: e.g., memory overhead vs CPU cycle speed, consistency vs availability (CAP theorem), or normalized schemas vs denormalized fast reads. Stating the drawbacks of your own proposal demonstrates maturity and production experience.

3. Clean Code & Edge-Case Proactivity

In live-coding rounds, communicate your thinking aloud before typing. State edge cases explicitly: null or undefined inputs, extreme boundary values, concurrency races, and network timeouts. Writing modular, well-named functions with deterministic unit tests separates junior candidates from staff-level engineers.

4. Antipatterns to Avoid

Avoid reciting memorized definitions without practical context. Never dismiss non-functional requirements such as security (CSRF, injection, token rotation), observability (logging, metrics), and accessibility (ARIA, semantic standards). Always ask clarifying scope questions before writing complex implementations.

Continuous learning: Practice daily, mark completed questions as learned, and revisit difficult concepts.Explore All Interview Tracks →

Explore Related Tools

Hand-picked utilities and calculators related to this tool.

Related Tools