Mobile vs. Web: Rethinking System Design
Understand the difference between mobile System Design and web System Design.
You’re leading the System Design for an e-commerce product with a “Save for Later” feature. The user taps a button to save an item to their favorites.
Seems simple, right? But here’s the twist: You must design this feature for both the mobile app and the web platform. Each has the same core function, but extremely different execution contexts.
Say “Hi” to Ed (the AI persona) in the widget below to test your knowledge on understanding the difference between the mobile app and the web platform.
If you’re unsure how to do this, click the “Want to know the correct answer?” button.
At first glance, designing for the web and mobile might seem similar. We have screens, users tap buttons, and data comes from the backend. Same app, different device, right? Not quite.
Unlike the web, mobile operates in unpredictable, often hostile environments. A web user typically sits at a desk with stable power, fast internet, and a full-sized browser. Failures are recoverable: refresh the page, try again, patch the bug. We control the deployment, the runtime, and even the update cycle.
Mobile strips all of that away.
Our user is on the move, and the connection is unstable. The device is constrained; it has a limited CPU, memory, and battery. Our app competes with dozens of others for OS attention. We can’t ship a fix in minutes, and we can’t assume our backend is even reachable.
Let’s say you’re on a train, moving fast. You open your mobile banking app to make an important transaction. The screen stalls briefly as your signal drops to a single bar. You close it with disappointment and move on.
The app didn’t crash or break, but it failed. This is what failure looks like in mobile: subtle, quiet, and costly. This is the mobile reality. And it’s unlike anything web System Designers typically prepare for.
Designing for mobile means designing for unpredictability. The device may be low on battery, juggling multiple apps, or operating on an unstable 3G connection. The app may be suspended, terminated in the background, or stripped of permissions. There’s no guarantee your carefully engineered backend has a reliable path to the device. Worse, your user may only blame one thing: your app.
Note: Most performance issues, retention problems, and architectural messes in mobile apps result from treating mobile like the web. This course will help us unlearn that habit, starting with this lesson.
This course starts where most end. It recognizes that mobile is not just a different UI layer. It is a fundamentally different system context. Designing for mobile means designing for unpredictability, which makes it one of the most interesting, complex, and critical System Design problems today.
Let’s start by understanding how and why it differs from the web.
Mobile vs. web: A System Design shift
Let’s say we’re designing a food delivery app.
On the web, a user logs in, places an order, and tracks it, all while sitting comfortably with stable Wi-Fi. The frontend sends requests to a backend, and the backend handles everything: authentication, order processing, real-time status, and delivery tracking. If something fails, we refresh the page and try again.
Now, picture that same flow on mobile.
The user is outside, ordering lunch while riding in a cab. As they switch between neighborhoods, the connection weakens. Midway through checkout, the app briefly loses signal. The map freezes. The “place order” button doesn’t respond. When it works again, the user isn’t sure if their order went through. They retry, possibly submitting the same order twice.
This is the fundamental shift. On mobile, the app can’t afford to be passive; it must be intelligent, resilient, and active, even when the network isn’t.
In a web system, the client relies entirely on the backend. In a mobile system, the client must take responsibility.
It needs to store the user’s input locally, detect that it’s offline, queue the order, and sync it once the signal is back, without the user ever noticing. It may need to locally cache the restaurant menu, manage the user’s session, and display estimated delivery times using stale but usable data. That can’t be done with just a UI layer.
To properly understand this shift, we must explore the key constraints shaping mobile System Design. We’ll start with the most immediate: the device and its runtime environment.
1. The device and runtime environment
A user starts their morning run, opens a fitness app, and begins tracking a workout. The app collects GPS data, calculates pace, and stores metrics every few seconds. Everything works great until the user gets a phone call. Then a low battery warning appears. Moments later, the OS quietly suspends the app to save power. When the user opens the app again, their run data is gone. What happened?
The user didn’t uninstall or close the app. The app simply faded out of memory. On mobile, this is not categorized as a crash; instead, it’s a normal behavior. This scenario highlights one of the most misunderstood truths about mobile System Design, as illustrated below:
Mobile devices juggle dozens of apps with limited memory and power. If our app consumes too much CPU, drains battery, or sits idle in the background, the OS may suspend or terminate it without warning. Even if our app runs in the foreground, it competes with incoming calls, notifications, camera usage, and more.
That’s just the runtime side. Now add to this: the hardware variability.
Our users could be running our app on:
A high-end flagship with 12GB of RAM and the latest chipset.
or
A 5-year-old budget phone with a slow CPU and just 2GB of RAM.
Some have fingerprint sensors; others don’t. Some have background data disabled. Some use dark mode, large fonts, or battery-saver modes that terminate background services altogether.
When we build for the web, we target a relatively stable environment: a few major browsers, decent memory, and stable execution. But when we build for mobile, we design for dozens, sometimes hundreds, of runtime environments.
Takeaway: In mobile System Design, the defaults are runtime volatility and device diversity. Our system must be resilient, even when paused, terminated, throttled, or running on underpowered hardware, and continue to deliver a seamless experience.
Designing for diverse devices and fragile runtimes is just one part of the mobile puzzle. But even if our app gracefully handles memory pressure and background suspensions, another unpredictable force shapes the mobile experience: the network.
It doesn’t matter how well our backend works if the request never arrives in time.
Let’s explore what happens when connectivity becomes a system variable.
2. Network behavior
Mobile apps often fail, not because the backend is down or the device is weak, but because the network couldn’t be trusted (as discussed earlier), and the system wasn’t designed for that possibility.
On the web, connectivity is practically assumed. Most systems are built on the expectation that requests will reach the server, responses will come back, and a user can simply refresh if something breaks. However, as mobile users aren’t tethered to stable connections, they jump between LTE and Wi-Fi, encounter coverage gaps, pass through elevators, and switch SIM cards mid-session.
Takeaway: Our system should cache, retry, and queue actions when offline and gracefully handle partial syncs. It must do all this invisibly because the user doesn’t care that they were offline. They care that their message wasn’t sent, their order wasn’t placed, or their form submission vanished into a void.
Designing for unstable networks teaches us to expect communication delays. But mobile systems must endure another kind of delay, not at runtime but during deployment.
Let’s talk about what it means to ship software in the mobile world.
3. Deployment in mobile
In web development, pushing code is almost instant. A fix can go live in minutes. We control the release, the server, and the feedback loop. Mobile is slower. And not because we want it to be.
Every release must undergo app store review processes, which often take hours, and sometimes even days. Once approved, we still face a fragmented user base: some will update immediately, others won’t for weeks. A critical fix we ship today might not reach 40% of users for days. The following graph indicates user adoption of updates to a mobile app:
Even worse, our system may need to support multiple live versions of our app, all interacting with the same backend, but each possibly behaving differently.
Takeaway: Mobile deployment is asynchronous, unpredictable, and out of our hands. Our system must be backward-aware and resilient, because once an app version is live, it’s out there for good.
Delays in deployment shape how we build. But once the code reaches the user, how they interact with the app introduces a new kind of complexity that doesn’t exist in the web world.
Let’s explore how mobile UX redefines how systems must behave behind the scenes.
4. UI paradigms and experience expectation
A tap. A swipe. A voice command. A glance. On mobile, interaction is direct and sensory. There’s no mouse cursor, no hover state, no keyboard fallback. Users expect instant feedback, fluid transitions, and platform-consistent behavior, whether they’re flicking through a social feed or scanning a QR code at checkout.
If a gesture freezes for even half a second, the experience feels broken. The system feels unreliable if the UI shows a button before the action is ready. Unlike the web, where users are used to small delays or full-page loads, mobile demands constant responsiveness, no matter what’s happening under the hood.
To meet this bar, systems often:
Preload and cache data aggressively.
Use optimistic UI updates (showing results before confirmation).
Minimize round-trip by delegating logic to the client.
Users expect smoothness, not convention. iOS and Android have behavioral norms: gesture directions, navigation styles, and error recovery patterns. Breaking these creates confusion. Respecting them means our system must adapt its flows accordingly.
Takeaway: Mobile user interactions are fast, sensory, and unforgiving. Systems must be designed to keep up with them, not just with back-end logic but also with the fluidity and pace of user behavior.
Designing for gestures and immediacy shows how closely mobile systems are tied to the user experience. But behind every swipe and tap is an operating system, a set of platform rules, and a growing ecosystem of APIs, all with opinions about how your app behaves.
And they don’t always work in our favor.
5. Ecosystem complexity
We’ve built a great feature that syncs real-time tasks across devices. But suddenly, users start reporting inconsistencies. Some updates don’t show up, and others lag for minutes. What’s going on?
On Android 13, background tasks are throttled unless the user explicitly adds our app to the allow list for unrestricted background activity. On iOS, background sync windows are tiny, and the opportunity disappears altogether if our app isn’t launched in time.
Unlike the web, where the browser is our gatekeeper, mobile development lives inside a tightly controlled OS sandbox. Our app’s behavior is shaped by:
Background execution limits.
Battery optimization policies.
Permission and consent flows.
Platform-specific SDK quirks.
Security restrictions on sensors, location, storage, and notifications.
And these rules change with every OS version, as illustrated below:
Even seemingly small tasks, like fetching location, reading local files, or sending a push notification, can fail silently if we haven’t designed for platform-specific constraints. Worse, our app may behave differently across devices even with the same OS version.
The ecosystem around them shapes mobile systems.
Designing resilient systems means tracking these policies, using platform APIs carefully, and building graceful fallbacks when the platform says “no.”
So far, we’ve explored how devices, networks, and OS behaviors shape mobile systems. But beyond those technical constraints lies something even more sensitive: user data, and the trust users place in your app to handle it responsibly. Let’s talk about it.
6. Security and privacy
Every time users install our app, they grant access to functionality and a piece of their personal world. And they’re trusting that we’ll handle it all safely. We may be handling:
Precise location data.
Contacts and messages.
Health metrics.
Files, photos, camera, or microphone input.
Access tokens and credentials.
Unlike the web, where browsers sandbox most interactions, mobile apps deal directly with sensitive APIs, and the system often defers security decisions to developers. That means our architecture must protect data in transit, at rest, in memory, and during device-level events like app switching or backgrounding.
Missteps are costly. Worse, platform restrictions may evolve: what was once allowed may now require explicit permissions or justification through system review (like iOS’s privacy nutrition labels or Android’s scoped storage enforcement). A mobile system is only as secure as its weakest layer, as illustrated below:
Design decisions here ripple across the entire stack. Should sensitive data be stored locally or encrypted and streamed? Should user actions work offline, and if so, how will they be secured until synced? What data could your app leave behind if the device is lost or compromised?
Takeaway: In mobile, our system runs in a personal, portable, and vulnerable environment. Security is a full-system obligation, and we should consider it from the very start, i.e., during System Design.
Let’s now summarize the key differences between the web and mobile:
Aspect | Web System Design | Mobile System Design |
Device runtime | Stable, consistent browser environment | Volatile, OS-controlled app life cycle |
Hardware diversity | Minimal impact; browser abstracts differences | Huge variability in CPU, RAM, battery, and sensors |
Network | Reliable, continuous connection | Intermittent, flaky, or unavailable at times |
Client role | UI-focused, thin frontend | Logic-heavy, stateful, sync-capable edge node |
Deployment model | CI/CD, instant updates | App store delays, fragmented adoption |
Interaction model | Keyboard + mouse, indirect input | Touch, gestures, sensors, and voice |
UX expectations | Tolerant of latency and reloads | Demands instant, fluid feedback with no hiccups |
Platform constraints | Few, consistent across browsers | OS policies, background limits, and permission models |
Security concerns | Mostly server-side | Data on-device, sensor access, runtime protection |
Conclusion
We started this lesson with a simple question: How is System Design for mobile different from the web?
We’ve now seen that the differences run deep, shaping not just how apps look but how they work, fail, recover, and evolve. From runtime behavior and network fragility to deployment delays and heightened security expectations, mobile presents a uniquely demanding design landscape.
But here’s the good news: These constraints aren’t roadblocks. They’re design signals. They push us to:
Be more thoughtful with state and sync.
Embrace failure as a design input.
Build experiences that respect the user’s world, not just our server’s state.
We'll build on this foundation as we move forward in this course. We’ll start with gathering mobile-specific requirements and exploring architectural patterns like BFF and offline-first sync. Then, we’ll design technically sound and context-aware systems.