System requirements


Functional:

FR1: User can reserve a parking spot

FR2: User pays for the reservation

FR3: User can park a car on the parking spot

FR4: User can leave before the reservation time expires

FR5: System handles no-shows by charging for the first 24 hours


Non-Functional:

NFR1: Scalability - Support an international company with 1000s of parking lots across nations

NFR2: High Availability - System must remain operational with minimal downtime

NFR3: Consistency - No double-booking; once reserved, a spot must be guaranteed available

NFR4: Performance - Reservation operations should complete within reasonable time

NFR5: Security - Secure payment processing and user data protection



Capacity estimation

Assumptions

  • Operations in 10 countries
  • 100 parking lots per country on average (1,000 total)
  • 200 parking spots per lot on average
  • 200 reservation requests per parking lot per day
  • 80% short-term parking (4 hours average)
  • 20% long-term parking (5 days average)

Calculations

  • Daily Reservation Requests: 1,000 lots × 200 requests = 200,000 requests/day
  • Request Rate: 200,000 ÷ 86,400 seconds ≈ 2.3 requests/second (with peak times likely 5-10× higher)

Storage Requirements

  • Each reservation record ≈ 128 bytes:
    • Reservation ID (8 bytes)
    • User ID (8 bytes)
    • Vehicle type (1 byte)
    • Start/end times (16 bytes)
    • Additional metadata (~95 bytes)
  • Daily Storage: 200,000 × 128 bytes = 25.6 MB/day
  • Two-Year Storage: 25.6 MB × 365 × 2 × 1.5 (growth factor) = ~28 GB

The storage requirements are well within the capabilities of relational databases, which will help satisfy our consistency requirements (NFR3).





Service Design

The system will be decomposed into the following core services:

ServicePrimary ResponsibilityFunctional RequirementsNon-Functional Requirements
Reservation ServiceManages parking spot reservations, availability checks, and reservation lifecycleFR1, FR5NFR1, NFR3, NFR4
Payment ServiceHandles payment processing and integration with third-party payment providersFR2NFR2, NFR5
Transaction ServiceManages vehicle entry/exit operations and updates reservation statusFR3, FR4NFR2, NFR3
Transaction Monitor ServiceDetects no-shows and handles automatic reservation status updatesFR5NFR2, NFR3
User ServiceManages user accounts, profiles, and authenticationSupports FR1-FR5NFR5
Notification ServiceSends confirmations, reminders, and alerts to usersSupports FR1-FR5NFR2
Analytics ServiceCollects and processes usage data for business intelligenceSupports system optimizationNFR1, NFR4

API design

User-Facing APIs

CheckCapacity: Check parking lot capacity

コピー GET /api/v1/lots/{lot_id}/capacity Parameters: - vehicle_type: Type of vehicle (car, motorcycle, etc.), string, required - start_date_time: ISO8601 format, required - end_date_time: ISO8601 format, required Returns: - available_spots: Number of available spots, integer - price: Estimated price for the duration, decimal - status_codes: 200 OK, 400 Bad Request, 404 Lot Not Found

ReserveSpot: Create a parking spot reservation

コピー POST /api/v1/reservations Body: - user_id: User identifier, string, required - lot_id: Parking lot identifier, string, required - vehicle_type: Type of vehicle, string, required - start_date_time: ISO8601 format, required - end_date_time: ISO8601 format, required Returns: - reservation_id: Unique reservation identifier, string - price: Total price for the reservation, decimal - payment_url: URL to complete payment, string - status_codes: 201 Created, 400 Bad Request, 409 Conflict (if lot is full)

CompleteReservation: Finalize reservation after payment

コピー POST /api/v1/reservations/{reservation_id}/complete Body: - user_id: User identifier, string, required - payment_token: Payment confirmation token, string, required Returns: - status: Reservation status, string - confirmation_code: Code for entry to lot, string - status_codes: 200 OK, 400 Bad Request, 404 Not Found, 402 Payment Required

Parking Lot Operations APIs

VehicleArrived: Record vehicle check-in

コピー POST /api/v1/transactions/arrival Body: - reservation_id: Reservation identifier, string, required - date_time: Arrival timestamp, ISO8601 format, required Returns: - transaction_id: Unique transaction identifier, string - status: Updated reservation status, string - status_codes: 200 OK, 404 Not Found

