System requirements


Functional:

List functional requirements for the system (Ask the chat bot for hints if stuck.)...

  1. Reserve a space for an allotted time, pay through a third party application and get a ticket/receipt for payment
  2. Look up available parking spots
  3. Cancel an existing reservation

Non-Functional:

List non-functional requirements for the system...

  1. 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
  2. Should be able to connect with third party applications well; i.e. Stripe for payment, potential Calendar application integration
  3. 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: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"

}


Gate Checking Service API Requests

  • /api/v1/vehicleArrived

UPDATE Request - Used to detail when car has arrived to its reserved parking space and update existing record. Service exists to address no show appointments and free up potential spaces.

Request:

{

"reservation_id": "124916",

"time_arrived": "2024-10-01 12:00:00"

}

Response:

204 HTTP Response


  • /api/v1/vehicleLeft

UPDATE Request - Used to detail and update existing record on when car left

Request:

{

"reservation_id": "124916",

"time_left": "2024-10-01 13:00:00"

}

Response:

204 HTTP Response


  • /api/v1/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)

reservation_id(int)

space_type: (varchar)

address: (varchar)

city: (varchar)

country: (varchar)

time_arrived: (datetime)

time_left: (datetime)

available: (boolean)


Transaction_Tbl

Schema

reservation_id(int: Primary Key - Unique)

receipt_id (int)

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
  • Use Gate checking service at individual parking lots to determine if a car has shown up or left for its reservation.
  • 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.
  • UPDATE Requests such as from the gate checking service are routed to write service and update existing records with the timestamps of when vehicle has arrived or left its reservation after providing reservation_id in the request and receiving 200 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
  • Gate checking service sends API Requests to notify when cars have arrived and left for their reservation. If car has not shown up within 15 mins of the start of their reservation then their reservation is automatically cancelled.
  • Load Balancer (AWS Network Load Balancer - due to multiple reads and high volume of traffic data) - 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.