System design · LLD design

Amazon Locker System

Functional Req

1.Single locker system

1.There can be multiple size locker

2.Package can be assigned of same size locker , and if not present then try for bigger locker (size matching logic)
3.no locker empty reject the drop with a clear reason (e.g., “no locker available”)
4 During drop-off assign a locker and generate a code
5.System generates a unique pickup code when the courier drops
6.During pickup, Customer enters a code and system verify the code matches assigned code

7.Allow max 3 retry attempts for code entry , -> will send a message (“flagged and locked for staff intervention )
8. If passed, Customer pick up the order , and package will be released from the locker
9.Pickup deadline for 3 days , after that remove from the locker - and locker will be again available for new packages

Non-functional

1.Extensible - Locker assignment strategy can be swapple with other logic

2. Scalable - handle more lockers
3.concurrency - handle concurrency if two courier try to drop off packages at the same instant and both get assigned the same locker?
(but to be honest i don’t think in real world its possible ? how can be two courier assigned at once ?
4.code uniqueness - all code generate will be unique - handle by generating random digits

Functional Requirements

  1. Support a single locker station with multiple locker sizes.
  2. On drop-off (given package details — ID, size, customer/order reference), assign a locker of matching size, or next-larger if exact size unavailable.
  3. If no suitable locker is available, reject the drop-off with a clear reason.
  4. Generate a unique pickup code upon successful drop-off.
  5. On pickup, validate the entered code against the package’s assigned code.
  6. Allow a maximum of 3 failed code-entry attempts; on the 3rd failure, lock the package and flag it for staff intervention.
  7. On successful validation, release the package and free the locker.
  8. Enforce a 3-day pickup deadline; if unmet, remove the package and make the locker available again.

Non-Functional Requirements

  1. Extensibility — locker-assignment strategy should be swappable without modifying core logic.
  2. Scalability — support adding more lockers/stations without restructuring core logic.
  3. Concurrency — the system must safely handle concurrent drop-off/pickup requests (e.g., from multiple kiosks or retried API calls) without double-assigning a locker or double-releasing a package.
  4. Code uniqueness — no two active packages should share a pickup code at the same time, including under concurrent code generation.

Entities

1.LockerSize - SMALL, MEDIUM , LARGE && LOCKERSTATE - AVAILABLE AND OCCUPIED

2. Package -

-packageID

-LockerSize size

-pickupCode

-expiryTime

-numberOfRety - 0 default

new Package(size, pickupcode) -> calc packageID uniqueid and expirytime 3 days from now()

+increseNumberOfRetry() - numberofrety++;

3.Locker

-LockerSize size

-State lockerstatus

-Package currentPackage

+boolean tryFit(package) - handle if free assign the package to currentpackage and status to OCCUPIED and return true else false

+removePackage() - remove the package + status to AVAILABLE

4.LockerStation

-List<Lockers> lockers

+addLocker()

5.LockerAssignmentStrategy

Find the locker for assigning the package
LockerAssignmentStrategy - interface

sizingMatchingStrategy - implement LockerAssignmentStrategy
+ findLocker(package) - synchronous call

-return all with this size and creator then in order from small size

and Call tryFit(package) in Locker

And if no empty left - return with a message “no locker empty left, try after sometime”

6.LockerSerivce

-assignmentStrategy

-list<lockers>

-Set<String> activeCode = ConcurrentHashMap.newKeySet();
// drop a package

+dropPackage(size , packageid)

Lock {
+generateUniqueCode() -> assign to package and add in activeCode
}

+assignLocker(package) ->

//pickup

+pickPackage(lockerID)

-getpackage detail from the lockerid

-input: customer code

-isValideCode() - code matches or not && canPickupPackage() - package expired & numbrofretry < 3

lock{
remove from active code
}

locker.removePackage()

+package.increseNumberOfRetry()

// expiry

+checkIFPackageExpiried()

Lock {
Check all locker which are occupied and check the package in it
And package with expirytime < now()
locker.removePackage() & remove from active code
}

7.LockerStation

// assign which strategy to use
//add lockers in locker station
//call locker service for
  • dropPackage
  • pickupPAckage
  • checkIfPAckageExpiried() - this in some intervals