Designing for Slow Networks and Low-End Devices

A retail client's user base skewed heavily toward Tier 2 and Tier 3 cities in markets where 3G and congested 4G were still common, and a large share of traffic came from devices with 2-3GB of RAM. Our dev team's usual testing setup — fast wifi, recent iPhones — was actively hiding the problems real users hit. We started testing on a throttled Moto G Power profile in Chrome DevTools and an actual budget Android device, not just the simulator, because CPU throttling in DevTools doesn't fully replicate real thermal throttling behavior.
The JavaScript bundle was the first target. It had grown to 890KB gzipped, largely from a UI library we were using for maybe 15% of its components and a moment.js dependency pulled in transitively. Swapping to date-fns and auditing unused component imports with a bundle analyzer got us to 310KB. On a throttled 3G connection, that alone cut Time to Interactive from 14.2s to 5.6s.
Images were the second problem. We moved to responsive images with explicit width/height attributes to prevent layout shift, served AVIF with a JPEG fallback, and set a hard budget of 100KB per hero image. We also added a low-quality image placeholder (LQIP) using a blurred 20px base64 thumbnail rather than a generic skeleton, which measurably reduced perceived load time in user testing even though actual load time was unchanged.
For low-RAM devices, we found that heavy use of CSS backdrop-filter and box-shadow on scrolling lists was causing frame drops on the Moto G test device, dropping scroll performance to around 24fps. Reducing shadow layers and avoiding backdrop-filter on list items (reserving it for modals only) brought scroll performance back to a steady 55-60fps.
Offline resilience mattered too, given how often users lost signal mid-session on mobile networks. We added a service worker that cached the app shell and last-viewed product data, so a dropped connection showed stale-but-usable content with a clear 'reconnecting' indicator instead of a blank error screen. Support tickets referencing 'app not loading' dropped by about 40% after that release.

