My Solution for Design an Efficient Parking Lot System with Score: 8/10

by quasar_nebula605

System requirements


Functional:


  1. The parking system should allow users to book a parking lot.
  2. User pays for the reservation.
  3. User can park a car on the parking spot and User can leave before the reservation time expires.
  4. There are three different parking spots - compact size, standard size, and with electric charger.
  5. If there is no current availability notify them once slots are available.
  6.  Common error case to handle is when a user makes a reservation, but fails to show up. In this case, we would charge for the first 24 hours.




Non-Functional:

  1. Real Time - We will allow users to check availability and book slot in real time, response time not more than a second.
  2. We will have load balancers which will equally distribute requests and will route the requests to only healthy clusters.
  3. Proper alerting system to monitor health checks and immediate actions if certain threshold is breached.
  4. Scalability: We onboard multiple companies having 100+ parking slot across the country.
  5. Proper authentication of users for login and signup.
  6. Consistency: Once a reservation is made, the parking spot must be available for the user. No double-booking should happen that is avoid race condition.


Capacity estimation


  • There is around 20 companies that collaborated with use. Each company has 100 parking lots, on an average.
  • On average, each parking lot has a capacity of 200 cars. 70% standard cars. 20% compact cars. 10% electronic cars with chargers.
  • 80% of users use it for short term parking, averaging 4 hours.
  • 20% of users use it for long term parking, averaging 5 days.
  • For each parking lot, there are on average 50 reservation requests per day.


Estimation:

  • 20 * 100 = 2000 parking lots.
  • For each day, this system will receive 100,000 reservation requests per day.
  • Each reservation would mainly consists of:
    • User ID (50 bytes)
    • Car type (10 byte)
    • Reservation start time (8 byte)
    • Reservation end time (8 byte)
    • Roughly totaling 76 ~ 80 bytes.

Daily total = 100,000 × 80 bytes = 8,000,000 bytes/day= ≈ 7.8 MB/day

In 1 year : 2.78 GB




API design

  1. Sign_up / login_page : API to register user if not present (phoneNumber, email-id)
  2. reserve_slot (user_id, lot_id, start_time, end_time, car_type, additional_service)
  3. Checking availability: (lot_id, vehicle_type,

start_time, end_time )

4. pay(reservation_id, user_id)

5. API used at gate checkin service

vehicle_arrived(reservation_ID, user_id, date_time)

vehicle_left(reservation_ID, user_id, date_time)






Database design

UserProfile Entity


CREATE TABLE user_profile (

'user_id' string primary key,

'email_id' string,

'phone_number' string,

'active' boolean,

'address' varchar(255),

)


CREATE TABLE lot (

'lot_id' string primary key,

'available' string,

'lot_capacity' string,

)


CREATE TABLE transaction (

'transaction_ID' string primary key,

'user_ID' string,

'reservation_id' string,

)





High-level design


  1. Use CDN - Caches static content (e.g : images, CSS, JS files, parking lot maps)
    • Reduces load on app servers and database.
    • Delivers static content faster by serving it from edge locations close to users.
    • Improves response times and overall user experience.
  • In the parking lot system:
  • Users might frequently load maps, parking lot layouts, or branding assets that don’t change often.


2. Rate Limiter

Purpose: Protects the system from abuse (e.g., DDoS attacks, bot overuse)

  • Why?
    • Prevents any user/IP from overwhelming the system with requests.
    • Helps maintain system availability and performance for legitimate users.
  • In the parking lot system:
  • Prevents scenarios like automated bots trying to reserve all spots or users spamming requests.


3. Ensures no single server is overwhelmed.

Improves fault tolerance and allows horizontal scaling.

Using weighted round robin allows prioritizing servers based on capacity.


4. Ensures no single server is overwhelmed.

Improves fault tolerance and allows horizontal scaling.

Using weighted round robin allows prioritizing servers based on capacity.


Clients make a request, request is routed from APP to API gateway which then sends it it load balancer from where request is routed to servers.




Request flows


check_capacity() is handled by Reservation Server consulting the data in the database.


reserve_spot() is handled by Reservation Server, which creates a new entry in Reservations table.

It would create a request for payment, which is queued by Message Queue and submitted to the external Payment System.


