MA5: Offline-first sync: outboxes, retries and conflicts
Deadlines, retries and backoff
🎯You'll be able to
Give every request a deadline, retry temporary failures with growing, randomised waits, and stop retrying changes the server refuses.
🏠The everyday picture
When a friend doesn't answer the phone, you try again in a few minutes, then later, then tomorrow. You don't ring every second, and if they've told you the number is wrong, you stop.
📘What it really is
-
Deadlines: a request with no answer could wait for ever on a bad network. KhetNote gives each request 10 seconds, then treats it as a failure (a timeout).
-
Temporary failures (no connection, timeouts, server errors like 500 or 503) are retried later.
-
Backoff: wait longer after each failure: about 1 s, 2 s, 4 s, up to 60 s. Jitter (a random part) spreads phones out, so a thousand phones coming back online don't all retry at the same second.
-
Permanent failures (400 or 422: the server says the change is wrong) aren't retried. Mark them as needing attention, and carry on with the other changes.
-
Record why: keep the attempts and the last error on each change, to show the user and to debug.
📝A worked example
Input: KhetNote's backoffDelay(attempt, random).
Steps:
- The ceiling doubles from 1,000 ms:
min(60000, 1000 × 2^(attempt − 1)). - The wait is between half and all of the ceiling:
ceiling × (0.5 + random × 0.5). - With
randomat 1: 1,000, 2,000, 4,000 ms; at attempt 10, 60,000 ms (the cap). Withrandomat 0: half of each.
Expected output: waits that grow, stop growing at a minute, and differ between phones.
🌍Where it's used
- Cloud SDKs retry with exponential backoff and jitter.
- App stores' download managers back off on bad networks.
- Push notification services retry delivery with growing gaps.
📝Case scenario
After a server outage, a ride app's phones all retried every second. When the server came back, the flood of retries took it down again, twice. Exponential backoff with jitter let it recover in minutes.
🖱️Try it
Work out the waits for attempts 1 to 7 with random at 0.5 (so each wait is 0.75 of the ceiling). Success: your numbers start at
750 ms and double, and the seventh is 45,000 ms, because its ceiling of 64,000 is capped to 60,000.
⚠️Common mistakes
- No deadline. Sign: a sync that never finishes on a weak network. Fix: a timeout on every request.
- Retrying instantly. Sign: retry storms. Fix: backoff with jitter.
- Retrying refused changes. Sign: the same 422 for ever, blocking everything. Fix: mark failed, carry on.
🛠️For your project
Project 1's tests 6 and 7 check backoff, refused changes and the 10-second deadline.
✅Quick check
Why add a random part to the backoff wait?
Show the answer
So many phones coming back at once don't all retry at the same moment.
Which responses should not be retried?
Show the answer
Refusals such as 400 and 422, where the change itself is wrong.
