← Portfolio
← SELECTED WORK
ENGINEERING CASE STUDY / 01

Same direction.
Smarter journeys.

LetzGo / Carpooling

I architected a distributed backend that turns fixed daily commutes into shared rides—without asking drivers to turn their journey into a detour.

700+users served
>85%candidate search-space reduction
Full stackmatching, live trips & payments
MY FOCUS Backend architecture · Spatial matching · Route optimization · Real-time coordination
01 / THE CONSTRAINT

A nearby rider isn’t
always a good match.

A driver is already going to work. The right match fits their route, their departure window, and their detour budget.

A simple radius search around a driver misses the shape of the journey. A rider can be nearby but traveling in the wrong direction, or have a drop-off that makes the trip impractical.

Checking every driver–rider pair with a mapping API is expensive. With N drivers and M riders, the number of possible checks grows as N × M.

My approach: use inexpensive geometry to narrow the search, then spend routing work on promising candidates.

02 / FOUR-TIER SPATIAL FILTER

Filter locally.
Verify on the road.

The route becomes a corridor. Sampled route points get 300 m circular buffers; a wider rectangle captures the surrounding travel area. Both endpoints of each rider’s journey determine their tier.

01 / GEOMETRY FIRST

Two endpoints, one decision.

The classifier checks pickup and drop-off together. Riders outside the corridor are discarded before further detour calculations or mapping calls.

02 / DETOUR CHECK

Approximate, then validate.

For tiers 1–3, Haversine distance × 1.3 provides an inexpensive road-distance estimate. Candidates are filtered against detour limits before road-network verification.

03 / ENGINEERING IMPACT

Over 85% fewer candidates.

The reported reduction is in the candidate search space before external mapping calls. Geometry does the early work; road routing checks feasibility.

THE TRADE-OFF

A corridor and a 1.3× distance estimate do not model bridges, one-way streets, or road barriers. They are screening heuristics, not proof that a ride is feasible. Road-network verification remains necessary, and narrow corridors can exclude useful matches.

Under the hood: corridor construction +

The engine calculates the bearing between the route endpoints, derives perpendicular expansion vectors, then offsets the endpoints with safety padding and half-width to construct a closed rectangular polygon. It decodes the route polyline and samples points at step intervals of 10 for the circular buffer checks.

The four tiers are mutually exclusive: both endpoints in route buffers; one in a buffer with both in the rectangle; neither in a buffer but both in the rectangle; or at least one endpoint outside the corridor.

03 / SYSTEM DESIGN

A responsive API.
A working background.

I separated request handling, asynchronous matching, and live trip updates so expensive work could be processed outside the HTTP request path.

letzgo / system-architecture LOGICAL VIEW
LetzGo backend architectureClients use HTTPS through Nginx to Express and WebSockets through Socket.IO. Express reads and writes PostgreSQL with Prisma, enqueues jobs in Redis and BullMQ, and integrates with Stripe Connect and mapping APIs. Workers run matching, routing, notifications and backfills. Prometheus and New Relic observe the API.HTTPS / RESTWebSocketrequestsread / writeenqueue jobsservice callsconsumeAPI telemetryMobile / web clientsNginxSocket.IOPrometheus + New RelicExpress applicationStripe Connect · Google RoutesMapbox · GeocodingPostgreSQL + PrismaRedis + BullMQ queuesBackground workersGPS · chat · presenceMetrics & tracingTrip state · segment cacheRecurring intents · route jobsCorridor filter → PDP optimizerMatch scoring · matrix backfillNotifications → Firebase FCMSelected dependencies shown. Live GPS is relayed to trip rooms; presence is persisted.
THE TRADE-OFF

Background jobs make matching eventually consistent. A request can return before the match is ready; WebSocket events communicate the result. Worker concurrency limits and Redis job locks control batch processing, but are not a substitute for booking-level capacity checks.

04 / ROUTE OPTIMIZATION

Keep the search small.
Reuse the expensive work.

For two riders, a simple constrained search was enough. The bigger win was avoiding repeated routing calls.

I evaluated the six pickup-before-drop-off orders and compared them using cached segment distances and durations, instead of querying a mapping API for every permutation.

A DELIBERATELY BOUNDED DESIGN

24 possible orders → 6 valid orders.
Each rider must be picked up before being dropped off.

Missing segments use an approximate distance model and trigger a background backfill. Nearby sequential stops can share a stop-order index.

This deterministic approach fits the two-rider case. More riders would require a different search strategy as the number of orders grows.

05 / EXPLAINABLE MATCHING

Compatible beats close.

After spatial screening, the ranking considers departure overlap, detour impact, and the confidence of the route data. Riders and drivers get reasons alongside the score.

45%Time overlap
45%Detour score
10%Confidence

Time overlap

A wider overlap between the driver’s arrival window and the rider’s departure window increases compatibility.

Detour impact

Balances relative route expansion with the driver’s preferred detour budget, so “nearby” doesn’t hide an inconvenient trip.

Data confidence

Distinguishes road-routing data from aerial-distance estimates. Reasons include “Low detour” and “Within driver detour preference.”

06 / PRODUCTION ENGINEERING

The route is only
part of the system.

01

Keep the API responsive

BullMQ workers handle recurring intent generation, route computation, reminders, and background backfills. Scheduled jobs automate the daily commute lifecycle.

02

Relay GPS, preserve the database

Socket.IO sends location updates to the associated trip room instead of persisting every GPS ping. Presence and trip milestones are stored; the full live path is ephemeral.

03

Make performance visible

Prometheus request histograms and New Relic expose latency. Normalizing dynamic URL IDs prevents metrics cardinality from growing with every user and trip.

Resume-reported Artillery result: P99 endpoint latency <100 ms under load test, not a guarantee for every production request.

04

Coordinate trust and payments

Corporate email verification, ratings, blocking, and contact-sharing detection support platform trust. Stripe Connect coordinates payment authorization, capture, and driver transfers.

THE ENGINEERING THROUGH-LINE

Spend expensive work
where it matters.

Geometry narrows the search. Cached segments make route comparison cheap. Background workers handle the heavy lifting. Together, these choices turn a difficult matching problem into a practical carpooling backend.

← Back to selected workDiscuss the engineering ↗