Mobile App Developer · Focus area 2: Mobile architecture

MA5: Offline-first sync: outboxes, retries and conflicts

Goal: build an app that saves first on the phone and syncs when it can: keep an outbox of changes, send each once even when answers are lost, retry patiently with deadlines and backoff, fetch only what changed, settle conflicts by clear rules, and tell the user in plain words whether their work is safe.

You'll need: MA4, Module 24 (Asynchronous Programming), Module 47 (REST API Design), Module 57 (Transactions and Indexes), Module 94 (Distributed Systems), and the KhetNote practice kit (src/sync/, server/, tests/offline.test.js).

Where this is used: field apps, messaging, notes, email, maps and any app used on trains, in lifts or in villages. Offline-first apps feel fast everywhere, because saving never waits for the network.

How it differs: a simple app asks the server and shows an error when there's no signal. An offline-first app treats the phone's copy as the place work happens, and the network as something that comes and goes.

Time: reading about 3 hours · practice (the Try it tasks) about 3 hours · assignment about 5 hours.

Lessons

  1. 1Save first, sync laterReading 15–25 minutes, plus practice✓
  2. 2Sending each change onceReading 15–25 minutes, plus practice✓
  3. 3Deadlines, retries and backoffReading 15–25 minutes, plus practice✓
  4. 4Fetching what changedReading 15–25 minutes, plus practice✓
  5. 5Conflicts and what the user seesReading 15–25 minutes, plus practice✓

🛠️Assignment: Make KhetNote work offline

  1. Make saving write to the store and the outbox, without waiting for the network.
  2. Make the sync engine send changes oldest first with idempotency keys, and start when the connection returns.
  3. Add the 10-second deadline, backoff with jitter, and marking refused changes as failed.
  4. Fetch changes since the stored cursor, and keep waiting changes on screen.
  5. Handle 409s by the merge rule, recording clashes, and show one status message.
  6. Write docs/sync-design.md, then run npm run test:offline.

Self-check before you finish:

✅Module check

Explain in a few sentences, in your own words:

How does an offline-first app keep the user's work safe and get it to the server?

Show a good answer

A good answer mentions: saving to the phone first with a pending state and an outbox of changes in order, removed only when the server confirms; idempotency keys so repeated sends are stored once; syncing after saves, on reconnect and regularly; deadlines on every request, backoff with jitter for temporary failures, and failed marks for refused changes; fetching changes since a stored cursor while keeping waiting changes on screen; versions, 409s and a written conflict rule that keeps edits and flags clashes; and one plain status message, announced to screen readers.

📚Official references

Official documentation and guidance for this module's topics, chosen on 2 November 2026. Tools, laws and standards change, so check the current version before you rely on a detail. If a link has moved, search the same site.

📝Module quiz

10 questions · 10 marks each · 100 marks in all · pass mark 70% · retry as often as you like ·

1. An adviser saves a visit with no signal. What should happen?

Why each option is right or wrong

  • “An error appears asking the adviser to try again later” (Incorrect): The work would depend on signal.
  • “The app waits with a spinner until signal returns” (Incorrect): That could take hours.
  • “The visit is kept in memory until the next sync” (Incorrect): Memory is lost if the app closes.
  • “It's saved on the phone as pending, in the outbox” is correct.

    Saving doesn't wait for the network.

    • Shown: "Offline · 1 change waiting".

📖 Revise: Lesson 1: Save first, sync later

Question ID sp-mobile-05-q1 · Report a mistake in this question
2. When should a change be removed from the outbox?

Why each option is right or wrong

  • “As soon as it has been sent once” (Incorrect): The send may have failed.
  • “After a fixed time, such as one hour” (Incorrect): It may not have reached the server.
  • “When the user opens the visit again” (Incorrect): That has nothing to do with the server.
  • “When the server confirms it was stored” is correct.

    Only confirmation proves it arrived.

    • Until then: it stays, with attempts recorded.

📖 Revise: Lesson 1: Save first, sync later

Question ID sp-mobile-05-q2 · Report a mistake in this question
3. A change's answer was lost after the server stored it. The phone sends it again. What stops a duplicate?

Why each option is right or wrong

  • “Waiting a full day before sending it to the server again” (Incorrect): The repeat is still a repeat.
  • “A new key for every attempt, so each is unique” (Incorrect): Then the server can't spot repeats.
  • “Sending the change by text message instead” (Incorrect): That's another channel with the same problem.
  • “The same idempotency key, so the server replies once” is correct.

    The key identifies the change, not the attempt.

    • Header: Idempotency-Key.

📖 Revise: Lesson 2: Sending each change once

