System Design

Optimistic Updates

mediumdata_state

Optimistic Updates

Asked In

MetaTwitterLinearNotionUberAirbnb

Key Challenges

  • ·Paint the UI before the server confirms
  • ·Roll back cleanly when the request fails
  • ·Avoid double-applies under retries
  • ·Never invent irreversible money or destructive state
★

Guided Answer

Read this path first — then deepen in RADIO below

Simple Explanation

User taps Like. If the heart waits for the network, the app feels slow — even when your API is fine.

Optimistic updates paint success first, then check with the server. The hard part is not the happy path. It is rollback, retries, and knowing when this pattern is dishonest.

Mental Model

It is a reversible bet.

1) Snapshot current state 2) Paint the success UI 3) Send the request with an idempotency key 4) Keep the bet on success, or restore the snapshot on failure

If you cannot undo the action, do not bet.

Diagrams

Architecture — who owns the bet
Component node + responsibility notes
LikeButton
OptimisticMutation
snapshot S
apply local success
POST with Idempotency-Key
confirmkeep UI
errorrestore S + retry
Server
source of truth after confirm
Flow — happy path and failure
Component node + responsibility notes
Happy path
1

tap Like

2

save snapshot S

3

paint liked = true — (instant)

4

POST /like

5

200 OK — keep UI

6

same steps until POST

7

error — restore S + show retry

Step-by-Step

1

Scene — the slow Like

User taps Like. A 400ms spinner teaches them the app is laggy. Perceived speed is the product.

Say this

“I would optimistically paint reversible social actions so the UI feels instant.”

2

Naive move

Two common mistakes: wait for the server before painting, or setLiked(true) with no snapshot. The first feels slow. The second cannot recover on failure.

Say this

“The naive approaches are wait-for-server or mutate-with-no-rollback.”

3

Where it breaks

The request fails after you already showed success. Without a snapshot you cannot restore. Retries without an idempotency key can double-apply. Optimistic payment capture lies about money.

  • ·Ghost success after a 500
  • ·Double-apply on retry
  • ·Irreversible domains

Say this

“It breaks when failure has no snapshot, retries are not idempotent, or the action cannot be undone.”

4

The fix

Snapshot → apply locally → send request with an idempotency key → confirm or roll back. Show a retryable error. Never leave a fake success on screen.

const snapshot = post;
apply({ liked: true });
try { await like(post.id, key); }
catch { replace(snapshot); toast('Retry'); }

Say this

“I snapshot, apply locally, send an idempotent request, and roll back on failure.”

5

When NOT to use it

Payments, hard deletes, security changes, and inventing server truth (including fake LLM answers) stay pessimistic — or use a clear pending state the user understands.

Say this

“I would not optimistically capture payment or invent irreversible state.”

Final Answer

Optimistic UI is a reversible bet. I snapshot state, paint success, and confirm with an idempotent request. Failures restore the snapshot and offer retry. I use it for likes, follows, and cart adds — not for payments, hard deletes, or invented server truth.

Deep Dive — RADIO Framework

★

2-Minute Answer — High-Level TL;DR

Read this before your interview

HLD Interview Focus

Optimistic updates paint the success state immediately, then confirm with the server. I snapshot prior state, apply the local mutation, fire the request with an idempotency key, and on failure restore the snapshot and surface retry. I would not use it for payments or hard deletes without a clear undo path — those stay pessimistic.

→

My Approach: Building the Solution

How to think about this problem

Start with a Like button. User taps. Waiting 400ms for the heart to fill feels broken. Then show how the same pattern destroys trust if you 'optimistically' mark an order paid.

Why This Approach?

Most candidates say 'just update local state.' Seniors name the snapshot, the failure path, idempotency, and the domains where optimism is banned.

Optimistic UI is writing a check before the bank clears it. Fine for coffee. Terrible for wiring your rent without a backup plan.

R

Requirements: What Makes a Great Solution?

Clarify scope before designing anything

Requirements Exploration Questions

Ask your interviewer these questions to refine requirements

Is the action reversible?

  • ·Like / unlike
  • ·Add to cart
  • ·Mark read
  • ·Pay / delete account

What does failure look like?

  • ·Rollback + toast
  • ·Keep pending + retry
  • ·Conflict merge

Functional Requirements

