System requirements


Functional:

  • efficiently manage vehicle entrance, exit and parking allocation
  • should accommodate different types of vehicles (not every parking spot accommodates every car type)
  • prioritize user convenience
  • safe and functional



Non-Functional:

  • scalable
  • available
  • performant
  • consistent
  • secure




Capacity estimation

  • 1000 parking lots in operation
  • 200 cars per parking lot (200k total parking spots)
  • 200 reservations per day (200k total)




API design





Database design

  • parking_lots: id, name (string), total_parking_slots (int)
  • parking_slots: id, parking_lot_id, car_type (enum: compact, suv, van, truck), is_available (bool)
  • user: id, name (string), car_type (enum), email (string), phone_number (string), email_notification_enabled (bool), phone_notification_enabled (bool)


High-level design

  1. Car placement system: Looks at the parking lot information/available slots and the user's car type; assigns a slot for the car or returns false if the car doesn't fit
  2. User data service: Stores user data like car info, user name, etc
  3. Payment service: To start, we will leverage a payment system like Stripe; that way we don't have to store sensitive payment data in our systems
  4. Notification service: Simple service to send email or text notifications to users. To start, we will only send receipts after the user has paid.
  5. Analytics service


client -> car placement service -> user data service-> payment service -> notification service -> analytics service


Note that if we want to maximize availability and scale, we can place queues in between each service. We can use Kafka, for example. Then we can have consumers at each service that process the Kafka messages at the rate the systems allow. This approach will ensure we can scale without problems and will prevent high throughput to take down the system.


Note that the car placement service should be called at entry and exit time.



Request flows

Car entry:

  1. car comes in, makes a request via the api gateway
  2. we rate limit the requests to avoid abuse/performance issues
  3. the car placement service picks up the call, checks the car details and checks if there's space in the given parking lot; sends a kafka message out
  4. user data service picks up the message and checks the user details to make sure everything matches the user records; sends a kafka message out
  5. the payments service receives the message, processes the payment; sends a kafka message
  6. the notification service picks up the message and sends out an alert to the user
  7. the analytics service consumes all kafka messages and stores the data in an elastic search index; can use graphana to display the results and facilitate data analytics


Car exit:

  1. car exits, makes a request via the api gateway
  2. we rate limit the requests to avoid abuse/performance issues
  3. the car placement service picks up the call, checks the car details and marks the parking slot it was using as available; sends a kafka message out
  4. the notification service picks up the message and sends out an alert to the user
  5. the analytics service consumes all kafka messages and stores the data in an elastic search index; can use graphana to display the results and facilitate data analytics




Trade offs/Tech choices

  • since there is not a lot of traffic, i did not include any caching; we could add that if need be
  • opted for a relational db
  • we can use kafka or something more light-weight like celery/redis. the important thing is having a queuing system. i opted for kafka because analytics can be done pretty straightforward with it
  • the notification service can be easily extended by adding more client types





Failure scenarios/bottlenecks

  • addressed by having a rate limiter and queues before each service call
  • we could add retry logic on the payments service that gets triggered depending on the received error




Future improvements

  • adding a camera system to detect cars entering and exiting