Question ID sp-mobile-05-q3 · Report a mistake in this question
4. Why does KhetNote stop sending when the oldest change fails?

Why each option is right or wrong

  • “To save battery while the phone is offline” (Incorrect): Battery isn't the reason.
  • “Because the server accepts only one change a day” (Incorrect): There's no such limit.
  • “Because failed changes should be deleted first” (Incorrect): Failed sends are kept and retried.
  • “So later changes don't arrive before earlier ones” is correct.

    Order matters when changes touch the same visit.

    • But: refused changes are marked and skipped.

📖 Revise: Lesson 2: Sending each change once

Question ID sp-mobile-05-q4 · Report a mistake in this question
5. A request on a weak network neither succeeds nor fails, and the sync doesn't finish. What's missing?

Why each option is right or wrong

  • “A bigger outbox, so that many more changes can wait” (Incorrect): Size doesn't end the wait.
  • “A faster phone with more memory and a newer processor” (Incorrect): The network is the problem.
  • “More frequent syncs, as often as once every second” (Incorrect): They'd all hang the same way.
  • “A deadline (10 s), after which it counts as failed” is correct.

    Timeouts turn waiting for ever into a retry.

    • Then: back off before the next try.

📖 Revise: Lesson 3: Deadlines, retries and backoff

Question ID sp-mobile-05-q5 · Report a mistake in this question
6. After a server outage, thousands of phones retry every second and knock it over again. What helps most?

Why each option is right or wrong

  • “Retrying even more often, so each phone gets through sooner” (Incorrect): That adds load.
  • “Stopping all retries until the user presses a button” (Incorrect): Changes would wait unnecessarily.
  • “One fixed wait of five seconds on every phone” (Incorrect): Phones still retry together.
  • “Waits that grow after each failure, with a random part” is correct.

    Backoff and jitter spread the retries out.

    • KhetNote: 1 s, 2 s, 4 s… up to 60 s.

📖 Revise: Lesson 3: Deadlines, retries and backoff

Question ID sp-mobile-05-q6 · Report a mistake in this question
7. The server answers 422 to a change: "areaAcres must be a number above 0". What should the app do?

Why each option is right or wrong

  • “Retry it with backoff until the server accepts it” (Incorrect): The same change gets the same refusal.
  • “Delete the visit from the phone without telling anyone” (Incorrect): The adviser's work is lost silently.
  • “Stop syncing everything until the app is updated” (Incorrect): One bad change shouldn't block the rest.
  • “Mark it as needing attention, and send the other changes” is correct.

    A refusal won't fix itself.

    • Shown: "1 change needs attention".

📖 Revise: Lesson 3: Deadlines, retries and backoff

Question ID sp-mobile-05-q7 · Report a mistake in this question
8. A sync fetches every visit each time and uses a lot of mobile data. What's the fix?

Why each option is right or wrong

  • “Sync only once a week” (Incorrect): Data would be stale.
  • “Compress the data more on the phone” (Incorrect): It still downloads everything.
  • “Turn off pulls entirely” (Incorrect): The phone would miss office changes.
  • “Fetch changes since a stored cursor” is correct.

    Only new changes are sent.

    • Example: GET /visits?since=3.

📖 Revise: Lesson 4: Fetching what changed

Question ID sp-mobile-05-q8 · Report a mistake in this question
9. While a change waits in the outbox, a pull brings the server's older copy of that visit. What should the screen show?

Why each option is right or wrong

  • “The server's copy, replacing the adviser's edit” (Incorrect): The edit would seem to vanish.
  • “Both copies side by side as separate visits” (Incorrect): That confuses the list.
  • “Nothing, hiding the visit until sync finishes” (Incorrect): The adviser loses sight of their work.
  • “The adviser's version until the change is sent” is correct.

    Local waiting changes win on screen.

    • Then: the merged result after sync.

📖 Revise: Lesson 4: Fetching what changed

Question ID sp-mobile-05-q9 · Report a mistake in this question
10. Offline, an adviser changes a visit's advice. Meanwhile the office changes the same visit's advice differently. What does KhetNote do?

Why each option is right or wrong

  • “Keeps the office's value and drops the adviser's” (Incorrect): The adviser's work is lost silently.
  • “Keeps whichever change reached the server last” (Incorrect): That's last writer wins, which hides the loss.
  • “Rejects both changes and asks everyone to start again” (Incorrect): That throws away good work.
  • “Keeps the adviser's value and flags the clash too” is correct.

    Nobody's edit vanishes unseen.

    • Banner: "1 change needs attention".

📖 Revise: Lesson 5: Conflicts and what the user sees

Question ID sp-mobile-05-q10 · Report a mistake in this question

ProLearners Assist