The assumption here is that this is for private parking lots and thus will require reservations either at the time of admission or before hand in order to obtain access.
Client flow:
Scalability
An assumption can be made here that we are making this for a parking lot management company that has 100s if not 1000s of parking lots under their jurisdiction.
Security
The user's data, payment methods and such should be secured through encryption, signatures and other compliance methods as mandated by the financial industry.
Reliability
The system must be resilient meaning that outages are not acceptable as it would prevent accurate information about available slots, payment transactions and other finer details from being visible.
Also when booking is made, double booking cannot take place, this means there must be a system in place to ensure that users cannot attempt to book the same slot at once. The person who books first must have the slot available. In situations where race conditions occurs regarding a specific slot, a priority queue of sorts may be needed to ensure that
Performance
Performance must be steady, and capable of handling 100s of requests per second.
Availability
System should be available constantly as otherwise information regarding lots and their reserved slots will either become unavailable or lost resulting in customer transactions that are required to be reversed from a set period of time. Ideally there is some redundancy in place to avoid this in the form of hot swapping or something way.
The following are all assumptions.
Company is in operation in 5 countries
Per nation, country has around 100 lots allocated on average
Each lot has approximately 300 slots, 60-70% are typically regular slots, 20% are oversized slots and the remaining 10-20% are for compact vehicles
There are typically 70 reservations requests per lot every 6 hours.
On average 30% of these reservations are for regular slots and the remaining are for oversize and compact vehicles that require the special places
Estimation of values:
70 * 4 = 280 requests per lot /24 hours
280 * ~100 = ~28000 reservation requests / country
~28000 * 5 = 140000 requests /day
Each Request contains information like:
user_id: UUID (16 bytes)
slot_id: UUID (16 bytes)
res_start:datetime (8 bytes)
res_end:datetime (8 bytes)
vehicle_type: Char (1 byte)
Overall request size is about 49 bytes which we can round to 50 for a easy number to work with. 50 bytes * 140000 / day = 7000000 bytes / day = 7MB/day
Because the overall data that we work with per day is quite small in size, it would be best to work with something that does not require constant partitioning due to sizing issues unlike with other applications that may be worked with.
Using a traditional REST API would be effective in this application as there is not a need for real time data to be transmitted to the user like with chat applications.
The following endpoints are required in this situation
registerUser(username, password (hashed))
reserve(user_id, vehicle_id, lot_id, vehicle_type, start_time, end_time)
cancelReserve(user_id, reserve_id)
checkCapacity(lot_id, vehicle_type, start_time, end_time)
payment(user_id, reserve_id) - this triggers a third party integration which handles transactions
On-site API endpoints
confirmArrival(reserve_id, arrival_time)
confirmDeparture(reserve_id, departure_time)
As confirmed previously we are using a mySQL style database to handle the information that is to be handled ranging from user data to vehicular information to lot information.
As such the tables are as follows:
User Table:
Reservation Table
Lot Table
Lot_Capacities Table
Vehicle_Type Table
Transactions Table
CDN is used to store static content that is not particularly necessary to store on the front end application side which will prevent bloating
Rate Limiter should also be introduced prior to the API layer to prevent DOS attacks from taking place
Load balancer would distribute traffic between instances of the service layer that would tackle the processes for our API calls as well as for any reads that need to be done for our database based on regional redirection that may be necessary
registerUser can be handled by the Reservation Service. Will reject creation if the params provided already exist within the database. On failure will return 400 in place of 200
reserve is an API call that is to be handled by the Reservation Service and will contact the Database in order to write the new reservation record within it, making sure to make connections to the user, vehicle and lot tables as well to ensure all the relevant information is present. On success this will return a 200. However, if a double booking is discovered either from the cache or in a database when attempting to write it will also stop and return a 400, and prompt a retry. In the situation where the final slot is booked before the reservation goes through the same failure will be returned
cancelReserve Another API call to be handled by the Reservation Service which will be contacting the data base in order to update the status of an existing reservation record to Cancelled, and should be marked as such on the front end or should be removed altogether (though the former seems more appropriate to let users parse through their own data with filters in the front end to sift out currently inactive reservations). On a success this is a 200 error but if for whatever reason the cancel fails, a retry attempt will kick in before returning a 400.
checkCapacity - this is one of the endpoints that will frequently read backend data and thus will require a cache in order to reduce the number of reads at any given time. An LRU cache would be fitting for this as it would ensure the most popular lots would be present here for quicker checks than having to read the database
On-site API endpoints
confirmArrival
confirmDeparture(reserve_id, departure_time)
One important algorithm is how to find an open spot when reserve is called by the API.
To support this functionality, we would chop 24 hours into 30 minute intervals. One day would be represented by 48 instances for any given slot. In terms of the reservation function, the only information that is required is occupied / unoccupied, we can use a bit to represent the slot in within any given parking lot. Each individual spot requires 48 bits per day. 17520 bits (~2KB) per year.
When reserve(user_id, vehicle_id, lot_id, vehicle_type, start_time, end_time) is called, the algorithm would be:
The run through of the different parking spots during our search will be bounded because we know there is a maximum number regardless of which lot is chosen. As such the performance wouldn't suffer in a manner that might be significant.
It would probably be possible to use Interval Tree data structure to optimize this algorithm further, as it will cover each slot in logn time where n is the number of possible slots for a parking space within a year.
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?