reserve_spot() may fail if multiple users are trying to book the same spot. Return an error and ask the client to try calling reserve_spot() again.


It would also fail if the lot is full. In that case, the client should not retry. Reservation Server may return helpful information such as estimated time spots may open up in the future.


vehicle_arrived() and vehicle_left() are handled by Transaction Server, which modifies the Transaction table to keep track of vehicle checkins and checkouts.


If vehicle does not arrive after some number of hours (e.g. 24 hours), reservation would be canceled. The user would be charged for 1 day of payment.


If inconsistent state happens, e.g., vehicle_left() is called before corresponding vehicle_arrived(), administrator at the lot should be notified. The service would assume the vehicle arrived around the corresponding reservation start time.



Detailed component design


For handling multiple request we can do scaling like adding more servers, increasing RAM size.

Tech Stacks: Java, Dropwizard, Maria DB, Aerospike, Caffeine, Singleton, Indexing.




Trade offs/Tech choices

The system is expected to store ~2.78 GB of data over 1 year, which is very manageable for any modern relational database (like PostgreSQL or MySQL).

Strong Consistency:

RDBs follow ACID (Atomicity, Consistency, Isolation, Durability) principles, ensuring that:

  • Each reservation is either fully saved or not at all.
  • No user gets a double-booked spot.
  • Data is reliable and accurate, which is critical when users are trusting the system with reservations.

Structured Schema:

Parking reservations have clearly defined relationships:

  • Users → Reservations
  • Reservations → Parking lots and time slots
  • An RDB is ideal for modeling and querying this structured, relational data efficiently.

Why Not NoSQL (e.g., MongoDB)?

  • NoSQL databases like MongoDB excel at:
    • Handling very large-scale, unstructured, or semi-structured data
    • Horizontal scalability (adding more machines to handle more data)
  • But in this case:
    • The system does not need massive horizontal scaling — traffic and data volume are predictable and moderate.
    • NoSQL databases typically sacrifice strong consistency for performance or scalability (CAP theorem). This increases the risk of eventual inconsistencies like double bookings or outdated reservation states, which are unacceptable for this use case.





Failure scenarios/bottlenecks



  1. Description: This can occur due to hardware failures, software bugs, or external service outages.

Prevention:

    1. Implement redundant servers and services to ensure the system can handle failures gracefully.
    2. Use monitoring tools to detect issues early, coupled with alerting systems for quick response.
    3. Schedule regular patching, updates, and system health checks.



2. Description: The system could struggle under heavy traffic like in case of concerts, cricket matches, leading to slow performance or downtime.

This would put a burden on the reservation work flow (reserve_spot(), pay()). Transaction Server would be fine, as the number of requests to Transaction Server would be limited by the physical limitation of the parking lots (i.e. how many spots they have).


To prepare for such an event, all the software components must be replicated horizontally to have enough capacity. Rate Limits have to be configured to smooth out extreme level of traffic.


The database tables must be replicated in multiple ways (e.g. a copy within data center, a copy in another data center, a copy in a different region) for fault tolerance and disaster recovery.

  • Prevention:
    • Load Balancing: Use load balancers to distribute traffic among multiple servers, preventing any one server from becoming a bottleneck.

Backup and Data Recovery:

  • Description: Loss of data due to system crashes, database corruption, or cyber-attacks.
  • Strategies:
    • Regular Backups: Schedule frequent backups of databases and critical system state to prevent data loss.
  • Geographic Redundancy: Store backups in multiple locations or data centers to safeguard against regional failures.
  • Automated Recovery: Implement automated recovery procedures to restore service quickly in case of failure.









Future improvements

  • Load Balancer: Distributes incoming traffic across multiple servers, enhancing load management.
  • Auto-Scaling Group: Automatically adjusts the number of active servers based on traffic conditions.
  • Cache (Redis): Reduces database load and improves response times by caching frequent queries.
  • Backup Service: Regularly creates backups of crucial data, stored in geographically redundant locations.
  • Monitoring & Alerts: Actively monitors server health and performance metrics, triggering alerts on anomalies.
  • Optimizations and availability improvement based on geographic locations would be a good area to invest further. For example, using Global Load Balancer so that clients get routed to the closest data center. Replicating databases between different geographic locations as a back up mechanism in case of a regional disaster.