Requirements


Functional Requirements:


  • Allow reservation of a parking spot.
  • Process payment for the reservation.
  • Enable parking of a car in the reserved spot.
  • Support early departure before reservation time expires.
  • Gate check-in/out.
  • Handle no show.



Non-Functional Requirements:


  • Needs to be consistent (need to handle multiple attempts of reserving the same parking spot at the same time)
  • Needs to be reliable (needs servers to always be up)


Capacity:


  • Assume we need to handle about 500 million parking lots around the world
  • Assume every parking lot can hold about 100 cars
  • Assume users park and depart around 5 times a second
  • Assume users reserve around 10 times a second


(5 cars parking and departing/second) * 60 seconds * 60 minutes * 24 hours * 365 days * 5 years = 788 million

Assume every database entry is about 500 bytes = 394 GB


(10 users reserving/second) * 60 seconds * 60 minutes * 24 hours * 365 days * 5 years = 1.6 billion

Assume every database entry is about 500 bytes = 788 GB


API Design


  1. reserveParking API
    1. Request: { userId: string, parkingLotId: string, parkingSpaceId: string, reservationTimeStart: DateTime, reservationTimeEnd: DateTime }
    2. Response: None
  2. getReservations API
    1. Request: { userId: string }
    2. Response: { parkingLotId: string, parkingSpaceId: string, reservationTimeStart: DateTime, reservationTimeEnd: DateTime }
  3. parkCar API
    1. Request: { userId: string, parkingLotId: string, parkingSpaceId: string }
    2. Response: None
  4. departCar API
    1. Request: { userId: string, parkingLotId: string, parkingSpaceId: string }
    2. Response: None
  5. checkInGate API
    1. Request: { userId: string, parkingLotId: string, time: DateTime }
    2. Response: None
  6. checkOutGate API
    1. Request: { userId: string, parkingLotId: string, time: DateTime }
    2. Response: None


High-Level Design


The client will connect to a load balancer to balance the requests made to the server. Client will also connect to CDN to access static content for better performance.


The load balancer can direct to the server which points to different services. We will have the reservation service which will handle all reservations and payment related actions. We handle both in the same service so that if payment fails, reservations should also fail. Payments can be sent to a message queue which will be sent to an external payment system. We will write all items to a write through cache which will directly store that into the database. All the services will check the cache first and if we get a cache miss, we will check the database.


We will have multiple database instances, with a lookup table that maps a parkingLotId to a different shard. For example, we can have a lookup table that looks like:

{

lot1: database1

lot2: database1

lot3: database2

lot4: database3

}

The database will only store information on the lots that are mapped to it.


If user arrives at the lot, the lot will access the CheckIn Service to check the user into the lot. If the user leaves the lot, the lot will access the CheckIn Service to check the user out of the lot.


Once user parks, the lot will access the Parking Service to mark in the database that the user has parked.


Detailed Component Design


Reservation Service

  • Functionality
    • Handles both reserveParking and getReservations APIs to reserve a parking spot for a user and can also fetch the reservation information so the user can view it at any time. Payment is handled in reserveParking so that payment fails, reservation will also fail. Information will be written to the cache which will write to the database. We will have to check for availability right before marking the spot as reserved to handle race conditions.
    • Tech Choice: Redis, Amazon RDS, Amazon SQS

Parking Service

  • Functionality
    • Handles parkCar and departCar APIs to track when a user has parked their car during their reserved time and when they choose to leave. Information will be written to the cache which will write to the database.
  • Tech Choice: Redis, Amazon RDS

CheckIn Service

  • Functionality
    • Handles when a user has arrived at a parking lot and when they have left the parking lot. Information will be written to the cache which will write to the database.
  • Tech Choice: Redis, Amazon RDS


TradeOffs/Tech Choice:

  • We will be using a write through cache so we do not have to sacrifice performance. If we just use a normal cache, we will potentially be using stale data and users may attempt to reserve or park in the same spot.
  • I have went with a relational database over a nonrelational one because I have chosen to prioritize consistency over speed and scalability. We want our parking lot to always have the correct information, otherwise users may park in the same spot as another user.