# React Native Async Storage: SQLite-backed key-value storage for mobile apps

> Async Storage gives React Native apps a persistent key-value API modelled on Web Storage, but backed by SQLite on Android, iOS and macOS and IndexedDB on the web. This is what version 3.1.1 actually ships, and where it stops being the right choice.

**react-native-async-storage/async-storage** — An asynchronous, persistent, key-value storage system for React Native.

- Repository: https://github.com/react-native-async-storage/async-storage
- Website: https://react-native-async-storage.github.io
- Stars: 5,070 · Forks: 483
- Language: Kotlin
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/react-native-async-storage-async-storage

## What problem Async Storage solves for React Native apps

React Native has no built-in persistence layer. Anything you want to survive an app restart has to be written somewhere yourself, and the platforms disagree about where. Async Storage is the answer the ecosystem settled on: a single JavaScript API, modelled on the browser's Web Storage API, that maps to SQLite on Android, iOS and macOS and to IndexedDB on the web. You call setItem and getItem; the native side decides what that means.

The README is direct about the threat model. It calls the library "an asynchronous, unencrypted, persistent key-value storage solution". Unencrypted is the operative word. This is the store for a cached user profile, a theme preference, an onboarding flag, the last sync timestamp. It is not the store for an access token you would be unhappy to see in a device backup.

The audience is React Native application developers who need persistence that works the same way on every platform they ship to. The API surface is deliberately small, and the README notes it comes with "additional extensions for batch operations and multi-database support", which is where version 3 departs from the older single-store design.

## How the storage backend differs across Android, iOS, macOS and web

The architecture is a thin JavaScript layer over per-platform native implementations. On Android, iOS and macOS the backing store is SQLite. On web it is IndexedDB. That split matters because the guarantees are not identical: SQLite on a phone is a file in the app sandbox, while IndexedDB is subject to browser eviction rules that no mobile developer has to think about.

The README's platform list also flags two platforms as second-class. visionOS and Windows are described as "legacy fallback, single database only". If your product ships to either, the multi-database feature is not available to you, and the README does not document what the fallback uses underneath.

The compatibility table is the other half of the architecture story. iOS and Android need React Native 0.76 or newer, macOS needs 0.78, and visionOS and Windows need 0.79. The native toolchain has its own floors: Kotlin 2.1.0, Android minSdk 24, iOS minimum target 13, macOS minimum target 12. Those numbers are not advisory. An app pinned to an older React Native cannot use version 3 at all.

The repository is a Yarn workspace monorepo. The published package lives under packages/async-storage, and the examples/ directory holds separate sample apps for react-native, expo, web and Compose targets. The root package.json declares node ^22.18.0 and yarn 4.9.4, which is the toolchain you need to build the library from source rather than consume it from npm.

## Installing Async Storage and storing a first value

Installation is two steps on Apple platforms and one everywhere else. The package comes from npm or yarn:

```bash
npm install @react-native-async-storage/async-storage
```

or, if your project uses yarn, the README gives the equivalent:

```bash
yarn add @react-native-async-storage/async-storage
```

On iOS and macOS there is a CocoaPods step. Run it from inside the macos or ios directory:

```bash
pod install
```

After that, the README's usage example shows the shape of the API. You create a named storage instance rather than importing a singleton, which is the version 3 change that enables multiple databases:

```typescript
import { createAsyncStorage } from "@react-native-async-storage/async-storage";

const storage = createAsyncStorage("appDB");

async function demo() {
  await storage.setItem("userToken", "abc123");
  const token = await storage.getItem("userToken");
  console.log("Stored token:", token); // abc123
  await storage.removeItem("userToken");
}
```

Every method returns a promise. The console line prints abc123 on the first run after the write, and the same value on the next launch of the app, which is the persistence claim being exercised. If you are migrating from the version 2 default import, that import shape is not what the current README documents; the createAsyncStorage factory is.

## Where Async Storage is the wrong tool: secrets, size and scale

The README says unencrypted, and it means it. Values written through Async Storage are stored in plain form in the platform's backing store. On a rooted or jailbroken device, in a device backup, or through a debugging tool attached to the app, those values are readable. A refresh token, a password, a private key: none of these belong here, and the related search phrase "async storage vs secure storage" exists precisely because developers hit this wall. The library does not offer an encrypted mode, and the README does not claim one.

The second boundary is volume. SQLite will happily hold megabytes, but the API is a key-value interface with no query language, no indexes you control, and no partial reads. If you need to filter, sort or join, you are loading everything into JavaScript and doing it there. At that point you want a real database, not a key-value wrapper.

