System requirements
Functional:
List functional requirements for the system (Ask the chat bot for hints if stuck.)...
- Reserve a space for an allotted time, pay through a third party application and get a ticket/receipt for payment
- Look up available parking spots
- Cancel an existing reservation
Non-Functional:
List non-functional requirements for the system...
- System must be highly consistent so no collision occurs and two spaces are not reserved at the same time, can sacrifice some latency for this
- Should be able to connect with third party applications well; i.e. Stripe for payment, potential Calendar application integration
- Be regionally available for support for 10 different countries
Capacity estimation
Estimate the scale of the system you are going to design...
- 200,000 write requests per day for all parking lots with around 2.3 write requests per second. Assume five times the amount of read requests for about 10 reads per second or 1,000,000 reads a day between all parking lots
- Estimate around 120 bytes for each entry between (name,parking_space,times_start,time_end). 120 bytes x 200,000 writes/day x 365 days x 5 years = 43.8 GB of storage within 5 years. Can use 100 GB of storage
API design
Define what APIs are expected from the system...
Public Endpoints
- /api/v1/reserve
POST Request - User provides paking_space_id and reservation_id is serializable which gets generated after a third party service (Stripe) validates user has paid through a token.
Request:
{
"reservation_id":"124916",
"parking_space_id": "12",
"parking_lot_id" : "2",
"name" : "Stephen"
}
Response:
{
"receipt_id": "1206",
"expiration_time": "2024-10-01 14:00"
}
- /api/v1/cancel/{reservation_id}
DELETE Request - User provides reservation_id so that they may cancel their current parking space reservation
Request:
{
"reservation_id": "124916"
}
Response:
204 HTTP Status code
Internal Endpoints
- /api/v1/calculateFreeSpots
GET Request - Used to calculate how many free spaces we might have available in a parking lot to display on our web app or outside the garage. Calculation can be done through a series of SQL transformations like COUNT on a specified parking lot and doing a query on status of each spot.
Request:
{
"parking_lot_id":"2"
}
Response:
{
"available_spaces": "13"
}
- /payment
(Handled by third party - Stripe, Token generated upon completion of payment to proceed with reservation)
Database design
Defining the system data model early on will clarify how data will flow among different components of the system. Also you could draw an ER diagram using the diagramming tool to enhance your design...
- Use relational database (Postgres), not a high amount of data to justify excessive scaling for database through NoSQL
- Lots of relational transformations possible, i.e. joins based on parking_lot_id to find total number of available parking spaces in a particular country/city
- Relational databases are good for avoiding collision too due to ACID properties
Tables:
Parking_Lot_Tbl
Schema
parking_space_id (int: Primary Key - Unique)
parking_lot_id (int)
space_type: (varchar)
address: (varchar)
city: (varchar)
country: (varchar)
available: (boolean)
Transaction_Tbl
Schema
transaction_id (int: Primary Key - Unique)
name: (varchar)
parking_space_id: (int)
space_type: (varchar)
date: (datetime)
High-level design
You should identify enough components that are needed to solve the actual problem from end to end. Also remember to draw a block diagram using the diagramming tool to augment your design. If you are unfamiliar with the tool, you can simply describe your design to the chat bot and ask it to generate a starter diagram for you to modify...
- Utilize CDN (Pull-based since content is static - AWS CloudFront) due to 100 parking lots in 10 different countries, differences in currency and price. CDN also helps in showing spaces only relevant to client i.e. within the same city
- Load balancer for distributed system (AWS Network Load Balancer since high amount of reads), with servers in multiple availability zones, can use AWS EC2 servers set up across multiple regions/Availability zones
- Multiple SQL database replicas to support availability across multiple countries with good support for reads. Synchronous replication across databases to ensure consistency at the cost of slight latency to ensure no collision is happening for the same parking spots.
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...
- Client is directed through load balancer to the API Gateway. From the API Gateway POST requests for /reserve are directed to the reservation service with the payment being verified through a third party application such as Stripe, once token is generated a write is generated to the Postgres database, with any failures causing the previous step to rollback. When write is successful, client is streamed back a receipt in the form of a returned receipt_id and an expiration time stamp
- GET Request such as /calculateFreeSpots are directed to our read service with a provided "parking_lot_id" field. The read cache is first checked to see if that corresponding "parking_lot_id" is present recently and if so provides the "available_spaces" for that given id. If cache doesn't hit, "parking_lot_id" will query the actual Postgres database and initiate a stored procedure to check the available spaces for the given parking_lot_id by querying Parking_Lot_Tbl. Result is then stored in the cache and streamed back to the internal service of "available spaces".
- DELETE Request such as /cancel are routed to the API Gateway which then routes to delete service. the DELETE service then uses the provided "reservation_id" field to look up in the database the corresponding id and removes it from the database as well as from the cache and returns 204 HTTP Status code.
Detailed component design
Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...
- CDN serves to show most readily available parking lots to client based on location
- Load Balancer (AWS Network Load Balancer - due to multiple reads) - can utilize Geolocation based load balancing to match clients closer to their parking lots. Could also include some weighted policy to the load balancer for high volume areas (NYC).
- Cache is being used with a LFU eviction policy for high traffic read requests. We delegate to LFU eviction policy because there are certain parking spaces that are used more frequently than others and for the most part will be in traffic majority of the time.
Trade offs/Tech choices
Explain any trade offs you have made and why you made certain tech choices...
- Have added some latency from the usage of synchronous replication for database but allows for more consistency and prevents collision on same parking spaces.
- Added latency from cross regional transactions with the presence of parking lots in 10 different countries.
Failure scenarios/bottlenecks
Try to discuss as many failure scenarios/bottlenecks as possible.
- Highly traffic areas could be subject to more usage depending on different times of day i.e. NYC with a big concert, system needs to be able to scale during these high traffic changes
Future improvements
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?
- Incorporate license plate usage as opposed to numbered spaces within parking lot, would require more changes in CDN based on license plate changes between countries
- Add account creation and enforce some type of account validation so only users that have created receipts can cancel only their reservations, incorporating this would require some use of a third party security service upon client request to API gateway.