Requirements


Functional Requirements:



  1. Spot reservation — Users can search and reserve available spots by vehicle type, time window, and location.
  2. Payment processing — Pre-payment at reservation time; refund/credit logic for early exits and no-shows.
  3. Vehicle entry/parking — Gate check-in via QR code, license plate recognition (LPR), or reservation ID.
  4. Early departure — System logs actual exit time and triggers partial refund processing.
  5. Gate check-in/out — Physical barrier integration; entry and exit events log timestamps.
  6. No-show handling — Spots are automatically released after a grace period (e.g., 15 minutes post-start time) and the user is charged a no-show fee.



Non-Functional Requirements:


  • Availability: 99.9% uptime — gates must never get stuck due to a backend outage (local fallback cache at gate hardware).
  • Latency: Gate open/close decisions under 500ms; reservation search under 200ms.
  • Scalability: Handle thousands of concurrent reservations across multiple lots.
  • Consistency: Spot allocation must be strictly consistent — no double-booking (distributed lock or optimistic locking with DB transactions).
  • Security: PCI-DSS compliance for payments; encrypted license plate data at rest.
  • Observability: Real-time occupancy dashboards; alerting on gate failures or payment service degradation.


API Design

SPOT DISCOVERY


GET /spots/available

?lot_id, vehicle_type, start_time, end_time — returns available spots with pricing


GET /spots/{spot_id}

Spot details, current status (available/reserved/occupied)


RESERVATIONS

POST /reservations

Body: {spot_id, user_id, vehicle_id, start_time, end_time} — creates reservation, locks spot


GET /reservations/{reservation_id}

Fetch reservation details and current state


PUT /reservations/{reservation_id}/cancel

Cancel before start_time; triggers refund eligibility check


PAYMENTS

POST /payments

Body: {reservation_id, payment_method_token} — charges user, returns payment_id


POST /payments/{payment_id}/refund

Body: {reason, amount} — partial/full refund on early exit or no-show


GATE CONTROL

POST /gate/check-in

Body: {reservation_id | license_plate | qr_code, gate_id} — validates entry, opens gate


POST /gate/check-out

Body: {reservation_id | license_plate, gate_id} — logs exit time, triggers billing reconciliation


VEHICLES & USERS

POST /users/{user_id}/vehicles

Register vehicle (plate, type: compact/SUV/motorcycle/EV)


GET /users/{user_id}/reservations

Reservation history with statuses



High-Level Design

The system is built as a set of loosely coupled microservices sitting behind an API Gateway that handles authentication, rate limiting, and routing. The core services — Reservation, Payment, Spot Management, Gate, and Notification — each own their own database, communicating asynchronously via a Kafka event bus for non-critical flows and synchronously via direct HTTP/gRPC calls where latency matters (gate validation, payment at checkout). Gate hardware runs a lightweight edge agent with a local cache so physical barriers never depend on backend availability. A Redis layer sits in front of spot availability to serve high-read-volume queries without hitting the database.



Detailed Component Design

Spot Management Service maintains real-time availability in Redis as a sorted set keyed by lot:floor:spot_id with values encoding the occupied time ranges. This allows O(log n) range queries to find free windows. The canonical source of truth is PostgreSQL; Redis is a write-through cache.

No-show handler is a scheduled job (cron every 5 minutes) that queries all reservations with status=CONFIRMED and start_time + grace_period < NOW(). For each match it fires a no_show.triggered Kafka event, which the Reservation Service consumes to update the status and the Payment Service consumes to charge the no-show fee (typically a percentage of the booking). The spot is released back into availability atomically.

Early departure — on gate/check-out, the Gate Service logs the actual exit timestamp. It then computes the unused duration and emits a checkout.early event. The Payment Service calculates the refund amount based on the lot's early-exit policy (e.g. prorated minus a minimum fee) and issues a partial refund via the payment provider's API.

Gate hardware runs a lightweight edge agent that syncs a local SQLite snapshot of all upcoming reservations (next 24h) every few minutes via the Gate Service. This ensures the gate can validate and open in under 200ms even during a network partition. All events are buffered locally and flushed when connectivity resumes.

Vehicle type accommodation — spots are tagged with types: compact, standard, SUV, motorcycle, and EV (which also carry a charger flag). The search API filters availability by vehicle type and the frontend surfaces only compatible spots. EV spots also expose charger status as a live field pulled from the charger management system.


Horizontal scaling

Each microservice is stateless and can be scaled independently behind a load balancer — you add Payment Service instances during peak hours without touching the Gate Service. Kafka partitions are the unit of parallelism on the consumer side; scaling a consumer group is just adding more instances, and Kafka rebalances partition ownership automatically. The main stateful bottlenecks are Redis and PostgreSQL — Redis scales horizontally via clustering and consistent hashing across nodes, while PostgreSQL scales reads through read replicas and handles write contention on hot spots (like a popular lot at peak time) through partition-level distributed locks rather than row-level locks on a single record.