01 / The Problem
A city is not short of roads, or drivers, or cars.
What it is short of is agreement. Who goes where, in what order, at what price, and for whom.
Every trip is a small negotiation between a thousand variables you never see. Where you are. Where they are. What the road is doing. What everybody else decided a second ago.
None of it is dramatic. It happens quietly, constantly, underneath ordinary life, which is exactly why nobody notices when it is handled badly.
You just notice that you waited.
Cities don't have a transportation problem. They have a coordination problem.
02 / The Idea
So I stopped building an app.
An app is a window. It shows you a map and a button, then hopes something sensible happens on the other side of the request.
Vectra is the other side. The part that works out who moves whom, in what order, with what guarantee, and can still tell you why an hour later.
It senses, it decides, it remembers. Thousands of times a second, for a city that never stops to wait for it.
The app turned out to be the smallest part of it.
03 / The Philosophy
None of this counts if you can't trust it.
01 / 04
04 / The Engineering
This is not a request and a response.
Underneath is a set of services that take nobody's word for anything, requests that leave a trail wherever they go, and failures the platform is expected to survive on its own, quietly, before anybody has to ask what happened.
Gateway
The request arrives here first. Authenticated, rate shaped, routed.
gateway → request accepted ride_req#4471
VECTRA
The next movement in urban mobility.
05 / The System
Everything above this is a claim. Here is the part you can check.
Vectra is not a prototype with a nice landing page bolted to the front of it. There are nine Go services, a Postgres database holding the only version of the truth, an event log that keeps everything else honest, and two apps running on real phones. What follows is what is actually deployed.
- 01Edge
One way in. Every request is authenticated, rate limited per address, and routed before it reaches a service that could act on it. Routes are public by exception, never by omission.
- 02Domain
Nine services, each owning one idea and one schema. Ride, Dispatch, Payment, Auth, User, Notification, Intelligence, Logging, and the gateway sitting in front of them.
- 03Truth
Postgres decides what is real. A rider cannot hold two open rides because a partial unique index refuses to write the second row. The rule sits underneath the code, where a bug cannot get at it.
- 04Movement
Services do not ring each other up to report news. They write it into their own database in the same transaction as the change itself, and a publisher delivers it afterwards to everyone who cares.
- 05Presence
Redis knows which drivers are where, right now. It is allowed to forget, because every driver says so again a few seconds later. Losing it costs nothing and rebuilds itself.
- 06Surface
Two Flutter apps. One for the person going somewhere, one for the person taking them there. Live location over websockets, notifications over FCM, payments through Razorpay.
- 9
- Go services in production
- 1
- public way in
- 4
- datastores, each doing one job
- 2
- apps in real hands
- 1
- server, smaller than your laptop
06 / The Guarantees
Four things the system will not let you do.
Features are easy to demo and easy to fake. These are the rules sitting underneath them, and each one is enforced somewhere a careless change cannot reach.
- 01
You cannot be on two rides.
Not because the app hides the button. Because Postgres holds a unique index over exactly the statuses that count as active, and the second insert simply fails. The app finding out about it is a formality.
Enforced by
unique (passenger_id) where status in ('requested','assigned','accepted','arriving','started') - 02
A driver is claimed once.
Two riders can want the same driver in the same millisecond. One of them gets him. The claim is a single atomic write with an expiry, so it holds across every replica at once, and the loser is told no straight away and sent to look again.
Enforced by
SET driver:reserved:{id} {ride_id} NX PX 30000 - 03
Nothing goes missing in between.
A service never announces something it has not already written down. The event and the state change go into one database transaction together, and a publisher picks it up afterwards. If that publisher dies halfway through, the row is still sitting there when it comes back.
Enforced by
insert into ride_outbox_events (...) in the same transaction, published_at is null - 04
Twice is the same as once.
At least once delivery means every consumer will eventually see a message it has already handled. So each one is written to recognise it and do nothing. That is not defensive code bolted on afterwards. It is the reason the delivery guarantee is allowed to be that loose in the first place.
Enforced by
idempotency key per message, deduplicated inside every handler
None of these are features. They are the reason the features are allowed to exist.
07 / Scale
Designed for millions. Engineered for one.
Not one user. One trip. The specific one happening right now, for a specific person, on a specific street, that has no idea it is one of millions.
Scale is not a milestone I am waiting to reach. It is a constraint I build against today, in every schema, and in every decision about where data lives and how far a request has to travel to get an answer.
I would rather have a platform that behaves the same on trip one and trip one billion than a number I cannot stand behind.
08 / Where it is
I don't say coming soon.
- Buildingdone
Nine services, independently scoped, independently deployed.
The same ten stages a request just travelled through, further up this page.
- Testingactive
Failure injected on purpose, before the world does it for free.
The Dispatch outage you watched is something I run deliberately.
- Breakingactive
On my terms, in a room I control, long before launch day.
If it cannot survive me breaking it, it is not ready for traffic.
- Learningqueued
Every incident turns into an invariant the system now enforces.
The reconciliation worker exists because once, something like it didn't.
- Improvingqueued
Nothing ships and then sits still. It ships and keeps moving.
There is no final version. There is only the current one.
- Launchingqueued
When the system earns it. Not a day before.
You'll know. The heartbeat on this page won't be the only one.
A city is really just a lot of people trying to be somewhere else. I intend to be very good at that.
Designed, built, and broken repeatedly by Utsav Kaushik.