Uber Clone Example
Deep dive into modeling a ride-hailing system (Uber-like) using Domain-Driven Design, Event Storming, CQRS, and Event Sourcing. No JavaScript; semantic HTML only.
Overview
Model a ride-hailing platform with Riders, Drivers, Trips, Vehicles, and Payments. The goal is to show a complete lifecycle from ride request to payment, with domain-driven boundaries and event-sourced history.
Domain Model
- Aggregates: Ride
- Entities: Rider, Driver (with Vehicle), Ride, Payment
- Value Objects: Location, GeoPoint, Fare, Currency
- Domain Events: RideRequested, DriverAssigned, RideStarted, RideEnded, RideCancelled, PaymentProcessed
Commands
- RequestRide
- AcceptRide
- StartRide
- EndRide
- CancelRide
- UpdateLocation
- ProcessPayment
Domain Events
- RideRequested
- DriverAssigned
- RideStarted
- RideEnded
- RideCancelled
- PaymentProcessed
Aggregates & Rules
Ride is the aggregate boundary. It enforces business rules like driver availability, surge pricing, ETA calculations, and safety checks (e.g., rider must be within service area, driver must be online).
Read Models & Projections
- RideDetails
- DriverAvailability
- RideHistory
- RevenuePerCity
Policies & Business Rules
- SurgePricingPolicy: increase fare during demand spikes.
- CancellationPolicy: time-based penalties and refunds.
- DriverAcceptancePolicy: ensure driver can accept within allowed window.
- RoutingPolicy: optimize ETA with real-time traffic data.
Integrations
- Maps/Geocoding: pickup/dropoff coordinates
- Routing: compute optimal routes
- PaymentGateway: process fare
- Notifications: push/SMS updates
Lifecycle Walkthrough
- Rider requests a ride (RequestRide).
- System matches with a nearby Driver (DriverAssigned).
- Driver starts the ride (RideStarted); location updates stream in.
- Ride ends at destination (RideEnded); fare calculated (Fare, PaymentProcessed).
- Ride history is stored and read models updated.
Sample Payloads
RideRequested payload example (conceptual JSON):
{
"rideId": "ride_12345",
"riderId": "rider_9876",
"pickup": { "lat": 37.7749, "lng": -122.4194 },
"dropoff": { "lat": 37.8044, "lng": -122.2711 },
"requestedAt": "2026-04-30T12:34:56Z"
}
Diagram & Illustration
Data & APIs (Conceptual)
Provide data contracts for core ride flows. All payloads shown are conceptual and for modeling only.
- RideRequest: riderId, pickup, dropoff, requestedAt
- RideAssignment: rideId, driverId, estimatedEta
- RideUpdate: rideId, location, status
- PaymentIntent: rideId, amount, currency, method
Example payload (RideRequest):
{
"rideId": "ride_9876",
"riderId": "rider_1122",
"pickup": {"lat": 37.7749, "lng": -122.4194},
"dropoff": {"lat": 37.8715, "lng": -122.2730},
"requestedAt": "2026-04-30T12:34:56Z"
}
Edge Cases
- Driver unavailability during surge; rescheduling.
- Rider cancels after a driver is assigned; cancellation fee rules.
- Multi-city trips; regional pricing considerations.
Testing & Validation (Conceptual)
- Event history verifications: ensure all domain events are emitted in order.
- Read model projections reflect event stream accurately.
- Policy gate checks (surge, cancellation) are enforced before command execution.