Building a Ride-Hailing Platform to Rival Uber and Ola — All by Hand
At the peak of the Uber-vs-Ola war in India, a regional taxi operator needed more than a dispatch app — they needed a full platform: real-time booking, driver apps, passenger apps, a CRM for call-centre agents, fleet management dashboards, corporate billing, and a reporting engine that could tell them which driver performed best on a Tuesday night.
No AI tools. No LLMs generating boilerplate. No Copilot suggesting the next line. Just engineers who understood the domain deeply enough to model it correctly the first time.
[!NOTE] For the complete architectural diagrams, database schemas, and deep dive code snippets, check out the Full Utoo Cabs Case Study.
The Scale of the Problem
India’s cab market is unforgiving. Passengers expect sub-minute response times. Drivers need clear earnings breakdowns. Operators manage fleets of hundreds of vehicles across multiple cities. Regulators mandate Aadhaar-based KYC. Payment methods range from Paytm wallets to corporate credit accounts.
A single “booking” is actually a coordinated state machine touching:
- A passenger app requesting a ride
- A driver app accepting it
- A CRM agent who may have manually booked it
- A fare engine calculating the real-time bill
- A payment gateway processing the collection
- A reporting pipeline aggregating the trip data
Building this without scaffolding from AI is a statement about engineering craft.
What Was Built
Platform at a Glance
| Dimension | Count |
|---|---|
| Ruby source files | 690+ |
| Lines of Ruby code | 12,000+ |
| Data models | 87 |
| API controllers | 39 |
| Background workers | 24 |
| External service integrations | 8 |
| User roles | 8 |
| MongoDB databases | 3 |
| Report types | 15+ |
The Full Ecosystem
- Passenger-facing: Registration, ride booking (instant + scheduled), real-time driver tracking, promo codes, wallet, ride history, referral program.
- Driver-facing: Profile, KYC verification, document management, shift-based scheduling, earnings, ratings.
- Fleet operations: Yard check-in/check-out, fuel logging, insurance/RC expiry tracking, driver-to-vehicle assignment history.
- Corporate accounts: Pre-negotiated rates, credit accounts, multi-user corporate portals, monthly billing.
- Admin & CRM: Multi-region booking management, live driver map, demand/supply heatmap, bulk promo uploads, configurable cancellation policies.
- Reporting: 15+ report types with Excel export, email delivery, and time-slice analytics (morning / afternoon / evening / night performance breakdowns).
Ride Booking State & Flow
Here is how the 8-state ride lifecycle handles booking coordination, fare calculation, and the post-trip worker pipeline.
The Broader Platform Ecosystem
The booking and fleet management system documented here is the operational core — but Utoo was built as a full platform ecosystem, with several companion systems serving different stakeholders:
- Driver Management System (DMS): A dedicated system for the full driver lifecycle beyond onboarding: compliance tracking, document renewal pipelines, performance history, and engagement tooling for fleet managers. Separating DMS from the core booking system keeps driver operations manageable without cluttering the booking path.
- Real World Simulator: The most technically ambitious companion system. It introduces bot drivers and bot passengers into the platform to model wait times, travel patterns, and supply-demand dynamics — without deploying real people. The simulator lets operators understand how a new city, new vehicle class, or new pricing tier will behave before launch. It learns from historical trip patterns to generate realistic synthetic load.
- Realtime Fleet Monitoring — WAR Room: A live command-centre display for operations managers: real-time vehicle positions, booking statuses, SLA alerts, incident flags, and fleet-health KPIs — all on a single large-format display. Built for a room of dispatchers who need to act on live events, not pull reports. The WAR Room view is a push-first, not poll-first, interface.
- Stats & Analytics App (Investor / Owner): A business intelligence layer for owners and investors. City-by-city revenue, fleet utilisation, growth trends, and driver supply metrics — separated from the ops CRM so executives see the right lens without exposure to ground-level booking data. Designed for weekly and monthly review cadences.
- Corporate Portal: A self-service interface for hotels, companies, and institutional clients. Corporate admins can schedule rides, manage employee travel accounts, set booking policies, and track monthly billing — without routing every request through a call centre. Direct integration with the corporate billing engine in the core platform.
These systems are built on a complementary stack — Rails, Python, Angular, and native iOS/Android apps — sharing the same underlying data infrastructure as the core booking platform.
The Engineering
Three Databases, One Coherent System
The most quietly impressive architectural decision: three separate MongoDB instances, each handling a different traffic pattern.
taximongo → operational data (drivers, passengers, taxis, fares, promos)
atlas → booking records (high-write booking lifecycle)
tracker → real-time location updates (highest-frequency writes)
Separating location tracking from booking data was not a “nice to have” — at scale, location pings arrive every few seconds from hundreds of driver apps. Mixing them with operational queries would have killed read performance on the booking list. This separation was reasoned from first principles, not a framework default.
Core Domain Entity Map
The core data entities and their relational mappings:
A Fare Engine with Real Complexity
Fare calculation in ride-hailing sounds simple until you’ve actually modelled it:
# BookingInvoice worker — invoice breakdown per trip
invoice = {
base_charge: flat fee per motor model (Compact vs. Sedan vs. SUV)
distance_fare: per-km rate × distance, with minimum km threshold
time_fare: per-minute rate × duration
additional_fare: surge / manual override
discount: promo code deduction (flat or percentage, with cap)
tax: regional GST configuration (percentage of subtotal)
wallet_deduction: passenger wallet credit offset
total_invoice: rounded to nearest rupee
}
Each variable is configurable per motor model, per sub-region. A Compact car in Zone A of Mumbai can have a different per-km rate than the same model in Zone B. Night surcharges activate at configurable times. Waiting charges kick in after a threshold. This was written without any pricing library — the logic lives in the models.
Geographic Segmentation at Depth
The platform supports city-level regions subdivided into polygon-bounded sub-regions. This is not simple lat/lng tagging — it’s full geofencing:
- Sub-regions store polygon coordinate arrays defining zone boundaries
- Fare tables bind to
(sub_region, motor_model)tuples - Demand/supply analysis is calculated per sub-region per vehicle class
- The CRM booking form auto-resolves the correct fare tier from pickup coordinates
All of this was hand-written before geospatial libraries became commodity features.
Background Jobs as a First-Class Architecture Choice
24 Sidekiq workers. Not as an afterthought — as the primary mechanism for anything that can’t block a web request:
| Worker | Purpose |
|---|---|
BookingInvoice | Generate and send PDF invoice after trip close |
DriverPerformance | Crunch multi-day driver analytics into Excel |
PromoCreation | Parse bulk CSV, create per-passenger offers, trigger SMS |
MigrateDriver / MigratePassenger | Safely migrate legacy system data |
SendSms / SendEmail | Async notification delivery |
ReportGeneration | Full report pipeline with file attachment and email |
Queue design is intentional: critical queue (rate 10/s) for booking-path operations, default for standard jobs, product_detail (rate 2/s) for bulk/batch tasks. Concurrency scales from 5 (dev) to 20 (production).
Bulk Promo Distribution at Scale
Marketing needs to run a promo for 50,000 passengers? Upload a CSV of phone numbers. The PromoCreation worker:
- Reads the CSV/XLS row by row
- Looks up each passenger by phone number
- Creates an individual
PassengerOfferrecord with validity window, usage cap, and discount parameters - Triggers an SMS via MSG91 for every successful assignment
- Tracks per-phone-number success/failure in
FileUploadStatus - Reports upload completion back to the admin
Fifty thousand database writes, fifty thousand SMS triggers, all without a single blocked web process.
India-Specific Integrations, Built Right
This platform was built for the Indian market — and the integrations reflect that:
- Aadhaar Bridge — Government biometric KYC for driver and operator onboarding. OTP-based auth flow with fingerprint fallback, integrated pre-prod and production environments.
- Freecharge & Paytm — Direct gateway integrations with SHA256 checksum verification and refund transaction support. Not aggregator-wrapped — direct API calls with custom security implementations.
- MSG91 — XML-based SMS API with configurable sender ID, routes, and batch support.
- GST-compliant invoicing — Regional tax configuration, GST line items on invoices, PDF generation via WickedPDF.
The Craft: What “No AI” Really Means
Every piece of logic in this codebase was written by engineers thinking through the domain:
The role hierarchy — eight distinct user roles (super_admin, admin, fleet_manager, fleet_admin, yard_supervisor, customer_care_executive, customer_care_manager, accountant) with region-scoped permissions. CanCanCan ability definitions for each role were written to exactly match operational reality, not copied from a tutorial.
The attachment type model — Drivers aren’t just “employed.” They’re categorised as Salaried, Revenue Share, Individual Attachment, Day Revenue, or Leased. The data model captures real-world fleet economics.
Time-slice analytics — Driver performance reports break down every shift into four time windows (morning, afternoon, evening, night) because fleet managers need to know which drivers underperform during peak hours. This wasn’t a product manager’s feature request — it was an engineer understanding the operational problem.
Soft deletes everywhere — Mongoid::Paranoia on all major entities. Deleted drivers, passengers, and taxis stay in the database with a deleted_at timestamp. Auditors can reconstruct history. No data is ever truly lost.
Data migration as production code — When the platform absorbed a legacy system, dedicated migration workers (MigrateDriver, MigrateTaxi, MigrateTrips) were written with careful field mapping, checksum verification, and status tracking. The utoo_id field in passenger and driver models is a marker of thoughtful system transition, not a hack.
Results
The platform launched across multiple Indian cities and competed directly with Ola and Uber in its target markets. The backend supported:
- Real-time ride dispatch with multi-app coordination
- Fleet operations for hundreds of vehicles
- Corporate billing for B2B clients
- CRM booking for call-centre agents handling passengers without smartphones
- Reporting pipelines that gave operations teams daily visibility into fleet health
The codebase remained maintainable at scale because it was built with clear domain boundaries, not because a code generator made it easy.
What This Project Demonstrates
Deep domain modelling. 87 data models isn’t bloat — it’s precision. Every entity (Shift, SubRegionFare, MotorModel, TaxiDriverMapping, PartnerTransactionLedger) captures a real operational concept.
Systems thinking. The three-database split, the queue architecture, the async reporting pipeline — these are decisions that require understanding both the domain and the infrastructure constraints simultaneously.
Integration depth. Aadhaar, Freecharge, Paytm, MSG91, Salesforce, FCM, Google Maps, SendGrid, S3 — each integration was built to spec, with proper authentication, error handling, and environment management.
Operational maturity. Shift management, yard check-in/out, collection reconciliation, document expiry tracking — this is not a MVP. It’s a platform built by people who understand how a taxi fleet actually runs.
Explore More
- Full Case Study: Read the detailed architectural breakdown and code logs for Utoo Cabs
- Custom Solutions: Learn about our custom Taxi & Mobility App Development services