I don't think we'll ever hit 1000 drivers: right-sizing before you over-engineer
The agent reached for a message broker and persistent streams to serve a few dozen users; the right answer was a five-second poll and the nerve to say so.
The agent wanted a message broker, persistent streaming connections, and a fan-out layer to push live locations to the dashboard. The system it was building served a few dozen active users on a good day. We were about to stand up infrastructure for a thousand concurrent drivers to serve forty, and nobody in the room had asked the only question that mattered: what is our actual scale?
I asked it. The answer was a few dozen, with maybe a hundred on the horizon if everything went well for a year. So we threw the broker out and shipped a five-second poll of a snapshot endpoint. It has never once been the bottleneck.
Real-time is a cost, not a free upgrade
The seductive thing about a streaming architecture is that it sounds like the responsible, grown-up choice. Push instead of poll. Events instead of requests. It reads like maturity. But every one of those words is a standing cost you pay forever, whether or not anyone benefits from it.
- A broker is a thing you babysit. It’s another process that can fall over at 2am, another set of metrics to watch, another failure mode where messages pile up in a queue nobody is draining. A poll has none of that. If the dashboard misses a beat, the next request five seconds later fixes it for free.
- Persistent connections pin resources. Every open stream holds a worker, a socket, and a slice of memory for as long as it lives. I have watched a handful of long-lived connections saturate a pool that handled ordinary traffic without breaking a sweat. Concurrency you didn’t budget for is the demo that dies in front of the client.
- Push needs reconnection logic you’ll get wrong. Mobile networks drop. The driver goes through a tunnel, the socket dies, and now you own the dance of detecting the drop, backing off, re-establishing, and replaying what was missed. A poll reconnects by definition: the next one just happens.
A five-second poll, by contrast, is almost insultingly dumb. The dashboard asks “where is everyone,” gets a snapshot, draws it, waits five seconds, asks again. There is nothing to babysit, nothing to reconnect, nothing to drain. For a map of forty drivers, five seconds of staleness is invisible. The operator cannot tell the difference, and neither can the driver.
Scale is earned, not assumed
The deeper mistake isn’t choosing the wrong tool. It’s reaching for the tool that fits a scale you don’t have and may never reach. “I don’t think we’ll ever hit a thousand drivers” sounds defeatist when you say it out loud, like you’re capping your own ambition. It isn’t. It’s the single most useful sentence in the architecture conversation, because it tells you which problems are real today and which are fan fiction.
Real-time architecture should be earned by load, not adopted because it’s impressive. The simplest thing that works is allowed to carry you right up until the moment it visibly cannot.
The honest version of capacity planning is arithmetic, not aspiration. Take your real concurrent users, multiply by the work each one generates, and see if the boring approach survives. At a few dozen users on a five-second interval, that’s a few hundred requests a minute hitting a query that returns in milliseconds. That’s not a load problem. That’s a rounding error.
Defer the migration to the version that hurts
None of this means streaming is wrong. It means it’s premature. The right move is to know exactly what would change my mind and write it down, so the upgrade is a decision and not a panic. When the poll starts costing real money, when staleness becomes something an operator complains about, when concurrency climbs past the point where polling is cheaper than pushing, that’s the version where you migrate. Not before.
So I left a note next to the poll: this is deliberate, here is the trigger that flips it. Until then, the most senior thing I can do is refuse to build for a company I don’t have yet, and let the dumb thing that works keep working.