Case Study · Online Taxi / Mobility
2+ Platforms (iOS & Android) from one codebase
<20ms Fare Calculation Latency
2 Live Cities at Launch
0× Surge Pricing — Always Fixed
RideOn™ needed a taxi platform for the holiest cities in Saudi Arabia — Makkah and Madinah — where passengers always know their exact fare before booking. No surge pricing. No dynamic adjustments. A confirmed fare that never changes.
The environment makes this uniquely challenging:
Requirements: real-time driver location tracking, instant fare calculation from geofenced zones, and reliable booking on poor networks — all from a single development team.
Dynamic pricing during peak periods punishes the users who need the service most. Pilgrims near the Masjid Al-Haram can't shop around — they need a ride, and they need to know what it costs. We needed a pricing model that felt fair regardless of demand.
Standard WebSocket connections drop silently when phones switch towers in dense crowds. A dropped connection in a ride-hailing app means missed location updates, broken booking state, and frustrated users. We needed a communication layer that survives network interruptions.
Users from 180+ countries means the app must work fluently in Arabic (RTL) and English (LTR) — not as an afterthought, but as a first-class concern. Arabic numerals, right-to-left layouts, and culturally appropriate formatting throughout.
Building and maintaining four separate native codebases (Rider iOS, Rider Android, Driver iOS, Driver Android) was not viable. We needed a shared codebase approach that still delivered a native-quality experience on each platform.
We divided Makkah and Madinah into geofenced zones using GeoJSON polygons stored in MongoDB with 2dsphere indexing. A pre-computed fare matrix maps every origin-destination zone pair to a fixed SAR amount, cached in Redis for sub-20ms lookups.
When a passenger enters their destination, the app resolves both coordinates to zones, fetches the fare from Redis, and displays it instantly. Once the passenger confirms, the fare is locked immutably to the booking. No driver or system action can change it.
We replaced the conventional WebSocket approach with MQTT — a protocol designed for unreliable mobile connections. MQTT's QoS Level 1 guarantees at-least-once delivery and maintains persistent sessions through network interruptions. When a driver's phone reconnects after a signal drop, all missed events are delivered automatically.
Drivers publish their location every 3 seconds. The MQTT broker routes updates with QoS 1 to the NestJS API, which updates Redis and pushes the update to the rider's app. The entire chain survives dropped connections on either end.
All four app targets (Rider iOS, Rider Android, Driver iOS, Driver Android) are built from a single React Native codebase. Build-time flags and context providers determine which flow the app renders at startup. Shared components — maps, booking cards, fare display, chat — live in a common library.
RTL/LTR support is handled via React Native's built-in I18nManager with locale detection at startup. Arabic and English are both first-class locales, not translations bolted on afterward.
Every booking moves through a defined state machine:
REQUESTED → ACCEPTED → DRIVER EN ROUTE → IN TRIP → COMPLETED
Each state transition triggers an MQTT event that updates both the rider and driver apps in real time. The booking state is persisted in MongoDB with a Redis cache layer for active trips.
Algorithm:
$geoIntersects query)fare:{zoneA}:{zoneB} key in Redisasync calculateFare(pickup: Coordinates, dropoff: Coordinates): Promise<number> {
const pickupZone = await this.zoneModel.findOne({
boundary: { $geoIntersects: { $geometry: { type: 'Point', coordinates: [pickup.lng, pickup.lat] } } }
});
const dropZone = await this.zoneModel.findOne({
boundary: { $geoIntersects: { $geometry: { type: 'Point', coordinates: [dropoff.lng, dropoff.lat] } } }
});
const fareKey = `fare:${pickupZone.id}:${dropZone.id}`;
const cached = await this.redis.get(fareKey);
return cached ? parseInt(cached) : await this.computeAndCache(pickupZone.id, dropZone.id);
}
Sample Fare Table (SAR):
| From | To | Fare | |------|----|------| | Masjid Al-Haram Precinct | Mina | 25 SAR | | Masjid Al-Haram Precinct | Aziziyah | 35 SAR | | Arafat | Muzdalifah | 15 SAR | | King Abdulaziz Airport | Masjid Al-Haram Precinct | 55 SAR |
| Key Pattern | Purpose | TTL |
|-------------|---------|-----|
| session:{userId} | Auth session | 24h |
| otp:{phone} | OTP verification | 5 min |
| driver:loc:{id} | Driver location | 30s |
| fare:{zoneA}:{zoneB} | Fare cache | 1h |
| booking:{id}:status | Active booking state | Trip duration |
| Phase | Scope | |-------|-------| | Discovery & Architecture | Zone mapping, fare matrix design, system architecture | | Core Backend | NestJS API, fare engine, MQTT infrastructure, Redis setup | | Mobile Development | React Native apps, RTL/LTR, maps integration, booking flows | | QA & Load Testing | Performance testing, network degradation simulation, UAT | | Launch & Support | Staged rollout in Makkah then Madinah, ongoing monitoring |
Zero Surge Pricing — Fares are locked at booking confirmation. No passenger has ever paid more than the fare they saw upfront.
Resilient Real-Time Dispatch — MQTT ensures driver location updates are delivered even through network interruptions common near holy sites.
Four App Targets, One Codebase — Approximately 60% reduction in ongoing maintenance overhead compared to maintaining separate native codebases.
Sub-20ms Fare Responses — Redis-backed fare lookups return in under 20ms, enabling instant fare display in the UI.
RTL + LTR Dual Locale — Arabic and English are both fully supported with correct bidirectional layout, numerals, and formatting.
Scalable for Peak Season — Stateless NestJS API, clustered Redis, and MQTT broker designed to handle Hajj-scale load spikes.
"The fixed fare feature was our entire value proposition. We needed passengers to trust the platform before they even got in the car — and that meant they had to know their fare before they confirmed. Techvisionar built exactly what we described, and they understood why it mattered. Passengers know their fare before they book, and that builds the kind of trust a new platform needs."
— RideOn™ Founding Team, Makkah, Saudi Arabia
Building something like this? Start a conversation →
Tell us about your project and we'll put together a tailored proposal.
Start a Project →