System requirements
Functional:
- Design a parking lot service that covers all vehicles such as cars (all all body types including SUVs), trucks, tractors, two wheelers and cycles
- We should also consider EV's and Hybrid vehicles that may require a charging or plug-in
- Special needs people and people with small children should have their reserved space.
- Users pay by Application
- They must be allotted a parking spot for a paid duration
- User notification on parking times
Non-Functional:
- High Availability. Our system must be always available
- High Scalability, During peak hours we ensure our system can adjust the load
- Security Monitoring
Capacity estimation
- Assuming this parking lot has a capacity of 2400 cars
- Each car is allotted a space for a minimum of 1 hour
- so, we can have 2400 cars per hour i.e. we can have 2400 *24 = approx 60,000 cars per day.
- Each car has 1MB info, 60K* 1M = 60 Billion = So, we may need 60GB (2^30 = 1GB) storage, with buffer, we may be 120 GB storage. For 10 years we will need 1.2 TB storage
- During peak hours, we may have 100 times the request i.e. 2400 * 100 = 240K requests per hour = 24K/3600 ~= approx 70 request/second
API design
POST - /api/v1/reservation
inputs:
- CAR REGISTRATION
outputs:
- Allotment ID
- Time Remaining
LIST - /api/v1/available_spaces
input:
- NONE
output
- Total number of available spaces
- Total number of available spaces for special needs and children carrier
- Total number of spaces for EV's with charging station
- Total number of spaces for vehicles of height over 5 meter
GET - /api/v1/allotment
input:
- car registration
output
- Allotment ID
- Time Remaining
POST - /api/v1/reservation/extend
input:
- car registration
output
- Allotment ID
- Time Remaining
POST - /api/v1/notify
input:
- user_id
output
- Time Remaining
Database design
- Since our usage is less than 5 TB and we will need ACID compliance as we have payments support which is w.r.t the hours of usage. Thus, we choose a RDBMS to store the state.
Reservation Table
String User_id NOT NULL,
String Car_Registration, PRIMARY KEY
Number Contact number NOT NULL,
String Email NOT NULL,
String Allotment_id
Timestamp<tz> Reserved_at
Timestamp<tz> Reserved_until
Allotment table
String Allotment_id NOT NULL PRIMARY KEY,
String Status NOT NULL,
String Allotment_type NOT NULL,
High-level design
Load Balancer: Act as an entry point to our service. This ensure we can scale and de-scale our service effectively
Cache: A list of reservations for a day. We invalidate the cache in 86400 seconds (1 day)
Parking Lot System: Our Service that supports Reservation APIs
Payment Service: An External service that manages client payments
Notification Service: Reads from the database and notifies for all reservations due to expire in 10 mins or less exactly once.
Database: State of our Service. Reserved, Empty
Request flows
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
Detailed component design
- Parking Lot system: Multi Threaded system | Concurrent
- Reads through cache and lists all available spaces.
- For a new allotment,
- acquires a lock in the database table (to ensure atomic operations), temporarily marking it as Reserved
- calls payment service and if successful reserves the space else, fails the transaction and releases the lock
- Notification service every 9 processes from database, by accumulating all reservations with less than 10 mins. Batch notifies all of them at-once using fan-out approach. Since this is the only operation that does this op. i think it is fine. however, if this becomes an issue we can switch to leader follower pattern for notification service. We also need to implement a retry logic with exponential backoff.
Trade offs/Tech choices
- We have chosen in /api/v1/reservation to not ask about the type of vehicle. As we expect users on the landing page be presented the output from List: /api/v1/available_spaces API which clearly lays out spaces in each category. This helps keep our focus on reservation management and we also know that, there are physical restrictions for such vehicles on the facility.
- Since our system demands ACID compliance we chose RDBMS this limits our ability to scale the database. We must ensure correct High availability with Active Standby model and Replication strategy
- Replication Strategy: A cost effective strategy would be to use Volume based replication, snapshots are taken at regular intervals and stored in Object Storage such AWS S3
- Notification Service. We chose not to write use message queue. because if we have missed to notify, there is no-point in re-notifying them unnecessary. So, if a notification service failure occurs, we apologise with a message. This shows our honesty with the customers rather than late notifying or bulk notifying the customers.
- Cache invalidation: We expire in 1 day. As we don't expect lot of cars post midnight. Also, invalidating using time remaining could create conflict, say notification service failed and user has not yet vacated the parking spot. In this case we may show users incorrect data
Failure scenarios/bottlenecks
- Database in our system could be a single point of failure. Also, since we have chosen a RDBMS, we won't be able to scale it horizontally.
- Notification Service. If we fail to notify customers, we may have to deal with issues of over parking usage
- Payment Service: We cannot complete transaction unless payment has been succeeded
Future improvements
- Variable Pricing for the hours and days. Peak hour prices could be different. Weekdays prices are different from Weekends. Midnight until 6:00 AM, we could offer ultra low prices or free parking
- CCTV management and Alarms for vehicles and customers safety and security
- Implement User notifications for parking
- Location Tracking: So we don't rely on hardware to ensure that the parking has been vacated or not. We can use apis such as whatthreewords to track exact co-ordinates and update our system