The demo where everything that could break, broke
Software isn't tested until real users hit it at the same time on the same shaky network, and a live demo is where they all arrive at once.
Software is never really tested until real people hit it at the same time, on the same shaky network, in the same room. Every green test I had was a green test in a world with one user, full bars, and infinite patience. The demo was the first time that world ended, and it ended all at once.
It was a field app being shown to a room that mattered. A handful of users tapped through the same flow within the same minute, and the stack folded like it had been waiting years to. Nothing I saw that day had ever appeared in a single test run. That’s the part worth writing down, because it isn’t bad luck. It’s the shape of the gap between “works on my machine” and “works when a dozen distracted humans arrive together.”
The four ways it fell over
None of these were exotic. Each was a corner I’d individually decided was fine, and reality stacked them into one bad minute.
- The backend saturated with a handful of users. What ran smoothly for me serially did not run for several people concurrently. The worker pool drained, requests queued, and what looked like a hang to each user was really everyone standing in the same invisible line. My local testing had exactly one person in that line, always.
- A five-minute upload with no progress bar. A photo that flew off my laptop crawled off a phone on one bar. With no feedback, the natural human response is to tap again, so one upload became three, which made the saturation worse. The bug wasn’t slowness. It was silence about the slowness.
- A login that never said “no signal.” Someone sat on a spinner that would never resolve, because their phone simply had no connection and the screen refused to admit it. They assumed the app was broken. The app assumed the network was fine. Neither told the person holding the phone anything true.
- A Continue button that threw a null. No message, no recovery, just a dead end on the one tap that was supposed to move them forward. In isolation it’s a trivial fix. In the room it read as the whole thing being held together with tape.
Why none of it showed up in testing
Each failure lived in a condition my tests didn’t have. Concurrency, a real cellular network, an actual dead zone, the specific empty state that triggered the null. My test environment was a quiet room with a fast pipe and one well-behaved user who never double-tapped anything. I had tested the happy path on a happy network, and called it tested.
A passing test suite tells you the code does what you imagined. A live demo tells you what you forgot to imagine. They are not the same audit, and only one of them happens in front of the people you’re trying to win.
The honest lesson is that reliability is mostly about the boring conditions you never recreate on purpose. Concurrency, bad networks, empty states, and impatient fingers aren’t edge cases in the field. They’re the median.
What I harden before a room sees it now
The fixes were unglamorous, which is the point. Compress images on the device before they leave the phone, and always show real progress so nobody taps twice into a void. Surface “no network” as an explicit, honest screen instead of an eternal spinner. Make the worker pool survive concurrent users, or know your real ceiling before you walk in. Catch the nulls and say something human when one slips through.
And the last one isn’t code: have someone tailing the logs live during the demo. The difference between “it’s broken” and “the third upload is queued behind two others, give it ten seconds” is the difference between losing the room and steering it.
I don’t run a demo as a victory lap anymore. I run it assuming everything I decided was fine alone will arrive together and prove me wrong, because that one time, every single thing did.