MVP:
Functional Requirements:
Questions: Capacity Estimation how many users are we accommodating?
A Booking System requires strong consistency and ACID (Atomicity, Consistency, Isolation, Durability) guarantees to prevent double-booking or race conditions. Built-in constraints help enforce data integrity, ideal for conflict resolution (double bookings), mature support for joins, transactions, complex queries.
Therefore for the primary booking system a Relation DB will be used like SQL Server or PostgresSQL.
Public User-Facing APIs:
Private APIs:
PaymentAPI
NotificationsAPI:
AnalyticsAPI
Car Park API - Gate Checking Service:
System Notes:
Used a Message Queue Kafka is used to decouple services for durable event queues.
Events are persisted for replay to support failure recovery and system observability.
User
ParkingLot
ParkingSpace
Booking
Payment
EventLog (for analytics/debugging)
The system uses a read-optimised, write-consistent architecture with event-driven architecture for processing asynchronous operations.
Client sends a request, which is communicate through the Load Balancer(s)/API Gateway, which is sent to BookingAPI.
BookingAPI optimises READs via a WRITE-THROUGH Cache this to keep the cache updated with the Database for strong consistency and durability at a trade-off of latency on WRITEs. BookingAPI WRITEs new bookings to the DB layer and produces "booking_created" topic to Kafka.
Kafka Message Queue
Data Layer
Message Queue (Kafka):
High-Level System Design Diagram:
The system follows as read-optimised, write-consistent and even-driven architecture.
BookingAPI
Kafka
Cache Layer (Redis)
Each component is designed for horizontal scaling, consistency, and resilience. Let me know if you’d like a component diagram or call flow.
Kafka
Chosen for asynchronous, decoupled communication between services.
Trade-off: Adds operational complexity (managing brokers, partitions, message retention), but enables scalability, failure isolation, and event replay.
Preferred over direct API calls or synchronous flows to prevent cascading failures, allowing for a separation of concerns and circuit-breaking pattern. Supports extensibility (e.g., plugging in new consumers like AnalyticsAPI).
Relational DB (e.g., Postgres)
Selected for strong consistency, ACID guarantees, and mature support for constraints and transactions—essential for preventing double bookings.
Trade-off: May require sharding or replication strategies at scale versus simpler horizontal scaling in NoSQL.
Chosen over NoSQL for its ability to handle complex queries, enforce data integrity, and support joins (e.g., booking + payment history).
Try to discuss as many failure scenarios/bottlenecks as possible.
1. BookingAPI Failure
If BookingAPI crashes after writing to DB but before publishing to Kafka, downstream services won’t be triggered.
Mitigation: Kafka’s exactly-once semantics to ensure atomic DB write and event publish.
Kafka Broker Outage
If Kafka is unavailable, services can’t produce or consume events.
Mitigation: Kafka replication and quorum-based writes ensure durability. Events can be replayed once brokers recover.
PaymentsAPI or Stripe Downtime
If PaymentsAPI fails or Stripe is unresponsive, booking remains unpaid.
Mitigation: Retry with exponential backoff, use webhook retry mechanisms, and persist payment state for replay.
Notification Failures
If NotificationsAPI fails, users may not receive confirmations.
Mitigation: Use dead-letter queues to retain troublesome erroring notification for later retries, retries, and monitor failed delivery metrics.
Database Bottleneck
Write-heavy traffic (e.g., during events) may overwhelm the primary DB.
Mitigation: Add read replicas, optimize indices, and consider partitioning or sharding if needed.
Kafka Replay
Kafka retains messages, allowing replay by consumers to recover from service failures or data loss—critical for PaymentsAPI, AnalyticsAPI, and NotificationsAPI reliability.
The system above provides a solid, scalable and event-driven implementation for a Parking System.
Future improvements:
Add CDN - Introduce a Content Delivery Network (e.g., Cloudflare) to cache static assets like images, scripts, and style sheets. This reduces load on backend servers and improves latency for users globally, it adds an additional logging layer to aid debugging issues.
Add a Logging layer to catch errors - Use Splunk or Sentry to capture info, debug, error logs.
Additional enhancements could include: