Keep the API responsive
BullMQ workers handle recurring intent generation, route computation, reminders, and background backfills. Scheduled jobs automate the daily commute lifecycle.
I architected a distributed backend that turns fixed daily commutes into shared rides—without asking drivers to turn their journey into a detour.
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.
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.
The classifier checks pickup and drop-off together. Riders outside the corridor are discarded before further detour calculations or mapping calls.
For tiers 1–3, Haversine distance × 1.3 provides an inexpensive road-distance estimate. Candidates are filtered against detour limits before road-network verification.
The reported reduction is in the candidate search space before external mapping calls. Geometry does the early work; road routing checks feasibility.
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.
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.
I separated request handling, asynchronous matching, and live trip updates so expensive work could be processed outside the HTTP request path.
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.
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.
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.
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.
A wider overlap between the driver’s arrival window and the rider’s departure window increases compatibility.
Balances relative route expansion with the driver’s preferred detour budget, so “nearby” doesn’t hide an inconvenient trip.
Distinguishes road-routing data from aerial-distance estimates. Reasons include “Low detour” and “Within driver detour preference.”
BullMQ workers handle recurring intent generation, route computation, reminders, and background backfills. Scheduled jobs automate the daily commute lifecycle.
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.
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.
Corporate email verification, ratings, blocking, and contact-sharing detection support platform trust. Stripe Connect coordinates payment authorization, capture, and driver transfers.
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 ↗