Must Have — MVP

  • ✓Snapshot before mutate
  • ✓Apply local update
  • ✓Request with idempotency key
  • ✓Rollback on failure

Advanced (If Time Permits)

  • +Outbox queue for offline
  • +Conflict merge for collaborative edits

Non-Functional Requirements

Interview bar

  • ·Name the invariant in one sentence
  • ·Give one concrete failure of the naive approach
  • ·State when the pattern is the wrong tool
A

Architecture (Conceptual)

Component structure, data flow, rendering strategy

Component Hierarchy

Top-Level: OptimisticMutation

  • ·Snapshot + apply
  • ·Track in-flight by idempotency key
  • ·Rollback or confirm
component-hierarchy-tree/
ONE APP · CLEAR BOUNDARIES
UI Control
useOptimisticMutation
snapshot
applyLocal
confirm | rollback
↓imports flow one way: features use ui, data-access, and utils; utils imports nothing

React-Specific Architecture Patterns

OptimisticMutation

  • ·Snapshot + apply
  • ·Track in-flight by idempotency key
  • ·Rollback or confirm
architecture-diagram/
ONE APP · CLEAR BOUNDARIES
LikeButton
OptimisticMutation
snapshot S
apply local success
request + Idempotency-Key
confirm(keep UI)
rollback(restore S + error)
↓imports flow one way: features use ui, data-access, and utils; utils imports nothing

Why React Query + Zustand?

Keep teaching state next to the concept; libraries are secondary.

D

Data Model (API + Entities + Cache)

Entities, interfaces, cache shape, consistency rules

Minimal entities that make the concept concrete in code reviews and whiteboards.

MutationRecord

Source: Client
Belongs to: Outbox
Fields: id, idempotencyKey, snapshot, status
concept.ts
async function optimisticLike(postId: string, store: Store) {
  const key = crypto.randomUUID();
  const snapshot = store.getPost(postId);
  store.apply(postId, { liked: true, likes: snapshot.likes + 1 });
  try {
    await api.like(postId, { headers: { 'Idempotency-Key': key } });
  } catch {
    store.replace(postId, snapshot);
    store.toast('Could not like — retry');
  }
}
I

Interface Design (React Integration)

API contracts, hooks, integration patterns

Contracts are light for core concepts — prove the idea, not a full product API.

O

Optimization (Performance + Scale)

Rendering, media, network, and memory optimizations

Optimistic updates paint the success state immediately, then confirm with the server. I snapshot prior state, apply the local mutation, fire the request with an idempotency key, and on failure restore the snapshot and surface retry. I would not use it for payments or hard deletes without a clear undo path — those stay pessimistic.

Sticky rules

  • ·Optimistic UI is a bet: show the success state, keep a rollback snapshot.
  • ·On failure, restore the snapshot and show a retryable error — do not leave a ghost success.
  • ·Idempotency keys stop retries from applying twice.
  • ·Do not optimistically charge cards, delete irrevocable data, or invent LLM answers.

Optimistic Updates

Most candidates say 'just update local state.' Seniors name the snapshot, the failure path, idempotency, and the domains where optimism is banned.

optimisticUpdate.ts
async function optimisticLike(postId: string, store: Store) {
  const key = crypto.randomUUID();
  const snapshot = store.getPost(postId);
  store.apply(postId, { liked: true, likes: snapshot.likes + 1 });
  try {
    await api.like(postId, { headers: { 'Idempotency-Key': key } });
  } catch {
    store.replace(postId, snapshot);
    store.toast('Could not like — retry');
  }
}

Remember

Optimistic UI is a bet: show the success state, keep a rollback snapshot.

Say this in the interview

“Optimistic updates paint the success state immediately, then confirm with the server.”

+

Bonus: Implementation Cookbook (Optional)

LLD snippets — only when asked by interviewer

Follow-ups interviewers use after you nail the core idea.

Included (Minimal)

  • ·Outbox queue for offline
  • ·Conflict merge for collaborative edits

Key Takeaways

  • ✓Optimistic UI is a bet: show the success state, keep a rollback snapshot.
  • ✓On failure, restore the snapshot and show a retryable error — do not leave a ghost success.
  • ✓Idempotency keys stop retries from applying twice.
  • ✓Do not optimistically charge cards, delete irrevocable data, or invent LLM answers.