System requirements
Functional:
- Supported vehicle types: 2 wheelers ( electric and ICE ), sedan size 4 wheel ( electric and ICE ). 6-8 wheeler bigger trucks ( ICE only )
- Multi-level parking. Each location can have different capacity and level based on proximity. e.g. Urban area and proximity to event location
- Same entry and exit for all types of vehicles.
- Cost estimation is done based on hours of parking.
- System shall be able to cater frequency of 1 million requests / second.
- Users can pre-book parking space upto 1 week before
Non-Functional:
- Uptime: 99.99 %
- Horizontally scalable
- User friendly
- Security: All users data shall be secure
- Response time: <100 ms
- Throughput: 10k req / sec
Capacity estimation
Assuming 1 out of 7 person owns a 4-Wheeler. 1/10th of these would use our service daily: 100 million people.
Data required to store single transaction ~ 100 B
Number of records inserted daily: 100 million * 100 B = 10 GB.
For 1 year = 3TB
Estimating for 10 Years = 30TB
API design
As all of these entries will be modifying db, these cannot be Get calls
- post /park?vn=<vehiclenumber>&type=2&elec=y
- return parking space where vehicle can be paraked
- post /unpark?vn=<vehiclenumber>
- Closes DB entry with after accepting payment
- post /book?vn=<vehiclenumber>&type=2&elec=y
- Reserves a slot for given type
- get /parkspace?type=<x>
- return parking space available for given type of vehicle
Database design
-- Table [ParkingTransactions] --
UniqueId ( uuid )
VehicleNumber ( 20 chars )
InTime ( dateTime )
OutTime ( dateTime )
ElectricConsumption ( number )
SlotAlotted (FK: string)
TransactionId ( FK )
ParkingBuildingId ( FK )
-- Table [ParkingSpace] --
MarkingNumber ( string )
BuildingDeatails
BuildingAdderss
MetaInfo (string)
State ( Enum )
-- Table [Transaction] --
UUID
Details
-- Table [PreBooking] --
CustomerId (FK)
RequestedStartTime ( DateTime )
Transaction ()
-- Table [Customer] --
CustomerId ( PK )
CustomerMetadata
High-level design
Table ParkingTransactions can be sharded based on ParkingBuildingId.
Services:
- CostCalculator
- Calculate cost based on space used and time parked
- Booking
- Prebooking and cancellation
- ParkingService
- finds required space based on
- SlotFinder
- Stores an active list of vacant slots
- PaymentService
- CustomerService
- AuthService
Request flows:
Detailed component design
Each component is horizontal scalable.
Every micro-service has its own database, and no sharing of DB is allowed.
- CostCalculator is a stateless service and hence do not need to access any DB.
- ParkingService is owner for below tables:
- ParkingTransactions
- SlotFinder service is owner for
- ParkingSpace
On Entering the building, vehicle is scanned to number plate and type. Post request is sent to "ParkService".
A distributed transaction is executed between SlotFinder and ParkService to block required slot and make a transaction entry.
Trade offs/Tech choices
Communication between microservice: gRPC
Communication between client and LB: REST
As we are not generating lot of data, SQL DB would be a fine choice.
Cache: Redis can be used.
Failure scenarios/bottlenecks
ParkService fails: Multiple instance will be running and pointing to same DB.
ParkService DB fails: A db replica is kept in sync in case of failover is required.
similar strategy for each service can be followed.
Natural calamity causing hardware failure: DataCenteres are kept in different geographical locations to avoid hardware failure in one continent
Any service fails to respond: exponential backoff while reissuing request.
Future improvements
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?