Low-Level Design: Elevator System
The elevator system is a classic OOP interview problem testing state machines, dispatching algorithms, and clean class design. The interviewer wants to see: how you model the core entities, how requests are dispatched across multiple elevators, and how the elevator decides which floors to service in what order.
Core Classes
Direction and State Enums
from enum import Enum
class Direction(Enum):
UP = "UP"
DOWN = "DOWN"
IDLE = "IDLE"
class ElevatorState(Enum):
MOVING = "MOVING"
STOPPED = "STOPPED"
MAINTENANCE = "MAINTENANCE"
Request
from dataclasses import dataclass
@dataclass
class ExternalRequest:
"""Button pressed in the hallway."""
floor: int
direction: Direction
@dataclass
class InternalRequest:
"""Button pressed inside the elevator."""
floor: int
Elevator
class Elevator:
def __init__(self, elevator_id: int, total_floors: int):
self.elevator_id = elevator_id
self.current_floor = 1
self.direction = Direction.IDLE
self.state = ElevatorState.STOPPED
self.destinations = set() # floors to stop at
def add_destination(self, floor: int) -> None:
self.destinations.add(floor)
def move(self) -> None:
"""Advance one floor in current direction (SCAN algorithm)."""
if not self.destinations:
self.direction = Direction.IDLE
self.state = ElevatorState.STOPPED
return
if self.direction == Direction.UP or self.direction == Direction.IDLE:
above = [f for f in self.destinations if f > self.current_floor]
if above:
self.direction = Direction.UP
self.state = ElevatorState.MOVING
self.current_floor += 1
else:
self.direction = Direction.DOWN
self.move() # re-evaluate downward
else:
below = [f for f in self.destinations if f list[int]:
"""
Process one time step. Move toward next destination,
stop if current floor is a destination.
Returns list of floors where doors opened this step.
"""
opened = []
if self.current_floor in self.destinations:
self.destinations.remove(self.current_floor)
self.state = ElevatorState.STOPPED
opened.append(self.current_floor)
if self.destinations:
self.move()
return opened
def cost_to_serve(self, request_floor: int, direction: Direction) -> int:
"""
Estimate steps needed to serve this request.
Used by dispatcher for assignment scoring.
"""
distance = abs(self.current_floor - request_floor)
# Penalize if elevator is going in opposite direction
if self.direction != Direction.IDLE and self.direction != direction:
return distance + 20 # detour penalty
return distance
ElevatorSystem (Dispatcher)
class ElevatorSystem:
def __init__(self, num_elevators: int, num_floors: int):
self.elevators = [
Elevator(i, num_floors) for i in range(num_elevators)
]
self.num_floors = num_floors
def request_elevator(self, floor: int, direction: Direction) -> None:
"""External request: person on a floor presses UP or DOWN."""
best = min(
self.elevators,
key=lambda e: e.cost_to_serve(floor, direction)
)
best.add_destination(floor)
print(f"Elevator {best.elevator_id} assigned to floor {floor} ({direction.value})")
def select_floor(self, elevator_id: int, floor: int) -> None:
"""Internal request: person inside elevator presses a floor button."""
if not (1 <= floor None:
"""Advance simulation by one time step."""
for elevator in self.elevators:
opened = elevator.step()
for floor in opened:
print(f"Elevator {elevator.elevator_id} doors open at floor {floor}")
def status(self) -> list[dict]:
return [
{
'id': e.elevator_id,
'floor': e.current_floor,
'direction': e.direction.value,
'state': e.state.value,
'destinations': sorted(e.destinations),
}
for e in self.elevators
]
Dispatching Algorithm: SCAN (Elevator Algorithm)
The SCAN algorithm is how real elevators work: the elevator travels in one direction, servicing all requests along the way, then reverses at the extreme. This minimizes average wait time and prevents starvation (unlike FCFS).
- FCFS (First Come First Served): Simple but causes backtracking — elevator might go from floor 1 to 10, then back to 3, then to 8.
- SCAN: Go in one direction until no more requests in that direction, then reverse. Serves requests in order of floor number within each direction.
- LOOK: Like SCAN but reverses at the last requested floor (not at the physical extreme). More efficient than SCAN.
Multi-Elevator Dispatching
The cost_to_serve() method is the key for assigning requests. In a real system, the score combines:
- Distance to the requested floor
- Direction alignment: An elevator already going up toward floor 7 is a better choice for a floor-7-up request than an elevator going down
- Load: An elevator with 0 destinations is preferred over one with 10 pending stops
A simple heuristic: cost = |current_floor – request_floor| + (20 if direction_mismatch else 0) + len(destinations) * 2. Assign the request to the elevator with the minimum cost.
Usage Example
system = ElevatorSystem(num_elevators=3, num_floors=20)
# External requests (hallway buttons)
system.request_elevator(floor=5, direction=Direction.UP)
system.request_elevator(floor=12, direction=Direction.DOWN)
# Internal request (inside elevator 0)
system.select_floor(elevator_id=0, floor=15)
# Simulate
for _ in range(20):
system.step()
print(system.status())
Interview Follow-ups
- Emergency mode: Add a priority level to requests. Fire alarm requests override all others and all elevators go to floor 1.
- Maintenance mode: Set
ElevatorState.MAINTENANCEto exclude an elevator from dispatching without removing it from the system. - Weight sensor: Elevator tracks current load; if at capacity (e.g., 80% full), skip external requests but still serve internal requests (passengers inside).
- Why SCAN over FCFS? SCAN reduces average wait time and prevents starvation. FCFS can cause an elevator to thrash between floors 1 and 20 on every request.
🏢 Asked at: Atlassian Interview Guide
🏢 Asked at: Shopify Interview Guide
🏢 Asked at: Apple Interview Guide 2026: iOS Systems, Hardware-Software Integration, and iCloud Architecture
🏢 Asked at: Uber Interview Guide 2026: Dispatch Systems, Geospatial Algorithms, and Marketplace Engineering
🏢 Asked at: Airbnb Interview Guide 2026: Search Systems, Trust and Safety, and Full-Stack Engineering
Asked at: LinkedIn Interview Guide
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering