System requirements


Functional:

Types of vehicles

Number of floors and parking spots

Near real-time update on Available parking spots when the vehicle entry / exit.

Calculating the fees depends on the vehicle type, start_time and end_time when they book / exit the parking lot.

Users should be able to see and book the parking spots via Mobile app and Website?



Non-Functional:

Consistency >> High Availability

Low Latency

Security - Payments

Observability - Logging, Monitoring and Notification alerts



Capacity estimation

100000 users in a month

4 requests per second




API design

GET - /v1/parking/listavailabileslots?vehicletype='car' {floor, availablespots, amountforanhour} For example: Level 1 , 10 available spots.

POST - v1/parking/bookingspot {user_id, floor_number, selected_spot, start_time, end_time, created_at, paymentdetails, amount} response : {200, booking_id, floor_number}

PUT - /v1/parking/updatebooking {user_id, floor_number, selected_spot, start_time, end_time, created_at, amount}

DELETE - /v1/parking/deletebooking {user_id, booking_id}




Database design

VehicleTypes -> vehicletypeid, vehicletype

Users -> userid, username, emailid, contactnumber

ParkingLot -> parkinglotid, floorid, spotid, minimumamount

bookinginformation -> userid,vehicletypeid,parkinglotid,start_time, end_time,created_at,updated_at,amount, isPaid





High-level design

  • Client sends HTTP requests to interact with the parking lot system.
  • Load Balancer receives these requests and routes them to different instances of the API Gateway to manage traffic and ensure reliability.
  • API Gateway handles the authentication and applies rate limiting to secure and control the flow of requests. Once authenticated, requests are forwarded to the respective Microservice.
  • Microservice processes the request. This could involve creating, reading, updating, or deleting bookings. Microservice can read the data from Redis cache to avoid the database roundtrip for available slots. Cache would be refreshed every 5 minutes. if there is a cache miss, then it should read from the database follower.
  • Database holds all the necessary tables for vehicle types, users, parking lots, and booking information. The Microservice performs SQL queries to interact with this data.
  • The Database returns the data requested, and the Microservice processes it to send it back to the Client as a response. Database would have leader-follower strategy to improve the performance for read (follower) and write (leader).







Request flows

Users sends the request to get the list of available slots for the specific vehicle type.

User sends the request with vehicle type, date, start_time, end_time, selected level and slot, payment details, amount for the duration.




Detailed component design

Consistency - To avoid the same parking spot is booked for multiple people. We can check whether one of the parking spot can be moved to another one.

We should go with Strong Consistency, so that it would avoid the conflict. Relational database would be good here.

Scalability - We can go with leader - follower pattern. One write with multiple replicas for read. So, this way people who are checking the list of available spots would be easier. Alternatively, we can introduce caching to keep the available spot details. We could use Redis cache with eviction policies of Time-to-live for 5 minutes. So, every 5 minutes, the data get refreshed in the cache. It improves the read performance.




Trade offs/Tech choices

API would be asynchronous calls. Alternatively, we put in the message queue which can process the data parallel and update the customers quickly. It's not a heavy load, so it should be quick enough to process the payment information and booking confirmation. I would prefer go with REST API's, Relational Database such as PostgreSQL, Redis cache and Kafka for message queues.




Failure scenarios/bottlenecks

If there are multiple requests and if one of the node is not responding, the other node would process this request in the service layer. Similarly, in the database side if the leader fails to process the request, one of the follower would be promoted as leader. If one of the follower fails, then the request goes to the other follower. These are the fault-tolerant options we have in each layer.




Future improvements

Have a monitoring system in place as part of observability to monitor the service and database nodes, if there is any failure, we should notification alert in place to notify us. Also, we should have logging or audit in place to check the service health.