Requirements
Functional Requirements:
- Allow reservation of a parking spot.
- Process payment for the reservation.
- Enable parking of a car in the reserved spot.
- Support early departure before reservation time expires.
- Gate check-in/out.
- Handle no show.
Non-Functional Requirements:
- List the key non-functional requirements (eg low latency, scalability, reliability, etc.)...
Low latency
- gate validation must be fast, ideally <200ms to 500ms
- reservation lookup and availability check should also be low latency
High availability
- gate entry/exit must keep working even during partial backend failures
- system should degrade gracefully
Strong consistency where needed
- inventory allocation must avoid overbooking
- payment and reservation state transitions must be correct
Scalability
- should support many parking lots and peak traffic windows
- read-heavy workload for availability
- bursty write workload around commuting hours/events
Reliability
- no lost payments
- no incorrect gate entries due to race conditions
- idempotent APIs for booking/payment callbacks/gate events
Security
- protect payment data
- secure user identity and reservation data
- prevent fraud at gates
Observability
- trace gate failures, payment issues, no-show rate, allocation failures
Extensibility
- easy to add new lot types, vehicle categories, pricing models, sensors
API Design
Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
I’ll separate read path and write path.
Read APIs
Search availability
GET /lots/{lotId}/availability?startTime=...&endTime=...&vehicleType=SUV
Response:
{
"lotId": "lot-123",
"available": true,
"spotTypes": [
{
"type": "SUV",
"count": 21,
"priceEstimate": 18.50
}
]
}
Get lot details
GET /lots/{lotId}
Get reservation
GET /reservations/{reservationId}
Get user reservations
GET /users/{userId}/reservations
Write APIs
Create reservation
POST /reservations
Request:
{
"userId": "u1",
"vehicleId": "v1",
"lotId": "lot-123",
"vehicleType": "SUV",
"startTime": "2026-04-14T09:00:00Z",
"endTime": "2026-04-14T12:00:00Z",
"spotPreference": "EV"
}
Response:
{
"reservationId": "r1",
"status": "PAYMENT_PENDING",
"amount": 18.50,
"paymentToken": "pay_abc"
}
Confirm payment / payment callback
POST /payments/callback
or
POST /reservations/{reservationId}/confirm-payment
Cancel reservation
POST /reservations/{reservationId}/cancel
Gate entry check-in
POST /gates/check-in
Request:
{
"lotId": "lot-123",
"gateId": "entry-1",
"plate": "ABC1234",
"qrCode": "optional",
"timestamp": "2026-04-14T08:58:12Z"
}
Response:
{
"allowed": true,
"reservationId": "r1",
"assignedSpot": {
"spotId": "B2-104",
"floor": "B2"
},
"message": "Welcome"
}
Gate exit check-out
POST /gates/check-out
Request:
{
"lotId": "lot-123",
"gateId": "exit-2",
"plate": "ABC1234",
"timestamp": "2026-04-14T10:40:00Z"
}
Response:
{
"allowed": true,
"sessionId": "s1",
"finalCharge": 0,
"refund": 3.00,
"message": "Thank you"
}
Mark no-show
Usually internal, event-driven:
POST /internal/reservations/{reservationId}/mark-no-show
High-Level Design
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
Main components:
- Client Appsmobile app
- web app
- operator dashboard
- API Gatewayauth, rate limiting, routing
- Reservation Servicesearch availability
- create/update reservations
- manage state machine
- Inventory / Spot Allocation Servicetracks spot inventory
- allocates spots
- handles temporary locks
- Payment Servicepayment initiation
- payment confirmation/refund
- integrates with external PSP
- Gate Control Serviceprocesses gate entry/exit
- talks to LPR cameras / gate controllers
- very latency-sensitive
- Parking Session Servicemanages active parked sessions
- check-in/check-out
- early departure logic
- No-show / Expiration Workerbackground jobs
- releases held spots
- applies penalties
- Notification Serviceemail/SMS/push
- Datastores
- transactional DB
- cache
- event bus
- analytics DB optionally
Detailed Component Design
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
10. Detailed component design
I’d deep dive into these 3:
- Inventory / Spot Allocation Service
- Gate Control Service
- Reservation + Payment orchestration
10.1 Inventory / Spot Allocation Service
This is the hardest core logic.
Responsibilities
- maintain spot inventory per lot/time window
- prevent double-booking
- support spot type constraints
- optionally assign exact spot up front or at entry time
Design choice: exact spot vs spot class reservation
There are two models:
Option A: Reserve exact spot at booking time
Pros:
- simple user experience
- deterministic
Cons:
- lower utilization
- more fragmentation
- difficult if users leave early or no-show
Option B: Reserve a spot class/capacity bucket, assign exact spot at entry
Example: reserve “SUV-compatible on floor B2”, assign actual spot when user arrives.
Pros:
- better utilization
- easier rebalancing
- easier handling of no-shows and early exits
Cons:
- more complex gate-time logic
- slightly less user certainty
Best practical choice:
Use spot class reservation, then assign exact spot at check-in or shortly before arrival.
For premium/VIP/accessibility cases, exact spot reservation can still be supported.
Inventory representation
At low scale, you can simply query DB rows for overlapping reservations.
At higher scale, better to maintain:
- spot metadata in SQL
- availability counters / interval indexes in Redis or specialized allocation layer
Core allocation rule
A spot can be assigned only if:
- vehicle type fits
- spot type fits
- no overlapping confirmed reservation or active session
- spot not under maintenance
Overlap condition
Two reservations overlap if:
new.start < existing.end AND new.end > existing.start
Preventing double booking
This is crucial.
Possible approaches:
Approach 1: DB transaction + row locking
- lock candidate spot rows using
SELECT ... FOR UPDATE - verify no overlap
- insert reservation
- commit
Pros:
- strong correctness
- simple at moderate scale
Cons:
- can become bottleneck for huge scale
Approach 2: Redis distributed lock + DB transaction
- acquire temporary lock on candidate inventory bucket
- perform DB transaction
- release lock
Pros:
- lower contention at app layer
- faster for hot lots
Cons:
- more complexity
- must handle lock expiry correctly
Approach 3: Pre-aggregated capacity buckets
Instead of exact spot selection during booking:
- maintain capacity by
(lot, spotType, timeSlot) - decrement counters on booking
- assign exact spot later
Pros:
- scales much better
- faster availability queries
Cons:
- less precise
- needs reconciliation with real spot-level state
Interview recommendation
Start with:
- SQL transactional allocation
- Then mention evolution:
- move to bucketed inventory with Redis caching
- exact spot assigned at check-in
That is a strong, pragmatic answer.
Data structures
- SQL tables for canonical reservations/sessions/spots
- Redis:
- hot availability counts
- temporary booking holds
- gate lookup cache by plate -> reservation/session
- optional interval tree / time-slot buckets for fast overlap computation if scale grows
Scaling strategy
Shard primarily by:
lotId
Why?
- reservations and gates are mostly lot-local
- avoids cross-lot contention
For large deployments:
- one inventory partition per lot/region
- cache popular lots heavily
10.2 Gate Control Service
This is operationally critical.
Responsibilities
- receive entry/exit events from hardware
- identify vehicle
- authorize or deny access
- open gate
- create check-in / check-out events
- operate under intermittent connectivity
Inputs
- LPR camera plate read
- QR code
- kiosk/manual operator override
Entry logic
- receive plate
- find matching confirmed reservation for current time window
- validate grace period
- if exact spot not assigned, request spot from allocation engine
- create parking session
- send open command to gate
Exit logic
- find active session by plate
- calculate final charge/refund/penalty
- verify payment state or settle delta
- close session
- open exit gate
Latency and resilience
This service must be very fast.
So I would keep:
- local cache / Redis cache for plate -> active reservation/session
- idempotent gate event processing
- offline fallback rules
Offline fallback
If central backend is temporarily unavailable:
- gate controller can use a short-lived local cache of recently synced valid reservations
- operator override can be used
- events are queued and reconciled later
This is a strong real-world point.
Fraud / error cases
- misread plate
- user changes vehicle
- fake QR
- car enters without reservation
- duplicate entry events
Solutions:
- support QR/manual confirmation fallback
- idempotency key on gate events
- camera confidence threshold
- operator console for exception handling
Scale
Gate traffic is not internet-scale, but spikes can happen at event venues.
Example:
- 50 lots
- 20 gates each
- 1 event causes 2000 cars in a short window
Still manageable with:
- stateless Gate Control Service
- Redis hot cache
- lot-based partitioning
10.3 Reservation + Payment orchestration
This is where distributed workflow correctness matters.
Why it is tricky
Reservation and payment involve multiple systems:
- our backend
- inventory
- payment provider
We need to avoid:
- paid but no reservation
- reservation created but payment failed
- double callback processing
Best approach: Saga / state machine
Flow:
- user requests booking
- create reservation in
PAYMENT_PENDING - create temporary hold on inventory
- initiate payment
- payment callback arrives
- confirm reservation and convert hold to confirmed booking
- if payment fails or times out, release hold
This is effectively a mini saga.
Why not one global distributed transaction?
Because PSP is external and distributed 2PC is impractical.
Idempotency
Need it for:
- create reservation
- payment callback
- gate events
- refunds
For example, payment callback may arrive twice.
So we store:
externalPaymentRef- processed status
- idempotency key
Early departure
Business rule options:
Option 1: no refund
simple, good for operators
Option 2: prorated refund
better UX, more complex
Option 3: credit for future use
great compromise
I would say:
- support configurable policy per lot/operator
Flow:
- exit event closes session
- compute actual usage
- compare against reservation payment
- issue refund/credit if policy allows
- release remaining reserved capacity
No-show
Need a configurable grace period, e.g. 15 minutes.
Flow:
- scheduler scans reservations whose start time + grace < now
- if not checked in:
- mark
NO_SHOW - free inventory
- apply penalty/refund policy
- notify user
- mark
This can be implemented using:
- delayed jobs in queue
- periodic sweeper job
I prefer delayed jobs because they are more targeted, but a periodic sweeper is simpler as backup.
11. Database design
Transactional SQL DB
Use PostgreSQL/MySQL for source of truth.
Why SQL?
- reservations/payments/sessions are transactional
- need consistency
- rich querying for overlaps/auditing/reporting
Example tables
- users
- vehicles
- parking_lots
- parking_spots
- reservations
- sessions
- payments
- gate_events
- no_show_events
Important indexes
- reservations
(lot_id, start_time, end_time, status) - reservations
(vehicle_id, start_time) - vehicles
(plate) - sessions
(plate, status) - spots
(lot_id, type, status)
Redis
Use for:
- hot availability cache
- temporary inventory holds
- plate-to-reservation lookup cache
- gate-side fast authorization path
Event bus
Kafka / RabbitMQ / SQS-like queue for:
- payment callbacks
- no-show jobs
- notifications
- analytics/audit streams
12. Capacity estimation
For interview purposes, keep it simple.
Example:
- 1,000 parking lots
- each lot has 500 spots
- average 5 reservation/session events per spot per day
That gives:
- 500,000 spots total
- 2.5M reservation/session events/day
This is not massive for a modern SQL + cache + queue architecture.
Peak traffic is the real concern:
- morning commute
- event venue opening/closing
- holiday traffic
So design for:
- burst handling
- cached reads
- async side effects
- low-latency gate path