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 Service | Manages parking spot reservations, availability checks, and reservation lifecycle | FR1, FR5 | NFR1, NFR3, NFR4 |
| Payment Service | Handles payment processing and integration with third-party payment providers | FR2 | NFR2, NFR5 |
| Transaction Service | Manages vehicle entry/exit operations and updates reservation status | FR3, FR4 | NFR2, NFR3 |
| Transaction Monitor Service | Detects no-shows and handles automatic reservation status updates | FR5 | NFR2, NFR3 |
| User Service | Manages user accounts, profiles, and authentication | Supports FR1-FR5 | NFR5 |
| Notification Service | Sends confirmations, reminders, and alerts to users | Supports FR1-FR5 | NFR2 |
| Analytics Service | Collects and processes usage data for business intelligence | Supports system optimization | NFR1, 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
- Client Applications:
- Web applications, mobile apps, and kiosk interfaces at parking locations
- API Gateway:
- Entry point for all client requests
- Provides routing, authentication, rate limiting, and SSL termination
- Load balanced across multiple availability zones
- Service Layer:
- Microservices architecture with individually scalable components
- Each service has dedicated responsibilities with proper separation of concerns
- Stateless design enabling horizontal scaling
- Data Layer:
- Relational database (PostgreSQL) for primary storage
- Read replicas for scaling read operations
- Redis for caching frequently accessed data and reservation state
- 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
- User searches for parking availability at a specific lot
- System returns available spots and pricing
- User selects a spot and creates a reservation
- System holds the spot temporarily (optimistic locking)
- User is redirected to payment
- Upon successful payment, reservation is confirmed
- System sends confirmation with a QR code or reference number
Key Flow: Vehicle Check-in
- User arrives at the parking lot
- User presents reservation code (QR code or reference)
- System validates the reservation
- System records the check-in time
- User parks in the assigned spot
Key Flow: Vehicle Check-out
- User returns to the vehicle and proceeds to exit
- System calculates final charges (if additional time used)
- User pays any additional charges (if applicable)
- System records the check-out time and completes the transaction
- User exits the parking lot
Key Flow: No-Show Handling
- Transaction Monitor Service periodically checks for no-shows
- For reservations where start_time + buffer (e.g., 2 hours) has passed with no check-in
- System marks the reservation as a no-show
- System charges the user for 24 hours as per policy
- 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 writes | Selected 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 limitations | Not 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 failure | Used for development and small deployments |
| Distributed Cache (Redis Cluster) | - Horizontal scalability<br>- Higher availability<br>- Partitioned data | - Higher operational complexity<br>- Network overhead | Selected 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 deadlocks | Used 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 handling | Selected 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
- Data Backup Strategy:
- Continuous incremental backups
- Daily full backups stored in multiple regions
- Point-in-time recovery capability
- Recovery Time Objective (RTO): 1 hour for full system recovery
- Recovery Point Objective (RPO): 5 minutes maximum data loss
- 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
- Advanced Reservation Features:
- Recurring reservations for regular users
- Flexible pricing based on demand and time of day
- Reservation modifications and cancellation policies
- User Experience Improvements:
- Interactive parking map selection
- Saved favorite parking lots
- Integration with navigation apps
- Operational Improvements:
- Enhanced monitoring and alerting
- Improved analytics for usage patterns
- Automated capacity planning