A ride-hailing platform built as an engineering journal — learning from Uber's mistakes, one module at a time.
Overview • Philosophy • Architecture • Phases • Tech Stack • Getting Started • Documentation • Contributing
Driverless is a full-stack ride-hailing platform that replicates the core functionality of Uber while systematically addressing the documented failures, design shortcomings, and engineering challenges the ride-hailing industry has faced over the past decade.
This isn't just a clone — it's an engineering case study. Every module ships with:
- 📖 A Case Study — what went wrong at Uber (and why)
- 🛠️ An Approach — how we solve it differently (or adopt what worked)
- ✅ A Justification — why our solution works, with references and trade-off analysis
The platform comprises three client applications and a backend:
| Component | Description |
|---|---|
| Rider App | Request rides, track drivers, make payments, rate experiences |
| Driver App | Accept rides, navigate, manage earnings, control availability |
| Admin Dashboard | Operations management, analytics, compliance, dispute resolution |
| Backend Platform | REST APIs, real-time WebSocket services, background workers, fraud detection |
This project is not just an implementation — it is a demonstration of:
• Designing real-time distributed systems • Handling high-frequency geospatial data (location streaming) • Building marketplace systems (supply-demand matching) • Applying event-driven architecture in production scenarios • Making explicit engineering trade-offs under real-world constraints
Driverless focuses on solving the hardest problems in ride-hailing systems:
• Efficient driver-rider matching at scale • Real-time location tracking with minimal write amplification • Handling race conditions in distributed dispatch systems • Designing fair and transparent dynamic pricing • Preventing fraud and abuse in marketplace systems • Maintaining system reliability under high concurrency
The ride-hailing industry has produced some of the most interesting engineering challenges of the past decade — real-time systems at massive scale, marketplace economics, safety-critical software, and regulatory compliance across jurisdictions. But many of these lessons live scattered across blog posts, conference talks, and post-mortems.
Driverless consolidates those lessons into a single, buildable codebase where every architectural decision is documented and justified.
| Principle | What It Means |
|---|---|
| 🏗️ Modular Monolith | Start as one deployable unit with strict module boundaries; split only when metrics demand it |
| 🧅 Clean Architecture | Domain logic has zero external dependencies; all I/O flows through ports and adapters |
| 📡 Event-Driven | Modules communicate via domain events — decoupled, auditable, replayable |
| 💥 Design for Failure | Every external call has a circuit breaker, retry policy, and fallback path |
| 🔒 Privacy by Design | Data minimization, purpose limitation, and consent are architectural concerns, not afterthoughts |
| 👁️ Observability First | Structured logging, correlation IDs, and Prometheus metrics from day one |
| 📓 Journal-Style Documentation | Every module has a case study — we don't just build, we document why |
Driverless follows Clean Architecture within a modular monolith, with a clear evolution path to microservices:
┌──────────────────────────────────────┐
│ CLIENT LAYER │
│ Rider App │ Driver App │ Admin Panel │
└─────────────────┬────────────────────┘
│
┌─────────────────▼────────────────────┐
│ API GATEWAY │
│ Auth │ Rate Limiting │ Routing │
└─────────────────┬────────────────────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌────────────────────┐ ┌───────────────────┐
│ Core Services │ │ Real-Time Layer │ │ Background Workers│
│ (REST API) │ │ (WebSocket) │ │ (Queue-based) │
└────────┬─────────┘ └────────┬───────────┘ └────────┬──────────┘
│ │ │
┌────────▼─────────────────────▼───────────────────────▼──────────┐
│ DATA & INFRASTRUCTURE │
│ PostgreSQL + PostGIS │ Redis │ RabbitMQ │ S3/MinIO │
└─────────────────────────────────────────────────────────────────┘
Every feature module follows the same four-layer structure:
src/modules/<module-name>/
├── domain/ # 🟢 Business logic (zero external deps)
│ ├── entities/ # Core business objects
│ ├── value-objects/ # Immutable typed values
│ ├── events/ # Domain events
│ └── enums/ # Domain enumerations
├── application/ # 🔵 Use cases & orchestration
│ ├── use-cases/ # Business operations
│ ├── dtos/ # Input/output contracts
│ └── ports/ # Abstract interfaces (dependency inversion)
├── infrastructure/ # 🟠 External concerns
│ ├── repositories/ # Database implementations
│ ├── adapters/ # 3rd-party service integrations
│ └── mappers/ # Entity ↔ Schema transformations
├── presentation/ # 🟣 HTTP/WebSocket layer
│ └── controllers/ # REST endpoints & WS gateways
├── <module>.module.ts # NestJS module definition
└── CASE_STUDY.md # 📓 Engineering journal entry
Dependency rule: outer layers depend on inner layers, never the reverse. The domain layer is pure TypeScript with no framework imports.
A simplified flow of a ride request:
Rider → API Gateway → Ride Service ↓ Matching Service → Redis (Geo Index) ↓ Driver Selection → WebSocket Notification ↓ Ride Confirmation → Real-Time Tracking
• Geo-spatial indexing using H3 instead of naive distance calculations • Redis for high-frequency location updates instead of PostgreSQL • Event-driven communication via RabbitMQ to decouple services • Modular monolith to balance simplicity and scalability
The build is broken into 6 progressive phases, each adding capabilities and shipping with full documentation.
| Module | Uber Problem Addressed |
|---|---|
| User Management | Monolith scaling pain & 57M-record data breach (2016) |
| Authentication & Authorization | Account takeover attacks via credential stuffing |
| Driver Onboarding & Verification | Inadequate background checks, impersonation incidents |
| Profile & Data Privacy | GDPR violations — €290M fine for illegal data transfers |
| Module | Uber Problem Addressed |
|---|---|
| GPS Tracking & Streaming | Write amplification from storing every GPS update to primary DB |
| Geospatial Indexing (H3) | O(n) nearest-driver queries → O(1) with hexagonal cells |
| ETA Calculation | Straight-line distance estimates destroying rider trust |
| Map & Routing | Unsafe route suggestions contributing to accidents |
| Module | Uber Problem Addressed |
|---|---|
| Ride Request Lifecycle | Race conditions: multiple drivers dispatched to one rider |
| Matching Algorithm | "Closest driver" failing in complex urban environments |
| Batched Matching | Greedy one-at-a-time matching vs. global optimization |
| Supply Prediction | Reactive surge vs. proactive driver repositioning |
| Module | Uber Problem Addressed |
|---|---|
| Dynamic Pricing | Surge pricing opacity (8.8x during Hurricane Sandy) |
| Fare Estimation | Unpredictable final fares eroding trust |
| Payment Processing | Scaling from card-only to cash, mobile money, wallets |
| Driver Earnings | Opaque commission structures driving driver churn |
| Promotions & Incentives | Multi-million dollar promotion abuse by fraud rings |
| Module | Uber Problem Addressed |
|---|---|
| In-Ride Safety | No proactive anomaly detection during trips |
| Identity Verification | Driver impersonation bypassing weak checks |
| Fraud Detection (RADAR) | Adversarial fraud evolving faster than static rules |
| Rating System | One-sided, gameable ratings without accountability |
| Dispute Resolution | Manual dispute handling that can't scale |
| Module | Uber Problem Addressed |
|---|---|
| Notification System | Multi-channel delivery failures and missed alerts |
| Regulatory Compliance Engine | Hardcoded rules breaking across jurisdictions |
| Observability & Monitoring | Silent outages discovered via social media complaints |
| Admin Panel | Monolithic admin without role-based access |
| Disaster Recovery | Cascading failures in distributed systems |
| Technology | Version | Role |
|---|---|---|
| Node.js | 20 LTS | Runtime |
| NestJS | 11 | Backend framework |
| TypeScript | 5.7 | Language |
| TypeORM | Latest | ORM with migrations |
| PostgreSQL | 16 | Primary database |
| PostGIS | 3.4 | Geospatial queries |
| Redis | 7 | Cache, sessions, real-time location store |
| RabbitMQ | 3.12 | Message broker for domain events |
| Socket.IO | 4 | Real-time WebSocket communication |
| Uber H3 | Latest | Hexagonal geospatial indexing |
| Tool | Purpose |
|---|---|
| Docker + Docker Compose | Local development environment |
| GitHub Actions | CI/CD pipeline |
| Jest + Supertest | Unit, integration, and E2E testing |
| k6 | Load and performance testing |
| Swagger / OpenAPI 3.0 | Auto-generated API documentation |
| Prometheus + Grafana | Metrics and dashboarding |
| Pino | Structured JSON logging |
| ESLint + Prettier | Code quality and formatting |
- Node.js ≥ 20.0.0
- Yarn (package manager)
- Docker & Docker Compose (for infrastructure services)
# Clone the repository
git clone https://github.com/kellendia/driverless.git
cd driverless
# Install dependencies
yarn install# Start PostgreSQL, Redis, RabbitMQ, and MinIO
docker compose up -d# Development (watch mode)
yarn start:dev
# Production build
yarn build
yarn start:prod# Unit tests
yarn test
# Watch mode
yarn test:watch
# E2E tests
yarn test:e2e
# Coverage report
yarn test:cov# Lint and auto-fix
yarn lint
# Format code
yarn formatAll project documentation lives in the docs/ directory:
| Document | Description |
|---|---|
| SRD.md | Software Requirements Document — 100+ functional requirements, user stories, non-functional requirements |
| TDD.md | Technical Design Document — system architecture, data models, API design, security, observability |
| Case Studies | Index of 25+ engineering case studies, one per module |
Each module's CASE_STUDY.md follows this structure:
- What Happened at Uber — the specific failure or challenge
- Impact — user trust, revenue, legal consequences
- Root Cause — technical or organizational
- Our Approach — how Driverless solves it
- Why It Works — references and industry best practices
- Trade-offs — what we sacrifice and why it's acceptable
driverless/
├── docs/ # 📚 Project documentation
│ ├── SRD.md # Software Requirements Document
│ ├── TDD.md # Technical Design Document
│ └── case-studies/ # Engineering case studies
│ └── README.md # Case study index
├── src/
│ ├── main.ts # Application entry point
│ ├── app.module.ts # Root module
│ ├── common/ # Shared kernel (decorators, guards, pipes, etc.)
│ ├── config/ # Configuration module
│ └── modules/ # Feature modules
│ ├── user/ # Phase 1 — User Management
│ ├── auth/ # Phase 1 — Authentication
│ ├── driver/ # Phase 1 — Driver Onboarding
│ ├── location/ # Phase 2 — Geospatial Services
│ ├── ride/ # Phase 3 — Ride Lifecycle
│ ├── matching/ # Phase 3 — Matching Engine
│ ├── pricing/ # Phase 4 — Dynamic Pricing
│ ├── payment/ # Phase 4 — Payments
│ ├── safety/ # Phase 5 — Safety Features
│ ├── fraud/ # Phase 5 — Fraud Detection
│ ├── notification/ # Phase 6 — Notifications
│ └── compliance/ # Phase 6 — Regulatory Compliance
├── test/ # E2E tests
├── docker-compose.yml # Local infrastructure
├── package.json
├── tsconfig.json
└── README.md # ← You are here
Where should driver location updates be stored?
- Store in PostgreSQL
- Store in Redis
- Hybrid approach
Use Redis for real-time location tracking.
• high write throughput • low latency reads • ephemeral data fits Redis model
• data not persisted long-term • requires fallback persistence strategy
Real-time systems require prioritizing latency over durability for certain data paths.
If Driverless were to scale to millions of users:
• split matching service into dedicated microservice • introduce regional sharding for location data • use Kafka instead of RabbitMQ for high-throughput streaming • implement read replicas for PostgreSQL • introduce edge caching for frequently accessed data
This project is designed with a clear path from modular monolith to distributed system.
The platform exposes a RESTful API with Swagger documentation available at /api/docs when running locally.
| Area | Base Path | Highlights |
|---|---|---|
| Auth | /api/v1/auth |
Register, login, OTP, MFA, token refresh |
| Users | /api/v1/users |
Profile management, data export (GDPR) |
| Drivers | /api/v1/drivers |
Application, documents, online/offline toggle |
| Rides | /api/v1/rides |
Fare estimate, request, cancel, rate, history |
| Payments | /api/v1/payments |
Payment methods, earnings, payouts |
| Admin | /api/v1/admin |
User search, driver verification, operations |
| Event | Direction | Purpose |
|---|---|---|
driver:location:update |
Driver → Server | GPS coordinate streaming |
ride:offer |
Server → Driver | New ride request notification |
ride:matched |
Server → Rider | Driver assignment with ETA |
ride:driver:location |
Server → Rider | Live driver tracking |
safety:check |
Server → Rider | Automated "Are you OK?" prompt |
Full event catalog is documented in the TDD.
| Metric | Target |
|---|---|
| API response time (p95) | < 200ms |
| WebSocket latency | < 100ms |
| Ride matching time (median) | < 10 seconds |
| Core service uptime | 99.95% |
| Safety services uptime | 99.99% |
| Concurrent active drivers | 100,000+ |
| Location updates/second | 25,000+ |
This is an engineering case study project by Kellendia Engineering. Contributions are welcome for:
- 🐛 Bug fixes and improvements
- 📖 Case study refinements and additional research
- 🧪 Test coverage improvements
- 📐 Architecture suggestions
- Create a feature branch from
main - Follow the Clean Architecture module structure
- Include or update the relevant
CASE_STUDY.md - Ensure all tests pass (
yarn test) - Submit a pull request with a clear description
- TypeScript strict mode enabled
- ESLint + Prettier enforced (run
yarn lintbefore committing) - Conventional Commits for commit messages
This project is UNLICENSED — proprietary to Kellendia Engineering.
Built with ❤️ by Kellendia Engineering — learning from the giants' mistakes so we don't have to repeat them.