The exchange app was designed on office fibre and tested on office fibre. Then we looked at the session data and found that a quarter of our users in Paris, Jakarta and São Paulo were on connections where a single round trip could take two seconds.
For one quarter, every designer and mobile engineer worked with a network conditioner pinned to 3G with 400 ms of added latency. Not for a sprint. For a quarter.
Three things changed immediately. Optimistic UI went from a nice-to-have to the default, because a spinner that runs for two seconds reads as a broken app. Every screen got a meaningful skeleton derived from cached data rather than a grey rectangle. And we deleted about 40% of the animation budget, because motion that waits on a network response is worse than no motion at all.
The deeper change was to what the interface was allowed to promise. A button labelled "Buy" that might not have worked yet is a lie on a slow connection. We now show the order as pending with a clear state and a real cancel affordance, rather than pretending it completed.
Crash-free sessions on low-end Android went from 98.1% to 99.7%. Order abandonment on slow connections fell by a third. Neither number moved because we optimised a bundle.