The third is the platform gap. visionOS and Windows are single-database legacy fallbacks. A codebase that assumes createAsyncStorage can be called with several database names will not behave the same way on those targets, and the README gives no detail on what the fallback does when you try.

## Async Storage compared with MMKV

The comparison developers actually search for is Async Storage versus MMKV, and the difference is in the storage engine and the API contract. MMKV is a synchronous key-value store built on memory-mapped files, which is why its reads return values directly rather than through a promise. Async Storage is asynchronous by design, matching the Web Storage API's promise-based shape, and it sits on SQLite or IndexedDB rather than on a mapped file.

That difference shows up in two places. First, call sites: with Async Storage every read is awaited, which pushes storage access into async functions and makes it awkward to read a value during the initial synchronous render of a component. Second, the platform story: Async Storage's README documents Android, iOS, macOS, visionOS, web and Windows, while a memory-mapped native store is a different porting exercise per platform.

Neither is strictly better. If your bottleneck is reading a small value on every frame, the synchronous API is the point. If your requirement is one API that behaves the same on web and on mobile, Async Storage's IndexedDB backend is the thing MMKV does not offer. The README does not benchmark either case, so treat any performance claim in this area as unverified.

## Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-10. The most recent published release is @react-native-async-storage/async-storage@3.1.1, dated 2026-05-29, following 3.1.0 on 2026-05-21 and 3.0.3 on 2026-05-19. The three releases landing within ten days suggests a stabilisation period after the version 3 rewrite rather than a steady drip of features.

Upgrade cost is dominated by the version 3 API change. The README's usage example imports createAsyncStorage and constructs a named instance, which is a different call shape from a default-imported singleton. Any codebase on version 2 will need to touch every module that imports the package. On top of that, the React Native minimums (0.76 for iOS and Android, 0.78 for macOS, 0.79 for visionOS and Windows) mean an upgrade may require bumping React Native itself first.

The licence is MIT, which permits commercial and closed-source use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive licence with no copyleft obligation and no source-disclosure requirement. This is a description of the licence text, not legal advice; if your organisation has specific compliance rules, read LICENSE in the repository root.

## Conclusion

Adopt Async Storage when you need a small, persistent, unencrypted key-value store shared across iOS, Android, macOS and web, and when your React Native version meets the compatibility table (0.76 for iOS and Android, 0.78 for macOS, 0.79 for visionOS and Windows). Do not adopt it for secrets, for large binary blobs, or for visionOS and Windows if you need more than a single database, because the README describes those two platforms as legacy fallbacks with single-database support only. Before writing code, verify two things: that your project's React Native version is at or above the table's minimum for your target platform, and that your iOS minimum target is at least 13 and your macOS minimum target is at least 12, since the pod install step will fail below those.

## FAQ

### How do I install Async Storage in a React Native project?

Install the package with npm install @react-native-async-storage/async-storage or yarn add @react-native-async-storage/async-storage, then run pod install from inside the ios or macos directory on Apple platforms.

### How do I use Async Storage in React Native?

The README's example imports createAsyncStorage, calls it with a database name such as "appDB", and then awaits setItem, getItem and removeItem on the returned instance. Every operation returns a promise.

### What is Async Storage in React Native?

It is an asynchronous, unencrypted, persistent key-value storage solution for React Native applications, with an API compatible with the Web Storage API plus extensions for batch operations and multi-database support.

### Is Async Storage persistent?

The README describes it as persistent, and the values are held in SQLite on Android, iOS and macOS and in IndexedDB on the web, so they survive an application restart. Persistence on the web is still subject to the browser's own storage rules.

### Is Async Storage safe for storing sensitive data?

No. The README states plainly that the storage is unencrypted, and it documents no encrypted mode, so tokens, passwords and keys should go into a platform secure storage facility instead.

### Is Async Storage a database?

It is a key-value store, but on Android, iOS and macOS it is implemented on top of SQLite, and on the web on top of IndexedDB. The API exposes no query language, so it is not a database you can filter or join against.

## Sources

- [License: MIT](https://github.com/react-native-async-storage/async-storage/blob/main/LICENSE)
- [Project website](https://react-native-async-storage.github.io)
- [react-native-async-storage/async-storage on GitHub](https://github.com/react-native-async-storage/async-storage)
- [README](https://github.com/react-native-async-storage/async-storage/blob/main/README.md)
- [Releases](https://github.com/react-native-async-storage/async-storage/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/react-native-async-storage-async-storage
