Q239: Resilient Networking, Retries, Offline and Progressive Recovery
What Interviewers Want To Evaluate
Interviewers want to know whether you can design frontend networking that recovers gracefully from real-world failure.
They check retry strategy, backoff, idempotency, cancellation, offline detection, optimistic UI, partial failure, stale data, error classification, and user communication.
Short Interview Answer
Resilient networking starts by classifying failures and deciding which operations are safe to retry. Reads may retry with backoff, but mutations need idempotency keys or careful duplicate prevention. I use AbortController for cancellation, typed result states for UI, offline-aware messaging, stale cached data when safe, and progressive recovery so one failed panel does not break the whole route.
Detailed Interview Answer
Networks fail.
Users experience:
timeouts
offline mode
slow responses
server errors
rate limits
partial data
duplicate submissions
stale cache
cancelled navigation
Good frontend networking expects this.
Error Classification
Classify errors first.
type NetworkError =
| { kind: "offline"; message: string }
| { kind: "timeout"; retryable: true }
| { kind: "server"; status: number; retryable: boolean }
| { kind: "validation"; fields: Record<string, string> }
| { kind: "auth"; redirectTo: "/login" };
The UI should know what action is possible.
Retry Strategy
Retry safe operations.
Usually safe:
idempotent GET requests
metadata refresh
non-critical analytics with queue
Risky:
payments
form submissions
orders
state-changing mutations
Mutations need idempotency or user confirmation.
Backoff
Avoid retry storms.
Use exponential backoff with jitter.
Conceptually:
retry after 300ms
then 700ms
then 1500ms
add randomness
stop after limit
Retrying aggressively can make outages worse.
Idempotency
Idempotency prevents duplicate mutation effects.
Example:
client generates idempotency key
server stores result for that key
retry returns same result
duplicate order is avoided
This matters for payments, submissions, and important state changes.
Cancellation
Use AbortController for obsolete requests.
const controller = new AbortController();
fetch("/api/search", {
signal: controller.signal,
});
controller.abort();
This is useful for:
route changes
search input changes
modal close
component unmount
stale filters
Cancellation reduces wasted work and stale updates.
Offline Awareness
Offline handling should be honest.
Possible UX:
show cached content
disable submit with explanation
queue draft locally
show retry when online
preserve unsaved work
Do not pretend an action succeeded if it has not.
Stale Data
Stale data can be useful.
Examples:
show last-read handbook page
show cached profile shell
show previous search results with refresh indicator
Label stale data where decisions matter.
For security or money-sensitive data, be more conservative.
Partial Failure
Do not fail the entire route if one optional panel fails.
Example:
main article loads
related questions fail
progress sync fails
practice history fails
The reader should still read the article.
Localize errors.
Optimistic UI
Optimistic UI improves perceived speed.
But it needs rollback.
apply optimistic state
send mutation
confirm success
rollback or reconcile failure
show recoverable message
Use it when the success rate is high and rollback is understandable.
Common Mistakes
Common mistakes include:
retrying every request blindly
retrying mutations without idempotency
not cancelling stale requests
showing generic error messages
losing user input after network failure
blocking whole route for optional data
not distinguishing offline from server error
Resilience is mostly classification and recovery.
Senior Trade-Offs
Resilience adds complexity.
Use deeper patterns for:
critical workflows
forms
payments
offline-capable features
collaboration
large data sync
Use simpler retry and error states for low-risk content.
Interview Framing
In an interview, say:
I classify network failures, retry only safe operations with backoff, use idempotency for mutations, cancel stale requests, preserve user work, and localize failures so the rest of the page remains useful.
Revision Notes
- Not all failures should be retried.
- Mutations need idempotency or duplicate protection.
- Backoff prevents retry storms.
- AbortController handles stale requests.
- Offline UX should preserve work and communicate clearly.
- Partial failure should be localized.
Follow-Up Questions
- When should a request be retried?
- Why are retries dangerous for mutations?
- What is an idempotency key?
- How does AbortController improve UX?
- How would you design offline form recovery?
How I Would Answer This In A Real Interview
I would say frontend networking should expect failure. I would classify errors, retry safe reads with backoff and jitter, protect mutations with idempotency, cancel stale requests, show cached or partial content when safe, and preserve user input. I would avoid generic failure states and design recovery based on what the user can actually do next.