System requirements
Functional:
- Users should be able to reserve a parking spot in advance.
- User pay for parking spot : daily or monthly
- User take a vehical out of spot of anytime
- System checking user infomation : user name , time parking spot out or in
- Vehicle Type Accommodation:
- Clearly specify the need to reserve spots based on vehicle size (compact, standard, large).
- Security Features:
- Include functionalities for displaying or reporting any unauthorized vehicles parked.
- Check for wrong user card
Non-Functional:
- Scalability: We are designing this for an company which manage building for other company hired. Assume : 1 building have 1000 parking slot
- Availability: System should always run for weekly working
- Consistency:
- Emphasize the importance of data consistency, especially during updates or reservation changes, to prevent booking errors.
- Performance:
- Implement measures to keep the system responsive even under heavy load, ensuring that user actions are processed within acceptable time frames.
- User Experience:
- Focus on intuitive design for easy navigation and interaction, minimizing user effort in all system interactions.
Capacity estimation
I assume:
- The company has 5 buildings
- 1 buildings has 1 parking lot contain 1000 slot
- 80% of users use it for short term parking, 8 hours
- For each parking lot, there are depend on number of employee working on that building. So we could take 80% capacity of 1000 slot that is 800
Estimation:
- 800 *5 building = 4000 reservation requests per day.
- We have two request in or out so will be 8000 reservation requests per day.
- Each reservation would mainly consists of:
- User ID (20 bytes)
- User's company name (5 byte)
- Car type (1 byte)
- Car ID (1 byte)
- Payment info: total of month (1 byte)
- Reservation start time (8 byte)
- Reservation end time (8 byte)
- Roughly totaling 50 bytes.
- Other metadata: User company name,
- Each day, we would add 500KB of data.
- In 1 year, it would add up to 182MB, we extend 20% more so it will be 212MB.
- In 5 years, It become 1GB
API design
User Management :
- GET api/user/{userId}
- POST api/user(userId, userCompany, CarType, carId)
- PUT api/user(userId, userCompany, CarType, carId)
Reservations Management
- POST api/reservation (userId, start_time, spot_id)
- PUT api/reservation (userId, end_time)
Payment:
- GET api/payment (userId)
- POST api/confirmPayment
Database design
Database Choice: The user solution suggests using relational databases without additional context. Since this is a parking reservation system with a requirement for strong consistency (to prevent double booking) and considering the estimated data size, choosing an RDBMS is appropriate.
User Table:
- user_Id (primary key)
- user_name (string)
- company_id (foreign key)
Company table:
- company_id (primary_key)
- name (string)
Vehicle table
- vehicle_id (primary key)
- name (string)
- type (string)
- register_id (string)
Reservation table:
- reservation_id (primary key)
- user_id (foreign key)
- spot_id (foreign key)
- time_start (date_time)
- time_end (date_time)
- status (string)
Spot table:
- spot_id (primary key)
- building_name (string)
- floor (string)
Payment table:
- payment_id (primary key)
- user_id (foreign key)
- daily_pay (number)
- total_in_month ( number)
- payment_status (string)
High-level design
flowchart TD
CL[Client] --> |HTTP Request| GW[API Gateway]
GW --> |Filter Requests| RL[Rate Limiter]
RL --> |Distribute Load| LB[Load Balancer]
LB --> |Handle Reservations| RES[Reservation Server]
RES --> |Query Cache| CC[Cache]
RES --> |SQL Queries| DB[Database]
RES --> |Send Messages| MQ[Message Queue]
MQ --> |Process Payments| PAY[Payment System]
RES --> |Send Notifications| NS[Notification System]
NS --> |Real-Time Alerts| CL
LB --> |User Data Handling| UX[User Server]
UX --> |SQL Queries| DB[Database]
Request flows
sequenceDiagram
participant User
participant Load Balancer
participant APIGateway
participant ReservationService
participant PaymentService
participant UserService
participant Cache
participant Database
User->>Load Balancer: Request Reservation In POST/api/reservation()
Load Balancer->>APIGateway: Forward request
APIGateway->>Cache: Check Authorization
APIGateway->>ReservationService: Make reservation
ReservationService->>Cache: Insert new reservation
ReservationService-->>APIGateway: Return Message success
APIGateway-->>Load Balancer: Return Message success
Load Balancer-->>User: Return Message success
PaymentService->>Cache: Create Payment
Cache->>Database: write-behind caching
User->>Load Balancer: Request Reservation Out PUT/api/reservation()
Load Balancer->>APIGateway: Forward request
APIGateway->>Cache: Check Authorization
ReservationService->>Database: Update reservation
Database-->>ReservationService: Return Message success
ReservationService->>PaymentService: Update Payment Daily
PaymentService-->>ReservationService: Update Payment Daily Success
ReservationService-->>APIGateway: Reservation Status
APIGateway-->>User: Reservation Status
User->>Load Balancer: Get User info get api/user/{user_id}
Load Balancer->>APIGateway: Forward request
APIGateway->>Cache: Check Authorization
UserService->>Database: GET User Info
Database-->>UserService: Return Message success
UserService-->>APIGateway: Return Message success
APIGateway-->>User: User Info
User->>Load Balancer: Request User POST api/user()
Load Balancer->>APIGateway: Forward request
APIGateway->>Cache: Check Authorization
UserService->>Database: Create User Info
Database-->>UserService: Return Message success
UserService-->>APIGateway: Return Message success
APIGateway-->>User: User Status
User->>Load Balance: Request Payment GET api/payment()
Load Balancer->>APIGateway: Forward request
APIGateway->>Cache: Check Authorization
PaymentService->>Database: Get User payment
Database-->>PaymentService: Return total number
PaymentService-->>APIGateway: Return total number
APIGateway-->>User: Return total number
User->>Load Balancer: Payment confirm POST api/confirmPayment()
Load Balancer->>APIGateway: Forward request
APIGateway->>Cache: Check Authorization
PaymentService->>Database: Get User payment
Database-->>PaymentService: Update staus payment
PaymentService-->>APIGateway: Return Message success
APIGateway-->>User: Return Message success
Detailed component design
Database:
- Stores all critical data such as user profiles, reservation details, transaction logs, and payment information. Ensures data persistence and consistency. Strong consistency we choose SQL: PostgreSQL
- Scalability:
- Vertical scaling: By number of employee will grow we need more storage
- Horizontal scaling: Db sharding by spot_id will improve read performance
- Replicas: consider use coppy of main db if main db failing
API Gateway:
- Security: handles user authentication and authorization
- Rate Limiting: Implements rate limiting to prevent misuse and ensure fair use of service.
- Request Routing: Distributes incoming requests to the appropriate backend services (e.g., Reservation Service, User Service).
- Audit and Logging: Maintains logs for monitoring and auditing purposes to track and diagnose issues efficiently.
Load Balancer:
- Health Monitoring: Continuously checks the health of service instances and reroutes traffic to healthy instances, avoiding downtimes.
- Load Distribution: Uses algorithms such as round-robin or least connections to efficiently distribute traffic.
Cache:
- Improves performance by storing frequently accessed data, such as available parking spots
- Write Behind / Write Back: Write sequence data to cache and then import to db. Improve write performance
- Read Through: Client read cache when make reservation out or user info. If miss cache read db
Trade offs/Tech choices
Database: we choose SQL
- Pros: Strong consistecy, support complex join bettwen tables
- Cons: Hard to scaling without more comlexities
Cache:
- In-memory(Redis): Highly performant for storing frequently accessed data, reducing database load.
- Cons: Can lose data if server down
API Gateway:
- Complexity: when adding more routing logic
- Debugging Difficulty: authorize fail,
Failure scenarios/bottlenecks
Failure Scenarios:
- Database Failure:
- Scenario: The database becomes unavailable due to a hardware failure, network issue, or incorrect configuration.
- Mitigation: Utilize database replicas and failover mechanisms. Implement regular backups and use a distributed transactional database system to ensure high availability.
2. Cache Invalidation/Failure:
- Scenario: The cache returns stale data due to invalidation failures, leading to inconsistent views of available parking spots.
- Mitigation: Implement cache expiration and invalidation strategies. Use a write-through or write-behind cache for critical data, ensuring the cache and database remain synchronized.
Bottlenecks:
- Database Write Bottlenecks:
- Cause: High volume of simultaneous writes to the database, especially during peak reservation times.
- Resolution: Optimize database write operations and consider sharding or partitioning data to spread the load.
Future improvements
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?