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
Block diagram for HLD is on the right side. Below services/components play major role here:
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.
1.High Traffic / Low Latency
Availability Search:
Client -> API Gateway -> Availability Service -> Redis/cache
lot_id + vehicle_type + time_bucket -> available_count
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:
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:
High-volume availability queries -> cache
Actual booking -> DB transaction with concurrency control
Non-critical work -> async queue
Add protection:
For very high scale, partition by parking_lot_id because reservations for different lots do not conflict.
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.
Proposed status flow:
Status flow:
AVAILABLE -> RESERVED(->EXPIRED / NO_SHOW) -> OCCUPIED(OVERSTAY / EARLY_EXIT) -> RELEASE_PENDING -> AVAILABLE
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.
-- payment gateway failure, spot still not released
-- Reservation service fails to pick the Spotbooked event to notify spot details to user.
-- ALB to evenly distribute load.
-- multi-AZ deployment
-- Message Queue
-- Monitoring, Containerization, CI/CD automation, logging, monitoring
-- Price rules caching
Trade-offs: