frontend May 14, 2026 Sunny Sharma
When IndexedDB beats Redux
Two state-management choices that look similar from a distance. They behave very differently when the network goes wrong, and the choice between them often decides whether a regulated surface ships at all.
architecture react
State management in a React or React Native app is one of those decisions that looks like a stylistic preference and turns out to be an operational one. The debate around Redux versus Zustand versus Jotai versus TanStack Query is usually a debate about ergonomics, code shape, and dev experience. That is the easy axis. The harder axis is what happens to your state when the network fails, when the user force-quits the app mid-action, when a tab is restored from the browser’s back-forward cache, or when a service worker decides to evict your memory.
For most products, ephemeral state is enough and the choice between in-memory libraries is more or less a matter of taste. For some products, ephemeral state is the wrong answer entirely. The state has to survive the kind of failure that loses everything in memory. That is where IndexedDB earns its keep, and where the choice between IndexedDB and a Redux-style library is not stylistic at all.
What Redux is good at
Redux (and the in-memory state libraries that have largely replaced it) is excellent for ephemeral UI state. The current tab. The expanded row. The contents of a form before submission. The optimistic update before the server confirms. The shape of “what is on the screen right now” lives in memory because it does not need to outlive the page render. If the user closes the tab, the state goes with it. That is fine. The state was never load-bearing.
This works well for products where the user’s action either succeeds (and the server now holds the truth) or fails (and the user retries). Most B2B SaaS products fit this shape. Most marketing and content surfaces fit this shape. Most non-regulated mobile apps fit this shape.
What IndexedDB is good at
IndexedDB is durable. Data written to it survives the tab closing, the browser restarting, and most service worker evictions. It is slower than memory, has an asynchronous API that is awkward to use directly (which is why every team writes a wrapper), and has subtle quotas and eviction rules across browsers. None of these is a deal-breaker for the use cases where IndexedDB is the right answer.
The use cases are the ones where memory is the wrong place for the state.
The audit-trail queue. Every user action on a regulated surface emits an event. The event has to survive a network drop. The event has to survive the user closing the tab between clicking submit and the server acknowledging. The event has to be reconciled with the server-side log later. We treat the audit trail as a first-class component backed by IndexedDB, not as a logger. The audit hook writes to IndexedDB first, then attempts to flush to the server. If the flush fails, the event sits in IndexedDB until connectivity returns.
The offline-payment queue. A field operator using a mobile payments app on patchy network needs every queued payment to survive being out of signal for forty minutes. Redux would lose those payments the moment the app is force-quit. IndexedDB holds them durably, with deduplication on a per-payment idempotency key so the eventual server-side replay does not double-charge.
Form-state recovery. A long form (a KYC application, an insurance claim) that takes the user 25 minutes to fill in cannot afford to lose state if the browser tab is accidentally closed. Auto-save to IndexedDB at every meaningful step, restore on tab reopen. Most teams reach for localStorage for this; localStorage works for small forms but hits its 5MB quota fast on rich-document forms, and IndexedDB is the correct tool above that threshold.
Caching for a slow API. A dashboard that pulls a 4MB analytics rollup from the warehouse cannot afford to wait for that fetch on every page load. IndexedDB stores the last-known rollup with a TTL. Redux would lose the cache between page loads.
Where the choice matters most
The choice between IndexedDB and an in-memory library matters most in two situations.
The first is when the consequence of losing state is regulatory rather than UX. Losing a draft tweet is a UX problem. Losing an audit event that should have recorded a payment authorisation is a regulatory problem. The cost of getting this wrong, in regulated finance, is not “the user has to retry.” The cost is a gap in the audit trail that the team has to explain in writing to a regulator a year later. IndexedDB is the answer not because it is faster or more elegant. It is the answer because the state has to be durable.
The second is mobile and offline-first. Mobile apps that operate under genuinely unreliable network conditions (field tools, mobile payments in rural areas, in-store retail) cannot trust that any in-memory state will reach the server. IndexedDB on React Native (via libraries like WatermelonDB or RxDB, or platform-native equivalents on iOS/Android) is the right shape for state that is generated faster than the network can flush it.
When you need both
A surprising number of regulated mobile apps need both. The UI state lives in memory (cheap, fast, ergonomic). The audit and queue state lives in IndexedDB (durable, network-resilient, reconcilable). They are not alternatives; they are different layers of the state model that happen to have similar shapes from a distance.
The common mistake is to use Redux for both. The team picks Redux for the UI state because the UI state is fast-moving and ergonomic. Then they add an “audit slice” to the Redux store, treat the audit slice the same way as the UI slice, and discover six months later that the audit data has been silently lost across browser restarts because Redux is, by default, in-memory.
The other common mistake is the inverse: use IndexedDB for everything. The performance is poor, the async API friction is constant, and the dev experience suffers. Most state does not need durability; using IndexedDB for it is over-engineering.
When you need neither
If your product is a marketing site, a non-regulated B2B dashboard, or a content surface where users are not generating state that needs to outlive the page, you probably need neither IndexedDB nor a Redux-style library. TanStack Query for server state, React’s built-in useState for ephemeral UI state, and you are done. Adding a state library to a product that does not need durable state is a tax the team will pay forever.
The decision tree, in one paragraph
Pick by the failure mode. If losing the state is a UX inconvenience, use in-memory (Redux, Zustand, Jotai, useState). If losing the state is a regulatory or operational incident, use IndexedDB. If your product has both shapes, use both, with explicit boundaries between them. Do not let the audit slice live in the UI store. Do not let the UI slice pay the IndexedDB cost. Most surfaces are simpler than the debate around them suggests; the choice is just a question of which failure mode you have, and the answer is usually visible by week three of the engagement.
02. Newsletter
More on engineering for serious teams, monthly.
Practitioner notes on the work behind real FinTech systems. One short essay or case study a month. No marketing, no sequences. Reply to talk.
Prefer RSS? Subscribe to the feed →
More from the blog
All posts