Blog
PreviousNext

Building SimpleRide: A Production-Ready Microservices Ride-Hailing Platform

How I built SimpleRide, an Uber and InDrive-inspired platform with microservices, real-time tracking, driver bidding, and cloud deployment.

SimpleRide is a production-ready ride-hailing platform inspired by Uber and InDrive. Riders can estimate fares, request trips, and follow a ride in real time, while drivers can discover requests and accept or counter-bid on the offered fare.

The App is live at simpleride.vercel.app. The App on github Github.

Why I chose microservices

The ride lifecycle has several independent responsibilities: authentication, location tracking, ride state, notifications, and gateway routing. I separated these responsibilities into services so each part could evolve independently and communicate through clear APIs and events.

SimpleRide contains five backend services:

  • Gateway: the single public entry point and reverse proxy for HTTP and WebSocket traffic.
  • Auth Service: registration, login, JWT access and refresh tokens, and rider/driver roles.
  • Ride Service: fare estimation, ride requests, bidding, OTP verification, status transitions, and ride history.
  • Location Service: driver GPS updates, Redis geospatial search, live tracking, and gRPC nearby-driver lookups.
  • Notification Service: ride event notifications, Socket.IO delivery, notification history, and completion receipts.

The communication model

I used the right communication method for each kind of work:

  • REST APIs handle client-facing requests through the Gateway.
  • RabbitMQ publishes ride lifecycle events such as ride.requested, ride.accepted, ride.completed, and ride.cancelled.
  • gRPC lets the Ride Service synchronously ask the Location Service for nearby drivers.
  • Socket.IO pushes driver locations and ride notifications to connected clients in real time.
  • Redis stores the driver geospatial index and supports BullMQ job queues.

This keeps synchronous requests focused while allowing services to react to ride events asynchronously.

The ride lifecycle

SimpleRide ride lifecycle flow diagram

1. Estimate and request

The rider first receives fare estimates for BIKE, MINI, and COMFORT vehicle types. When the rider creates a request, the Ride Service validates the custom offered fare, creates the ride with a four-digit OTP, and asks the Location Service for nearby drivers.

2. Bidding and race-condition protection

Drivers can accept the rider’s offer directly or send a counter-offer. Acceptance is protected by an atomic database update so only one driver can win a ride request. When a rider accepts a counter-offer, a transaction accepts the selected bid and rejects competing bids.

3. Live location and trip verification

The driver connects to the Location Service through Socket.IO and sends GPS updates. Redis stores the driver location, while the service broadcasts updates to the rider’s ride room. The driver must provide the OTP before the ride can move into IN_PROGRESS.

4. Completion and expiration

BullMQ schedules a two-minute expiration job for requests that no driver accepts. Successful rides publish completion events through RabbitMQ, allowing the Notification Service to send a receipt and the Location Service to clean up tracking rooms.

 
Fare Estimate → REQUESTED → SEARCHING → ACCEPTED → ARRIVED → IN_PROGRESS → COMPLETED
                                                        ↳ CANCELLED
                                     SEARCHING/REQUESTED ↳ EXPIRED

Frontend experience

The frontend is built with Next.js, TypeScript, Zustand, Axios, shadcn/ui, and Framer Motion. It provides separate rider and driver experiences, real-time updates, booking flows, fare displays, status changes, and responsive interfaces.

Technology stack

  • Frontend: Next.js, React, TypeScript, Zustand, Axios, shadcn/ui, Framer Motion
  • Backend: Node.js, Express, TypeScript, REST APIs, JWT
  • Distributed systems: RabbitMQ, BullMQ, Redis, gRPC, Socket.IO
  • Infrastructure: Docker, NGINX, AWS, Vercel, CloudAMQP
  • Development and testing: Postman, Git, AI-assisted development with Claude, Codex, OpenCode, Antigravity, and agent skills

Deployment

I deployed the frontend on Vercel and the backend services and supporting infrastructure on AWS. Docker provides consistent service environments, NGINX handles public routing, and CloudAMQP provides managed RabbitMQ messaging.

What I learned

SimpleRide helped me practice designing systems where correctness and responsiveness matter at the same time. The most valuable lessons were choosing between events and synchronous calls, protecting bid acceptance from races, keeping WebSocket channels focused, and making background expiration work reliably across services.

Explore the live App at simpleride.vercel.app, or return to the projects section to see the project in my portfolio.