0) Problem Restatement
Design Amazon Locker: self-service stations with many compartments of different sizes (small, medium, large). When a customer chooses a locker for delivery, the system assigns a compartment that fits the package. The courier deposits the package, and the customer gets a one-time pickup code valid for a few days (e.g., 3). If nobody picks it up, the package is returned. Amazon asked it both as class design (one station) and as a distributed system (many stations, multi-size allocation).
1) Requirements
- Locker stations with compartments of sizes S, M, L (and availability).
- Assign a compartment that fits the package (smallest size that fits).
- The courier deposits → the compartment is marked occupied → the customer gets a code (SMS or app).
- The customer enters the code → the door opens → the compartment is freed.
- Codes expire. Expired packages go back to the courier for return.
- Handle two couriers or requests at once without double-assigning a compartment.
2) Class Design
Architecture Diagram
classDiagram
class LockerStation {
+String stationId
+Location location
+List compartments
+findCompartment(size) Compartment
+deposit(packageId, compartmentId) PickupCode
+pickup(code) Compartment
}
class Compartment {
+String id
+Size size
+State state
+String packageId
}
class Package {
+String id
+Size size
+String customerId
}
class PickupCode {
+String codeHash
+String compartmentId
+DateTime expiresAt
+boolean used
}
class LockerService {
+reserve(orderId, stationId, size) Reservation
+confirmDeposit(reservationId) PickupCode
+redeem(stationId, code) Compartment
+expireOld() void
}
LockerStation "1" --> "*" Compartment
LockerService --> LockerStation
Compartment --> Package
PickupCode --> CompartmentFREE → RESERVED → OCCUPIED → FREE (plus OUT_OF_SERVICE).
3) Key Logic
3.1 Choosing a compartment (best fit)
Pick the smallest free size that fits (S before M before L), so big compartments stay available for big packages. Only if the fitting size is full, use a bigger one.
SIZES = ["S", "M", "L"]
def find_compartment(station, pkg_size):
for size in SIZES[SIZES.index(pkg_size):]: # same size first, then bigger
for c in station.compartments:
if c.size == size and c.state == "FREE":
return c
return None # station full for this size
(In a real system, keep a free list per size so this is O(1).)
3.2 Concurrency
Two deliveries could pick the same free compartment. Make the state change atomic: UPDATE compartments SET state='RESERVED', reservation_id=? WHERE id=? AND state='FREE'. If 0 rows are updated, someone else took it, so pick another. In a single process, use a lock per station (or per size free list).
3.3 Codes
- Generate a random 6–8 digit code, and store only its hash with the compartment and expiry.
- Codes are single-use. After too many wrong attempts, lock the keypad for a while (stops guessing).
- On pickup, check hash, expiry and
used = false, then open the door, and mark the compartmentFREEand the codeused.
4) Backend for Many Stations
Architecture Diagram
flowchart LR
CHK["Checkout - choose locker"] --> LS["Locker Service"]
LS --> DB[("Stations, compartments, reservations")]
CR["Courier app"] --> LS
ST["Locker station controller"] <-->|"sync, commands"| LS
LS --> N["Notifications - SMS, app"]
JOB["Expiry job"] --> LS- Reserve at order time: when the customer picks a locker at checkout, reserve a compartment size for the expected delivery date. This avoids a courier arriving to a full station.
- Station controllers can lose connectivity. They cache active codes (hashed) locally so pickups still work offline, and sync events (deposits, pickups) when back online.
- Expiry job: every hour, find
OCCUPIEDcompartments whose code expired. Notify the customer, then create a return task for the courier and free the compartment after removal.
5) Edge Cases
- Package doesn't fit the assigned compartment: the courier requests a re-assignment to a bigger one on the spot.
- Door fails to open / compartment broken: mark it
OUT_OF_SERVICE, move the package or reassign, and alert operations. - Customer changes delivery location: release the reservation.
6) Wrap-Up
Model a station with sized compartments that move through FREE → RESERVED → OCCUPIED → FREE. Assign the smallest free compartment that fits, with an atomic conditional update so two couriers never get the same one. Issue hashed, single-use, expiring pickup codes with attempt limits, reserve capacity at checkout, let station controllers work offline with cached codes, and run an expiry job to return unclaimed packages.