Case study
Routing out of the monolith, one route type at a time.
A Series-B logistics platform in the Netherlands, around 40 staff, with dispatch routing inside a Rails monolith. Four engineers have been on the extraction since 2025. On the route types already moved into the Go service, p95 dispatch latency is 780 ms against 2.4 s before.
The situation
Dispatch — deciding which driver takes which job — lived in the same Rails application as billing, the admin tools, and the customer portal. A change to routing meant deploying all of it, so routing work waited for the release train. At the volumes the platform had reached by 2025, p95 dispatch latency was 2.4 s, and the slow path was one request reading the whole candidate set out of PostgreSQL before it could answer.
The client came to us with a plan to rewrite the monolith. We told them which half of that plan was wrong and quoted the smaller job instead: take routing out, leave the rest where it is.
What we did
Routing moved into a Go service one route type at a time. The monolith kept serving live traffic throughout. For each type, the Go service ran in shadow against real requests first, then took the type over behind a flag the client's own team could flip back without calling us.
Job and vehicle state reaches the service over Kafka rather than through a shared database, so the two systems never write the same tables. The service runs on Kubernetes on AWS with its own PostgreSQL, and deploys on its own schedule. Four engineers, one of them the named technical lead, who runs review, estimation, and escalation on our side; priority stays with the client's product owner.
What changed
On the route types that have moved, p95 dispatch latency is 780 ms against 2.4 s before — a 68% reduction, taken from the client's own dashboards rather than from a measurement we built for the purpose. Routing changes no longer wait on the monolith's release train.
The route types that have not moved still run in Rails at the old latency. The figure above describes the moved set, not the whole platform, and the client reads it that way.
How it ended
It has not. The engagement began in 2025, is in its fourteenth month with the same four engineers, and more route types are still in the monolith. There is no fixed end date, because there is no point yet at which the remaining work stops being worth doing. Either side can end it on 30 days' notice.
When it does end, the exit will look like the handover engagement written up on this site: a written description of the system, training for whoever keeps it, and a date agreed in advance.
The Go service runs on Kubernetes on AWS, keeps its own PostgreSQL, and takes job and vehicle state over Kafka. Five of the ten technologies we staff against; nothing on this engagement sits outside them. The Rails monolith is the client's own, inherited rather than chosen, and still serves every route type that has not moved.
Dispatch, before and after
We came in asking for a rewrite. Before anything was signed, they told us which half of the plan was wrong, and quoted the smaller job instead. Fourteen months in, it is still the same four engineers.
Routing stuck behind everything else in the repository?
Four engineers, 14 months, one route type at a time. Ramp-up is 10–15 business days from signature; three months is the minimum engagement.