VehicleLeft: Record vehicle check-out

コピー POST /api/v1/transactions/departure Body: - reservation_id: Reservation identifier, string, required - date_time: Departure timestamp, ISO8601 format, required Returns: - transaction_id: Unique transaction identifier, string - status: Updated reservation status, string - final_charge: Final amount charged (if different from reservation), decimal - status_codes: 200 OK, 404 Not Found

Admin APIs

GetLotOccupancy: Get current occupancy for a lot

コピー GET /api/v1/admin/lots/{lot_id}/occupancy Parameters: - date: Optional date for historical data, ISO8601 format Returns: - capacity: Total lot capacity, integer - occupied_spots: Number of occupied spots, integer - reservations: List of active reservations - status_codes: 200 OK, 403 Forbidden, 404 Not Found




Database design

erDiagram

User ||--o{ Reservation : makes

User ||--o{ Vehicle : owns

Reservation ||--|| Spot : reserves

Reservation ||--o{ Transaction : generates

Reservation ||--o{ Payment : has

Spot }|--|| ParkingLot : belongs_to

ParkingLot ||--o{ ContactInfo : has

User ||--o{ ContactInfo : has


User {

string user_id PK

string name

string email

string phone

datetime created_at

}

Vehicle {

string vehicle_id PK

string user_id FK

string license_plate

string vehicle_type

datetime created_at

}

Reservation {

string reservation_id PK

string user_id FK

string spot_id FK

string vehicle_id FK

datetime start_time

datetime end_time

string payment_status

string completion_status

datetime created_at

}

Spot {

string spot_id PK

string lot_id FK

string spot_type

boolean is_active

}

ParkingLot {

string lot_id PK

string name

string address

int capacity

string lot_type

boolean is_active

}

Transaction {

string transaction_id PK

string reservation_id FK

datetime check_in_time

datetime check_out_time

decimal final_charge

}

Payment {

string payment_id PK

string reservation_id FK

decimal amount

string payment_method

string payment_status

datetime payment_time

}

ContactInfo {

string contact_id PK

string entity_id FK

string contact_type

string contact_value

}


Database Technology Selection

We'll use a relational database (PostgreSQL) for primary storage due to:

  • Strong consistency guarantees (essential for reservation systems)
  • Mature transaction support
  • Reasonable data volume (under 30GB for 2 years)
  • Clear relational data model with complex joins
  • Support for advanced features like partitioning and replication

Partitioning Strategy

Data will be partitioned by parking lot ID, which ensures:

  • Related data stays together (reservations, spots for a given lot)
  • Even distribution of load across database shards
  • Minimal cross-partition queries for typical operations
  • Horizontal scalability while maintaining consistency




High-level design

flowchart TD

Client[Client Applications]

GatewayLB[API Gateway Load Balancer]

APIGateway[API Gateway]

ResLB[Reservation Service LB]

RS[Reservation Service]

PayLB[Payment Service LB]

PS[Payment Service]

TxLB[Transaction Service LB]

TS[Transaction Service]

TMS[Transaction Monitor Service]

NS[Notification Service]

US[User Service]

AS[Analytics Service]

Redis[(Redis Cache)]

RDBM[(Primary DB)]

RDBS[(Read Replicas)]

CDN[CDN]

ThirdParty[Third-Party Payment]

Client --> GatewayLB

GatewayLB --> APIGateway

Client --> CDN

APIGateway --> ResLB

APIGateway --> PayLB

APIGateway --> TxLB

APIGateway --> US

ResLB --> RS

PayLB --> PS

TxLB --> TS

RS --> Redis

RS --> RDBM

PS --> RDBM

PS --> ThirdParty

TS --> RDBM

TS --> Redis

US --> RDBM

TMS --> RDBM

TMS --> NS

RDBM --> RDBS

AS --> RDBS

NS --> Client

subgraph "Service Layer"

RS

PS

TS

US

TMS

NS

AS

end

subgraph "Data Layer"

Redis

RDBM

RDBS

end

style Client fill:#f9f,stroke:#333,stroke-width:2px

style APIGateway fill:#bbf,stroke:#33f,stroke-width:2px

style Redis fill:#bfb,stroke:#3f3,stroke-width:2px

style RDBM fill:#fbb,stroke:#f33,stroke-width:2px

style RDBS fill:#ffb,stroke:#ff3,stroke-width:2px


Architecture Components

  1. Client Applications:
    • Web applications, mobile apps, and kiosk interfaces at parking locations
  2. API Gateway:
    • Entry point for all client requests
    • Provides routing, authentication, rate limiting, and SSL termination
    • Load balanced across multiple availability zones
  3. Service Layer:
    • Microservices architecture with individually scalable components
    • Each service has dedicated responsibilities with proper separation of concerns
    • Stateless design enabling horizontal scaling
  4. Data Layer:
    • Relational database (PostgreSQL) for primary storage
    • Read replicas for scaling read operations
    • Redis for caching frequently accessed data and reservation state
  5. External Integrations:
    • Third-party payment processors
    • Notification delivery services (SMS, email)






Request flows


sequenceDiagram

actor User

participant App as Mobile/Web App

participant API as API Gateway

participant RS as Reservation Service

participant Cache as Redis Cache

participant DB as Database

participant PS as Payment Service

participant PP as Payment Provider

participant NS as Notification Service

User->>App: 1. Check parking availability

App->>API: 2. GET /lots/{id}/capacity

API->>RS: 3. Forward request

RS->>Cache: 4. Check capacity in cache

alt Capacity in cache

Cache-->>RS: 5a. Return cached data

else Cache miss

RS->>DB: 5b. Query database

DB-->>RS: 6b. Return capacity data

RS->>Cache: 7b. Update cache

end

RS-->>API: 8. Return availability & price

API-->>App: 9. Return response

App-->>User: 10. Display available spots

User->>App: 11. Reserve spot

App->>API: 12. POST /reservations

API->>RS: 13. Forward request

RS->>DB: 14. Create reservation (uncommitted)

alt Successful reservation

DB-->>RS: 15a. Reservation created

RS->>PS: 16a. Request payment

PS->>PP: 17a. Forward to payment provider

PP-->>PS: 18a. Return payment URL/token

PS-->>RS: 19a. Return payment info

RS-->>API: 20a. Return reservation & payment URL

API-->>App: 21a. Return response

App-->>User: 22a. Redirect to payment

else Reservation failed (e.g., spot taken)

DB-->>RS: 15b. Error (e.g., conflict)

RS-->>API: 16b. Return error

API-->>App: 17b. Return error response

App-->>User: 18b. Show error & alternatives

end

User->>PP: 23. Complete payment

PP->>PS: 24. Payment callback

PS->>DB: 25. Update payment status

PS->>RS: 26. Notify payment complete

RS->>DB: 27. Commit reservation

RS->>NS: 28. Send confirmation

NS-->>User: 29. Email/SMS confirmation

sequenceDiagram

actor Attendant

participant Terminal as Parking Terminal

participant API as API Gateway

participant TS as Transaction Service

participant DB as Database

participant RS as Reservation Service

participant NS as Notification Service

actor Customer

Customer->>Terminal: 1. Present reservation code

Terminal->>API: 2. Verify reservation

API->>RS: 3. Validate reservation

RS->>DB: 4. Check reservation status

DB-->>RS: 5. Return reservation details

alt Valid reservation

RS-->>API: 6a. Reservation confirmed

API-->>Terminal: 7a. Allow entry

Terminal-->>Attendant: 8a. Open gate

Attendant->>Terminal: 9a. Confirm vehicle entered

Terminal->>API: 10a. POST /transactions/arrival

API->>TS: 11a. Record arrival

TS->>DB: 12a. Create transaction record

TS->>DB: 13a. Update reservation status

else Invalid reservation

RS-->>API: 6b. Reservation invalid

API-->>Terminal: 7b. Deny entry

Terminal-->>Attendant: 8b. Keep gate closed

end

Note over Customer, Terminal: Some time later...

Customer->>Terminal: 14. Present ticket at exit

Terminal->>API: 15. Get reservation details

API->>TS: 16. Request checkout

TS->>DB: 17. Retrieve reservation & transaction

DB-->>TS: 18. Return details

alt Early exit (before reservation end)

TS->>DB: 19a. Update transaction record

TS-->>API: 20a. Return exit approved

API-->>Terminal: 21a. Allow exit

Terminal-->>Attendant: 22a. Open gate

else Late exit (additional charges)

TS->>RS: 19b. Calculate additional charges

RS->>TS: 20b. Return updated charges

TS->>DB: 21b. Update transaction with charges

TS-->>API: 22b. Return exit approval with charges

API-->>Terminal: 23b. Display additional charges

Terminal-->>Customer: 24b. Request payment

Customer->>Terminal: 25b. Make payment

Terminal->>API: 26b. Process additional payment

API-->>Terminal: 27b. Payment confirmed

Terminal-->>Attendant: 28b. Open gate

end

TS->>NS: 29. Send receipt

NS-->>Customer: 30. Email receipt


Key Flow: Reservation Process

  1. User searches for parking availability at a specific lot
  2. System returns available spots and pricing
  3. User selects a spot and creates a reservation
  4. System holds the spot temporarily (optimistic locking)
  5. User is redirected to payment
  6. Upon successful payment, reservation is confirmed
  7. System sends confirmation with a QR code or reference number

Key Flow: Vehicle Check-in

  1. User arrives at the parking lot
  2. User presents reservation code (QR code or reference)
  3. System validates the reservation
  4. System records the check-in time
  5. User parks in the assigned spot

Key Flow: Vehicle Check-out

  1. User returns to the vehicle and proceeds to exit
  2. System calculates final charges (if additional time used)
  3. User pays any additional charges (if applicable)
  4. System records the check-out time and completes the transaction
  5. User exits the parking lot

Key Flow: No-Show Handling

  1. Transaction Monitor Service periodically checks for no-shows
  2. For reservations where start_time + buffer (e.g., 2 hours) has passed with no check-in
  3. System marks the reservation as a no-show
  4. System charges the user for 24 hours as per policy
  5. System releases the spot for new reservations




Detailed component design


Reservation Service - Slot Allocation System

The Reservation Service is a critical component requiring special attention due to its impact on consistency and user satisfaction. The key challenge is efficiently finding available spots while preventing double-booking.

Bitmap Approach for Availability Tracking

Each parking spot's availability is tracked using a bitmap:

  • Time is divided into 15-minute slots (96 slots per day)
  • Each slot is represented by a bit (1 = occupied, 0 = available)
  • For each spot, we store a bitmap per day
  • For a 1-year reservation window, each spot requires ~4KB storage
Reservation Algorithm
コピー function findAvailableSpot(lotId, startTime, endTime, vehicleType): // Convert times to slot indices startSlot = convertTimeToSlotIndex(startTime) endSlot = convertTimeToSlotIndex(endTime) // Create a bitmap representing requested time requestBitmap = createBitmapForTimeRange(startSlot, endSlot) // Get spots with compatible vehicle type eligibleSpots = getEligibleSpots(lotId, vehicleType) // Find closest available spot (transaction with SELECT FOR UPDATE) BEGIN TRANSACTION for spot in eligibleSpots: // Get bitmap for relevant days spotBitmaps = getSpotBitmapsForDays(spot.id, startTime, endTime) // Check if any timeslot overlaps if !hasOverlap(spotBitmaps, requestBitmap): // Update spot's bitmap with the new reservation updateSpotBitmaps(spot.id, requestBitmap, startTime, endTime) COMMIT TRANSACTION return spot ROLLBACK TRANSACTION return null // No available spot found

The strength of this approach:

  • O(1) lookup time per spot
  • Compact representation of availability
  • Efficient batch operations for multiple days
  • Atomic operations with database transactions

Memory requirement for the bitmap approach:

  • 1,000 lots × 200 spots × 4KB = ~0.8GB for a 1-year window
  • Will easily fit in cache for fast operations

Limitations:

  • Fixed 15-minute intervals
  • Storage grows linearly with reservation window

Transaction Monitor Service

This service handles edge cases such as no-shows, late arrivals, and early departures.

コピー function monitorNoShows(): // Find reservations that have started but have no check-in record cutoffTime = currentTime - NO_SHOW_BUFFER // Query for potential no-shows possibleNoShows = queryReservations( where: "start_time < cutoffTime AND completion_status = 'to_be_completed' AND NOT EXISTS (select 1 from transactions where transactions.reservation_id = reservations.id)" ) foreach reservation in possibleNoShows: // Apply no-show policy markAsNoShow(reservation.id) applyCharges(reservation.id, NO_SHOW_CHARGE_DURATION) // Release the spot for future reservations updateSpotAvailability(reservation.spot_id, reservation.start_time, reservation.end_time) // Notify user sendNoShowNotification(reservation.user_id)

This approach ensures:

  • Spots don't remain unused due to no-shows
  • Business policies are enforced consistently
  • Users are notified of charges





Trade offs/Tech choices

Database Selection: Relational vs. NoSQL

OptionProsConsDecision
Relational DB (PostgreSQL)- Strong consistency guarantees<br>- ACID transactions<br>- Complex query support<br>- Well-suited for relational data- Horizontal scaling challenges<br>- Potentially higher latency for writesSelected for core transactional data due to consistency requirements
NoSQL (e.g., MongoDB)- Horizontal scaling<br>- Flexible schema<br>- Potentially higher write throughput- Eventual consistency<br>- Less support for complex joins<br>- Transaction limitationsNot selected for core data, but could be used for analytics

Cache Strategy: In-Memory vs. Distributed

OptionProsConsDecision
In-Memory (Single Node Redis)- Lower latency<br>- Simpler setup<br>- No data partitioning- Limited by single node capacity<br>- Single point of failureUsed for development and small deployments
Distributed Cache (Redis Cluster)- Horizontal scalability<br>- Higher availability<br>- Partitioned data- Higher operational complexity<br>- Network overheadSelected for production to support scaling requirements

Reservation Approach: Pessimistic vs. Optimistic Locking

OptionProsConsDecision
Pessimistic Locking- Prevents conflicts entirely<br>- Simpler error handling- Reduced concurrency<br>- Potential for deadlocksUsed for critical operations like final reservation confirmation
Optimistic Locking- Higher concurrency<br>- Better performance under low contention- Conflicts require retry logic<br>- More complex error handlingSelected for initial reservation creation with timeout mechanism




Failure scenarios/bottlenecks


Potential Failure Points

    • Database AvailabilityRisk: Single point of failure if not properly replicated
    • Mitigation: Multi-AZ database deployment with automatic failover, read replicas for scaling reads
    • Payment Processing FailuresRisk: Incomplete transactions if payment service unavailable
    • Mitigation: Asynchronous payment workflow, reservation timeout for incomplete payments, retry mechanisms
    • Peak Load HandlingRisk: System overload during high-demand events
    • Mitigation: Auto-scaling for services, rate limiting at API Gateway, queue-based processing for non-critical operations
    • Service-to-Service CommunicationRisk: Cascading failures if dependencies are unavailable
    • Mitigation: Circuit breakers, fallback mechanisms, retries with exponential backoff


Scalability Bottlenecks

    • Database Write OperationsBottleneck: Reservation creation requires serializable transactions
    • Solution: Partition data by lot_id, implement connection pooling, optimize indexes
    • Cache CoherenceBottleneck: Maintaining consistent cache state across distributed system
    • Solution: Cache invalidation patterns, time-to-live (TTL) settings, write-through caching
    • Geographic DistributionBottleneck: Latency for users far from data centers
    • Solution: Regional deployments, CDN for static content, edge caching

Disaster Recovery

  1. Data Backup Strategy:
    • Continuous incremental backups
    • Daily full backups stored in multiple regions
    • Point-in-time recovery capability
  2. Recovery Time Objective (RTO): 1 hour for full system recovery
  3. Recovery Point Objective (RPO): 5 minutes maximum data loss
  4. Failover Process:
    • Automated database failover to standby replicas
    • Service deployment in multiple availability zones
    • Global load balancing for regional failover



Future improvements


Short-term Enhancements

  1. Advanced Reservation Features:
    • Recurring reservations for regular users
    • Flexible pricing based on demand and time of day
    • Reservation modifications and cancellation policies
  2. User Experience Improvements:
    • Interactive parking map selection
    • Saved favorite parking lots
    • Integration with navigation apps
  3. Operational Improvements:
    • Enhanced monitoring and alerting
    • Improved analytics for usage patterns
    • Automated capacity planning