1. Blocking UI during network requests. The pattern is familiar: the user taps a button, the app shows a spinner, and the UI is unresponsive until the server replies — or until a timeout error appears. On a fast connection, the wait is half a second. On a congested 2G connection, it is thirty seconds, after which the user taps again, generates a duplicate request, and wonders whether the app is broken. The fix is to never block the UI for network operations: queue the action locally, update the UI immediately to reflect the intended state, and sync in the background.
2. Infinite loading screens. A variant of the above: the app attempts to load data from the server, the server is unreachable, and the loading indicator spins indefinitely with no timeout, no error message, and no recovery option. The user closes the app and does not return. Every network request must have an explicit timeout, a meaningful error message, and a recovery path (retry, use cached data, or continue offline).
3. No cache, no state. An app that fetches data fresh from the server on every launch and stores nothing locally will be useless the moment connectivity is lost. Even a minimal caching strategy — storing the last successful response and displaying it while a refresh is attempted — dramatically improves the experience in intermittent connectivity environments. Users who can see their data from the previous session while the app tries to refresh are far more patient than users who see a blank screen.
4. Large uncompressed assets. Splash screens, onboarding images, icon sets, and in-app illustrations that are not compressed for low-bandwidth delivery can consume a user's entire daily data budget in a single session. Mobile images should be served in modern formats (WebP, AVIF), sized appropriately for the device display, and lazy-loaded where possible. This applies particularly to the initial app bundle — a first-launch download that is 50MB will not complete on many low-bandwidth connections.
5. Silent data loss on interrupted writes. A user fills in a form, submits it, the connection drops mid-transmission, and the data is lost with no notification. The user assumes the submission succeeded. This is the most damaging failure mode because it is invisible — the user may not discover the loss until much later, and the data cannot be recovered. All writes must be persisted locally before being transmitted, and transmission must be confirmed before the local copy is discarded.
6. Requiring connectivity for authentication. Many apps require an internet connection to verify a login token, even for features that could otherwise work offline. A user who is already logged in and loses connectivity should not be logged out or blocked from app features that do not require server data. Authentication tokens should be cached locally with an appropriate expiration, allowing continued offline use within a session.