Backends for mobile apps cheat sheet

The 8 Backends for mobile apps interview answers in 30 seconds each, plus quick facts. Printable, free.

One page per topic: print it or save it as PDF from your browser's print menu. Practise these questions

Rules of thumb

  • Push is a hint; apps fetch real state when opened.
  • Store UTC instants; keep IANA zone names for local rules.
  • One call per screen for mobile; aggregate on the server.
  • Sync with server versions, cursors and tombstones.
  • Force-update check from version 1; compare versions numerically.
  • Verify purchases with the store, server-side.

Sending push notifications at scale

Store device tokens per user and platform, refreshed whenever the app reports a new one. A notification request goes onto a queue; workers expand it to devices, respect each user's preferences and quiet hours, and call APNs and FCM over persistent HTTP/2 connections in batches, with rate limits and retries with backoff for temporary errors. Remove tokens the provider reports as invalid. Push is best-effort, so the app must fetch the real state when opened.

Time zones and timestamps

Store instants in UTC (PostgreSQL timestamptz, which normalises to UTC), send them in ISO 8601 with an offset or Z, and convert to local time only for display on the client. Store a user's IANA time zone name (like Asia/Kolkata), not a fixed offset, when you need local rules like 'remind me at 9 AM', because offsets change with daylight saving. Future local events (a meeting at 10:00 next March) are stored as local time plus zone.

from datetime import UTC, datetime
from zoneinfo import ZoneInfo

stored = datetime(2026, 10, 31, 15, 30, tzinfo=UTC)
print(stored.astimezone(ZoneInfo("Asia/Kolkata")).strftime("%H:%M"))
print(stored.astimezone(ZoneInfo("America/New_York")).strftime("%H:%M"))

Backend for frontend (BFF)

A backend-for-frontend is an API shaped for one client. It aggregates several internal services into one call per screen, trims payloads to what the app shows, and handles mobile concerns like versioning for old app releases and image sizes. That cuts round trips on slow networks and lets the mobile team change their API without negotiating with every service. The cost is another service to run; GraphQL is an alternative way to let clients shape responses.

An API for offline sync

Give each change a server-side, monotonically increasing version, and expose 'give me changes since cursor N', returning changes plus the next cursor, including deletions as tombstones. Uploads carry client-generated ids and a base version so retries are idempotent and conflicts are detectable; resolve them with a rule per field (last writer wins, merge, or ask the user). Keep tombstones long enough that offline devices still see deletions.

Minimum supported app versions

Every request sends the app version and platform in a header. The backend keeps a minimum supported version per platform (configurable, not hard-coded) and a 'recommended' version. Below the minimum, it returns a specific error that the app knows to show as a 'please update' screen; between minimum and recommended, a soft prompt. Compare versions numerically, not as strings, and track the version distribution before raising the floor.

def parse(v: str) -> tuple[int, ...]:
    return tuple(int(p) for p in v.split("."))


MIN_SUPPORTED = parse("4.10.0")
for v in ["4.9.3", "4.10.0", "4.12.1"]:
    print(v, parse(v) >= MIN_SUPPORTED)

Serving images to mobile apps

Store originals in object storage and serve resized variants from a CDN. Either pre-generate a few sizes on upload, or use an on-the-fly resizing service behind the CDN with an allow-list of sizes so attackers can't request endless variants. Serve modern formats (WebP, AVIF) where supported, set long cache lifetimes with content-hashed URLs, and have the API return the URL for the size the client asks for.

Verifying in-app purchases on the server

Never trust the app saying 'purchase succeeded'. Send the transaction to your server, verify it with the store's server API (Apple's App Store Server API with signed transactions, Google Play Developer API), then grant entitlements in your database keyed to the user. Subscribe to the stores' server notifications (App Store Server Notifications, Google Real-time Developer Notifications) for renewals, refunds and cancellations, and make processing idempotent by transaction id.

API performance on mobile networks

Round trips dominate on mobile, often 100 ms or more each, so cut them: one call per screen, HTTP/2 or HTTP/3 connection reuse, and no redirect chains. Shrink payloads with sparse fields, pagination and compression. Make responses cacheable with ETags so repeat visits cost a 304. Support retries safely with idempotency keys and short client timeouts, and return partial data instead of failing the whole screen when one dependency is slow.

Quick facts

US DST end 2026
US daylight saving time ends on Sunday 1 November 2026, so New York is UTC−4 on 31 October.
India offset
Asia/Kolkata is UTC+5:30 all year; India doesn't use daylight saving.
Google Play acknowledgement
Purchases not acknowledged within three days are automatically refunded.
timestamptz
PostgreSQL stores timestamptz as a UTC instant and displays it in the session's TimeZone.