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.





Markdown supported