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
  1. 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

  1. receive plate
  2. find matching confirmed reservation for current time window
  3. validate grace period
  4. if exact spot not assigned, request spot from allocation engine
  5. create parking session
  6. send open command to gate

Exit logic

  1. find active session by plate
  2. calculate final charge/refund/penalty
  3. verify payment state or settle delta
  4. close session
  5. 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:

  1. user requests booking
  2. create reservation in PAYMENT_PENDING
  3. create temporary hold on inventory
  4. initiate payment
  5. payment callback arrives
  6. confirm reservation and convert hold to confirmed booking
  7. 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:

  1. exit event closes session
  2. compute actual usage
  3. compare against reservation payment
  4. issue refund/credit if policy allows
  5. release remaining reserved capacity

No-show

Need a configurable grace period, e.g. 15 minutes.

Flow:

  1. scheduler scans reservations whose start time + grace < now
  2. if not checked in:
    • mark NO_SHOW
    • free inventory
    • apply penalty/refund policy
    • notify user

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