How Apps Actually Work
A guide for someone who already understands APIs.
1. The mental model: apps are API clients
The single most useful frame: a mobile app is another client for the same APIs a website uses. When you tap "order" in the McDonald's app, the app sends an HTTPS request with a JSON body to an endpoint, gets a JSON response, and renders it. The HTTP contract can be the same whether the request comes from a browser, a Python script, or a Kotlin app.
This is why companies invest in good APIs: one backend can serve the website, the Android app, the iOS app, and partner integrations. Everything about status codes, auth headers, pagination, and error handling transfers directly. A server can identify clients deliberately through app metadata or separate endpoints, but it does not need a different protocol for each one.
Browser ─────────┐ Android app ──────┤──► HTTPS + JSON ──► The same API backend ──► Database iOS app ──────────┤ Python script ────┘
That is the server's view: many clients, one API.
Treat this lesson as the map, not the full journey. From here on it surveys native apps, the installed, store-distributed kind. Later lessons implement login, push, offline sync, frameworks, payments, and security in detail. For now, notice what changes when your API's client lives on a phone.
2. Anatomy of a native app
An app is easier to understand as five cooperating parts. The UI sits above application state and business rules; that application layer coordinates networking, local storage, and services supplied by the operating system. These are architectural responsibilities rather than a rigid stack, but the separation stops every screen becoming a tangle of HTTP calls and database code.
UI layer
Instead of HTML/CSS, screens are declared in a UI toolkit, either the platform's own or a cross-platform one. Conceptually similar to templating, and the modern toolkits are reactive: the UI is a function of state, and re-renders automatically when state changes.
Examples
- Jetpack Compose (Android)
- SwiftUI (iOS)
- Flutter widgets
- React Native components
Application state and business logic
This is the part that decides what the app should do: which user is signed in, whether an order can be submitted, what the current screen should show, and whether data should come from the network or the local cache. The UI observes this state; repositories or data services hide where the data came from.
Responsibilities
- State management
- Business rules
- Navigation
- Repositories
Networking
The equivalent of Python's requests: the same verbs, headers, status codes, and JSON parsing. Mobile adds practical pressure around timeouts, cancellation, limited data, and retries, but the HTTP fundamentals do not change.
Examples
- Retrofit / OkHttp (Android)
- URLSession (iOS)
- dio (Flutter)
Local storage
The web has persistent storage too, but native apps have richer storage APIs and users expect them to survive a flaky or absent connection. Apps commonly keep a local database and reconcile it with the API when online. A lot of real complexity lives in deciding what happens when the user acts offline and the server changes in the meantime.
What lives here
- SQLite / Room (Android)
- Core Data / SwiftData (Apple)
- Caching
- Offline queue
- Conflict resolution
Platform services
Push notifications, location, camera, background jobs. These go through OS-level APIs and permission prompts, and each has its own registration dance. Push, for instance, means your backend stores a device token and sends to it via Google's FCM or Apple's APNs, never directly to the phone.
Examples
- Push (FCM / APNs)
- Location (GPS)
- Camera / Photos
- Background jobs
- Device sensors
- Contacts, Calendar
3. How apps stay logged in
Those five parts are the machinery. The first place mobile habits differ from browser habits is keeping a user signed in.
Websites typically let the browser manage cookies and sessions. Native networking libraries can use cookies too, and browser-based sign-in flows often do, but native API clients usually favour token-based auth:
- Log in once; receive an access token (often a JWT) plus a long-lived refresh token.
- Store them in the platform's secure storage: the Keychain on iOS; on Android, encrypted storage whose encryption keys are held by the Keystore. Never in plain files or preferences.
- Attach
Authorization: Bearer <token>to every request. - When the access token expires, silently exchange the refresh token for a new one.
This is the same OAuth-shaped world API books cover, with a different storage location. Long-lived clients make refresh-token rotation important: each refresh issues a new refresh token and invalidates the old one, limiting the value of a stolen token.
One more principle to absorb now: an installed app is a public client. Anything shipped inside the binary can be extracted, so an app never holds a client secret; the login and security lessons both build on that fact. The next lesson follows the login flow request by request.
4. The lifecycle is hostile in ways the web isn't
Browsers discard background pages too, and careful web apps save drafts for exactly that reason; the difference is one of degree and expectation. On mobile, the OS backgrounds, freezes, and kills apps routinely to reclaim memory, then resurrects them, sometimes mid-flow, and the user expects to land back exactly where they left off. Well-built apps therefore save state constantly and restore it seamlessly; the user should never notice their app was killed while they were in another app.
The OS also throttles background work aggressively to protect battery life. "Sync while the app isn't open" is genuinely hard. A background push may give the app time to fetch fresh data, or a visible notification may prompt a fetch when the user returns, but delivery and execution are not guaranteed. The push lesson explains those limits in detail.
Why this matters to an API designer: mobile clients reconnect after long gaps, retry aggressively on flaky networks, and replay queued offline actions. APIs that serve mobile apps well tend to need idempotency keys (so a retried order isn't a duplicate order), efficient "what changed since timestamp X" endpoints, and tolerant auth expiry handling.
5. Shipping to the stores is a pipeline, not a push
Lesson 1 established the store-and-release difference. The short version here is the consequence for your API:
Where a website deploys with a git push, an app release looks like:
- Bump the version number.
- Build a signed bundle. The signing key proves authorship; losing it is a serious problem, so it lives in secure storage or the store's managed-signing service.
- Upload to the Play Console / App Store Connect and wait for review (hours to days).
- Commonly, a staged rollout: release to 5% of users, watch the crash-rate dashboards, ramp to 100% only when the numbers hold.
Because you can't instantly fix a bad release, mobile teams lean hard on two things:
- Crash reporting (Crashlytics, Sentry): every crash in the field is captured with a stack trace and phoned home.
- Feature flags: code ships dark and is switched on remotely, so turning a broken feature off doesn't need a new release or a review cycle.
The API consequence: old app versions linger on users' phones for months, so a mobile-serving API must preserve compatibility for a long time. Prefer additive changes where possible; when you truly need a breaking contract, a new path such as /v2/ is one versioning option. Mobile is a strong reason for API versioning, not the only one.
6. Money in the stores, briefly
Lesson 1 introduced the physical-versus-digital distinction. Keep that distinction here; leave the changing rates and regional exceptions to Payments in Apps.
| Model | How it works | Store cut? |
|---|---|---|
| Paid up front | Pay once to download. Nearly dead outside niche tools and games | Yes |
| In-app purchases / subscriptions | Free download, with paid digital upgrades or recurring access | Usually; rates and permitted alternatives vary |
| Ads | Free app, attention sold to ad networks. The free-game economy | No cut on ad revenue |
| Storefront for physical goods/services | The takeaway model: app is free, money changes hands for real-world things via your own payment processor | No |
Recurring revenue makes subscriptions attractive, but there is no single store rate: programmes, product types, regions, and alternative-payment rules change the result. The durable idea is the physical-goods carve-out from Lesson 1; always check the current policy before designing a checkout.
7. Where to go deeper
The rest of the course takes each part of this map in turn:
- A login flow end to end: what actually happens, request by request, from tapping "log in with Google" to an authenticated session. Deep OAuth territory.
- Push notifications end to end: the full backend → FCM/APNs → device path, token management, and delivery guarantees. The most API-flavoured piece of mobile.
- Cross-platform frameworks compared: Flutter vs React Native vs Kotlin Multiplatform, and how teams choose.
- Your path to a first app: tooling, emulators, and a realistic learning path for a Python developer.
- Offline data and sync: the local-storage layer taken seriously: the outbox pattern, conflict handling, and the API features a sync-ready backend needs.
- Payments in apps: store billing versus your own processor, and the entitlements layer that unifies them, with the current rates and exceptions this lesson left out.
- Real-time and WebSockets: the networking layer taken further: chat and live updates when request-response runs out of road, and what a stateful backend costs.
- Mobile security: the public-client idea taken to its conclusion: what it means that the binary, the traffic, and the device are all in the user's hands.
- App architectures: eight case studies: the capstone. WhatsApp, Uber, Spotify, McDonald's, and four more, remixing every pattern above.
Check your understanding
- Why can one API contract serve a website, native apps, and a Python script? Does the server needing to know which client is calling change that?
- A screen must show cached orders instantly and refresh them from the API in the background. Which of the five anatomy parts makes that call, and which two does it coordinate?
- Why can a mobile app never hold a client secret, and where should it keep the user's tokens instead?
- A mobile client retries requests on flaky networks and replays queued offline actions. What API features does that behaviour push you towards?
- Why must an API behind a mobile app stay backwards-compatible longer than one behind a website?
Sources and further reading
Reviewed 6 August 2026.