My Solution for Design an Efficient Parking Lot System with score 85%
by echo5413
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:
- No two vehicles to be reserved to same spot.
- Reservation system to be strong consistent.
- System to be highly available
- System to be scalable to handle heavy traffic.
- low latency, reliability
API Design
Gate check-in API:
POST /gates/{gateId}/check-in
{
"reservationId": "...",
"licensePlate": "...",
"timestamp": "..."
}
and then,
RESERVED -> OCCUPIED
gate opens
Gate check-out:
POST /gates/{gateId}/check-out
{
"reservationId": "...",
"licensePlate": "...",
"timestamp": "..."
}
then,
OCCUPIED -> COMPLETED
spot -> AVAILABLE
payment captured
gate opens
prposed APIs:
POST /reservations
GET /reservations/{reservationId}
POST /reservations/{reservationId}/cancel
POST /reservations/{reservationId}/check-in
POST /reservations/{reservationId}/check-out
POST /payments/authorize
POST /payments/capture
GET /parking-lots/{lotId}/availability
GET /pricing/quote
Status flow:
AVAILABLE -> RESERVED(->EXPIRED / NO_SHOW) -> OCCUPIED(OVERSTAY / EARLY_EXIT) -> RELEASE_PENDING -> AVAILABLE
High-Level Design
Block diagram for HLD is on the right side. Below services/components play major role here:
- Reservation module
- Spot allocation module
- Pricing module
- Gate access module
- Payment module
Below is the HLD, to maintain stron consistency, we'll have same DB for reservation and Spot allocation service/module.
API Gateway
-> Reservation Service
-> Reservation DB
-> Spot Inventory table
-> Outbox table
-> Payment Service
-> Payment Provider
-> Payment DB
-> Gate Service
-> Entry/Exit devices
-> Reservation Service
-> Notification Service
<- Events
Exit (Checkout) process/flow:
1. Gate exit request received.
2. Validate active reservation and vehicle.
3. Calculate actual parking duration.
4. Calculate refund/additional charge if applicable.
5. Capture/adjust payment.
6. Mark reservation COMPLETED.
7. Mark spot AVAILABLE.
8. Open gate.
If payment fails at exit, business choice matters:
-- send to manual assistance
or depends on the business choice.
-- kafka message/event queue Queue to notify users about check-in/checkout.
-- vehicle arrived details (vehicle number, type, entry time etc) will be stored in reservation db via reservation service.
- rate limit public APIs like search/availability/reservation creation
- protect payment APIs from abuse
- use backpressure and queueing for non-critical async work
- gate APIs should be highly available and low-latency, with local fallback if central service is temporarily down
1.High Traffic / Low Latency
- read/write strategy
Availability Search:
Client -> API Gateway -> Availability Service -> Redis/cache
- Use cached aggregate availability for fast reads:
lot_id + vehicle_type + time_bucket -> available_count
- Availability lookup can be eventually consistent and served from cache, but reservation confirmation must be strongly consistent.
This keeps common read paths low-latency while protecting correctness during booking.
2.Failure Handling Strategy
DB changes -> outbox event -> async consumer -> retry/DLQ
3.For service failure:
- Reservation service failure: DB transaction rolls back, no spot assigned.
- Outbox publisher failure: event remains in outbox and is retried.
- Notification failure: no impact on reservation correctness.
- Payment service failure: reservation can stay in PAYMENT_PENDING for a short TTL.
- Spot allocation failure: return “no spot available” or retry with another spot.
- Gate service failure: local gate controller can validate recently synced reservations for limited offline operation.
- Use an Idempotency-Key to avoid duplicate booking, duplicate payment, or duplicate gate events.
3.Overlapping Reservations:
in SQL design, we can use transaction + indexed overlap query + lock
1. Find candidate spots compatible with vehicle type/accessibility.
2. Exclude spots with overlapping active reservations.
3. Lock selected spot or reservation-window row.
4. Insert reservation window.
5. Commit.
4.Surge in reservations:
- For sudden spikes, separate "search" from commit."
High-volume availability queries -> cache
Actual booking -> DB transaction with concurrency control
Non-critical work -> async queue
Add protection:
- Token bucket rate limiting on reservation creation/search APIs.
- Per-user/per-IP throttling to prevent abuse.
- Queue-based smoothing if one lot receives extreme demand.
- Short-lived spot holds with TTL, e.g. 2-5 minutes.
- Optimistic retry with another spot if selected spot is taken.
- Bulkhead isolation so payment/notification issues do not take down booking.
- Circuit breaker around payment provider.
- DLQ for failed async events.
For very high scale, partition by parking_lot_id because reservations for different lots do not conflict.
Detailed Component Design
Reservation Flow:
1. Client requests reservation with vehicle type, lot, desired time window.
2. Reservation service validates request.
3. In one DB transaction:
- find compatible AVAILABLE spot
- lock candidate row / use conditional update
- create reservation with RESERVED status
- mark spot RESERVED for time window
- write outbox event ReservationCreated
4. Return reservationId and spot details.
5. Async notification is sent.
6. Payment authorization may happen before or after reservation depending on business policy.
- notification, payment capture, analytics, and user communication can be async commuicaation by using kafka message broker.
Proposed status flow:
Status flow:
AVAILABLE -> RESERVED(->EXPIRED / NO_SHOW) -> OCCUPIED(OVERSTAY / EARLY_EXIT) -> RELEASE_PENDING -> AVAILABLE
- idempotency keys on reservation, payment, gate events
- request validation
- correlation IDs
- clear error responses
- authN/authZ assumptions
For the “no two vehicles reserve same spot” requirement
pessimistic locking can be used as shown below:
SELECT ... FOR UPDATE SKIP LOCKED
payment service fetches price rules from cache, and calculate final price based on total time, vehicle type and flat rate.
- tradeoffs:
-- payment gateway failure, spot still not released
-- Reservation service fails to pick the Spotbooked event to notify spot details to user.
- Use of resilience (circuitbreaker, retries for payment process)
- Scalability: enable auto-scaling of containers on AWS for web tier. DB tier auto-scaling for horizontal scaling, DB replication.
- High Availability:
-- ALB to evenly distribute load.
-- multi-AZ deployment
-- Message Queue
-- Monitoring, Containerization, CI/CD automation, logging, monitoring
-- Price rules caching
Trade-offs:
- Availability lookup latency: cache lot-level availability counts.
- Reservation correctness: DB constraints + row locks/conditional updates.
- Idempotency: reservation/payment/gate APIs.
- Recovery: outbox relay retries, dead-letter queue.
- Observability: reservation lifecycle tracing.
- Security: license plate data encryption/masking, PCI considerations for payments.
- Accessibility: reserve accessible spots only for eligible users if required.
- Safety: manual override for gates.