Android Mobile System Design Interview Questions

Offline-first, sync, caching, and scale tradeoffs.

50 questions in this topic · 8 sample questions below

Practice Mobile System Design in the quiz engine

Sample questions

  1. In a truly offline-first app, what should be the single source of truth that the UI observes?

    • The local database, with the network layer only reconciling it in the background — correct
    • The remote server, with the local database used only as a temporary cache
    • The in-memory ViewModel state, rebuilt from the network on each screen entry
    • A shared in-memory cache that both UI and network mutate directly

    Why: Offline-first means the UI reads and writes the local store (e.g. Room) and observes it reactively, while sync updates that store asynchronously. Treating the server as the source of truth defeats offline capability because the UI stalls whenever the network is unavailable.

  2. Two devices edit the same record offline and later sync. A pure last-write-wins strategy keyed on server-receive time can silently lose data primarily because:

    • Last-write-wins requires vector clocks that mobile clients cannot compute
    • It cannot detect that two edits were concurrent, so the later-arriving write overwrites an unrelated earlier one — correct
    • Server-receive time is always identical for both writes, causing a tie
    • It duplicates the record instead of merging, creating two rows

    Why: LWW resolves conflicts by picking one write and discarding the other; keyed on arrival time it can discard a legitimate concurrent edit with no record that a conflict happened. Vector clocks are one way to detect concurrency, but LWW's flaw is data loss from undetected concurrency, not an inability to compute clocks.

  3. When syncing deletions in an offline-first system, why is a tombstone record usually preferred over simply removing the row locally?

    • Tombstones compress better than live rows on disk
    • Tombstones let the server skip conflict detection entirely
    • A hard local delete cannot be propagated to peers, so the record reappears on next sync from another device — correct
    • Hard deletes violate SQLite foreign-key constraints

    Why: A tombstone marks the record as deleted so the deletion itself can be synced; without it, another device still holding the row re-creates it as a fresh insert on the next pull. Foreign-key constraints are unrelated to why deletions need to be represented as syncable events.

  4. For an infinite feed where items are frequently inserted at the top, why does classic offset-based pagination (LIMIT/OFFSET) produce visible bugs?

    • Offset queries cannot be indexed, so they time out on large tables
    • Offset pagination loads the entire table into memory on the first page
    • The server cannot compute OFFSET without a total count, which is expensive
    • New inserts shift every item's offset, causing already-seen items to repeat or items to be skipped between pages — correct

    Why: Because offset counts positions rather than anchoring to a stable item, inserting rows above the current window shifts everything down, so page 2 re-serves rows already shown on page 1 or skips some. Cursor/keyset pagination anchors on a stable key and avoids this; the total-count cost is a performance nuance, not the correctness bug.

  5. In Paging 3, what is the specific role of a RemoteMediator when the database is the source of truth?

    • It is triggered when the local cache runs out of items to fill a page, fetches from the network, and writes into the database that the PagingSource reads — correct
    • It replaces the PagingSource and fetches directly from the network per page
    • It caches network responses in memory only, bypassing the database
    • It performs conflict resolution between local and remote edits before display

    Why: RemoteMediator handles boundary conditions: when the local DB can't satisfy the requested page it fetches more from the network and inserts into the DB, while a separate PagingSource still reads exclusively from the DB. It does not replace the PagingSource nor do conflict resolution.

  6. You cache full-resolution images but display them in small thumbnails and hit OutOfMemory. The most effective fix is:

    • Increase the memory cache size so more bitmaps fit
    • Downsample images to the target view size at decode time using inSampleSize before they enter the bitmap cache — correct
    • Switch the memory cache from LRU to FIFO eviction
    • Store bitmaps as PNG in memory instead of ARGB_8888

    Why: A decoded bitmap's memory cost is width times height times bytes-per-pixel regardless of file size, so decoding at the display resolution slashes per-bitmap RAM. Enlarging the cache stores the same oversized bitmaps and makes OOM worse; bitmaps in memory are uncompressed pixel buffers, not PNGs.

  7. With HTTP caching, what does an ETag combined with a conditional If-None-Match request buy you that a plain TTL does not?

    • It guarantees the client never makes a network request while the cache is fresh
    • It encrypts the cached payload so stale data cannot be read
    • When the TTL expires it lets the server answer 304 Not Modified with no body if content is unchanged, revalidating cheaply — correct
    • It removes the need for the server to send Cache-Control headers

    Why: An ETag enables cheap revalidation: after the freshness window lapses the client asks if the resource changed, and an unchanged resource returns a bodyless 304, saving bandwidth. A pure TTL forces a full re-download once it expires because there is no way to confirm the cached copy is still valid.

  8. The stale-while-revalidate caching pattern improves perceived latency by:

    • Blocking the UI until fresh data arrives, then rendering once
    • Never serving stale data and instead pre-fetching everything at startup
    • Discarding the cache the moment it becomes stale so the UI always shows a spinner
    • Immediately serving the stale cached value while asynchronously fetching a fresh one to update the cache — correct

    Why: Stale-while-revalidate returns the cached (possibly stale) response instantly for a responsive UI, then refreshes in the background so the next read is current. Blocking on the fresh fetch is exactly the latency the pattern avoids.

Practice all 50 Mobile System Design questions

These 8 are a sample. The full Mobile System Design bank is scored, tracks your progress, and explains every answer.

Open the quiz

More Android interview topics