# IndexedDB Alternative - Why RxDB is the Better Choice

> Looking for an IndexedDB alternative? Discover why RxDB offers superior performance, ease of use, and built-in reactivity compared to raw IndexedDB.

# IndexedDB Alternatives

IndexedDB is the standard [browser storage](../articles/browser-storage.md) API for storing significant amounts of structured data, including files/blobs. It is available in every modern browser.
However, using the native IndexedDB API is **verbose**, **low-level**, and lacks many features modern applications need.

If you are looking for an **IndexedDB alternative**, you likely want a library that abstracts the complexity away and provides features like **Reactivity**, **Schema Validation**, and **Sync**.

RxDB is the ultimate alternative because it gives you the speed of a [local database](../articles/local-database.md) with the ease of use of a modern [JSON-document store](../rx-collection.md).

## The Problem with Raw IndexedDB

IndexedDB was designed as a low-level building block, not a developer-facing database engine.
Because of that, relying on raw IndexedDB (or thin wrappers) often leads to significant friction:

1.  **Callback Hell**: The API heavily relies on event handlers (`onsuccess`, `onerror`), making control flow difficult to read and maintain.
2.  **Missing Observability**: Standard IndexedDB provides no way to listen to data changes. You have to build your own event bus to update the UI when data changes.
3.  **Complex Transaction Management**: You must explicitly create transactions for every read or write, which is repetitive and error-prone.
4.  **No Schema Enforcement**: IndexedDB is schema-less. You can store anything, which sounds good until your app crashes because of inconsistent data structures.
5.  **Limited Querying**: You can only query by simple key ranges. Complex queries (like "find users older than 18 and sort by name") require manually iterating over cursors, which is slow and code-heavy. See [Slow IndexedDB](../slow-indexeddb.md).

RxDB solves all of these problems while maintaining the benefits of a local database.

## Why RxDB is the Best Alternative

RxDB is a NoSQL database for JavaScript applications. It uses [IndexedDB](../rx-storage-indexeddb.md) (or faster alternatives) under the hood but provides a rich, feature-complete API on top.

### 1. Developer Experience

RxDB offers a promise-based API that feels intuitive for JavaScript developers. It uses [JSON Schema](../rx-schema.md) to define your data structure, ensuring you never store invalid data.

**Raw IndexedDB:**
```js
const request = indexedDB.open('myDatabase', 1);
request.onupgradeneeded = (event) => { /* Handle versions */ };
request.onsuccess = (event) => {
  const db = event.target.result;
  const transaction = db.transaction(['users'], 'readonly');
  const store = transaction.objectStore('users');
  const getRequest = store.get('user1');
  getRequest.onsuccess = () => {
    console.log(getRequest.result); // Finally got the data
  };
};
```

**RxDB:**
```js
const db = await createRxDatabase({
  name: 'myDatabase',
  storage: getRxStorageDexie() // Uses IndexedDB under the hood
});
// Define collection once
await db.addCollections({
  users: { schema: myJsonSchema }
});
// Query data
const user = await db.users.findOne('user1').exec();
```

### 2. Reactivity (The "Rx" in RxDB)

Modern UIs ([React](../articles/react-database.md), [Vue](../articles/vue-database.md), [Angular](../articles/angular-database.md), Svelte) need to be reactive. When data changes, the view should update.
RxDB is built on **[RxJS](https://rxjs.dev/)**. Every query, document, or field can be observed.

```js
// Subscribe to a query -> UI updates automatically on change
db.users.find({
  selector: { age: { $gt: 18 } }
}).$.subscribe(users => {
  updateUI(users);
});
```
This works even across multiple browser tabs. If a user changes data in Tab A, Tab B updates instantly. Implementing this with raw IndexedDB and `BroadcastChannel` manually is a massive undertaking. See [Reactivity](../reactivity.md).

### 3. Advanced Query Engine

Searching for data in raw IndexedDB requires opening cursors and iterating over records manually, which is slow and complex.
RxDB includes [Mango Query](../rx-query.md) syntax (like MongoDB). You can filter, sort, and limit data with a simple JSON object.

```js
const results = await db.users.find({
  selector: {
    age: { $gt: 18 },
    role: { $in: ['admin', 'moderator'] }
  },
  sort: [{ name: 'asc' }],
  limit: 10
}).exec();
```

### 4. Synchronization

Raw IndexedDB is purely local. Usage in real-world apps usually requires syncing data with a backend.
Building a robust sync protocol (handling [offline](../offline-first.md) changes, conflict resolution, delta updates) is one of the hardest problems in software engineering.

RxDB solves this out of the box. It has a robust [replication protocol](../replication.md) that supports:
-   **[Real-time sync](../articles/realtime-database.md)**: Changes are pushed/pulled immediately.
-   **Conflict Resolution**: Strategies to handle concurrent edits.
-   **Multi-Backend**: Plugins for [CouchDB](../replication-couchdb.md), [GraphQL](../replication-graphql.md), [Firestore](../replication-firestore.md), [Supabase](../replication-supabase.md), and generic [HTTP](../replication-http.md).

### 5. Performance & Storage Engines

While IndexedDB is fast enough for simple tasks, it can be the bottleneck for high-performance apps due to serialization overhead and browser implementation details. See [RxStorage Performance](../rx-storage-performance.md).

RxDB abstracts the storage layer. You can start with IndexedDB and switch to unparalleled performance engines later without changing your application code:

-   **[Dexie.js RxStorage](../rx-storage-dexie.md)**: A optimized wrapper around IndexedDB.
-   **[OPFS RxStorage](../rx-storage-opfs.md)**: Uses the Origin Private File System, which is significantly faster than IDB for many operations.
-   **[SQLite RxStorage](../rx-storage-sqlite.md)**: Uses SQLite via WebAssembly (or Native in [React Native](../react-native-database.md)/[Electron](../electron-database.md)) for robust SQL-based storage.
-   **[Memory RxStorage](../rx-storage-memory.md)**: For ephemeral data or testing.

### 6. TypeScript Support

IndexedDB API is loosely typed. You often cast `any` or struggle with correct event types.
RxDB is written in TypeScript and provides first-class type safety. Your database schema generates TypeScript types, so you get autocomplete for every field in your documents and queries.

```ts
// TypeScript knows that 'age' is a number
const user = await db.users.findOne().exec();
console.log(user.age.toFixed(2));
```

### 7. Encryption & Compression

Storing sensitive data? RxDB has [Encryption](../encryption.md) built-in. You provide a password, and the data is stored encrypted at rest.
Storing lots of data? The [Key-Compression](../key-compression.md) plugin shrinks your JSON keys to minimize storage usage, often reducing database size by 40%+.

## Other Alternatives

There are other ways to store data in the browser, but they all have significant limitations compared to IndexedDB (and RxDB).

### LocalStorage
`localStorage` is a synchronous key-value store. See [Using localStorage](../articles/localstorage.md).
- **Why it fails**: It blocks the main thread (UI freezes on large reads/writes). It is capped at ~5MB. It only supports strings, so you must constantly `JSON.parse` and `JSON.stringify`.
- **Use case**: Simple settings like "dark mode: on".

### Cookies
Cookies are small pieces of data sent with every HTTP request.
- **Why it fails**: Extremely limited size (4KB). Wastes bandwidth by sending data to the server on every request.
- **Use case**: Session tokens, authentication.

### WebSQL
WebSQL was a wrapper around SQLite but is **deprecated** and removed from non-Google browsers.
- **Why it fails**: It is a dead standard. Do not use it.
- **Use case**: Legacy apps only.

### OPFS (Origin Private File System)
OPFS is a new high-performance file system API for the web.
- **Why it fails**: It is a file system, not a database. It has no indexing, no querying, and no document structure. It is extremely low-level.
- **Note**: RxDB *uses* OPFS in its [OPFS RxStorage](../rx-storage-opfs.md) to give you the performance of OPFS with the features of a real database.

## Comparison

| Feature | Raw IndexedDB |  **RxDB** |
| :--- | :--- | :--- |
| **Api Style** | Event-based / Callback | Promise / Observable |
| **Reactivity** | ❌ None | ✅ [Observables](../rx-query.md) / [Signals](../reactivity.md) |
| **Sync** | ❌ Manual Implementation | ✅ Built-in & Backend Agnostic |
| **Query Engine** | ❌ Basic Key-Range | ✅ [MongoDB-style (Mango)](../rx-query.md) |
| **Transactions** | ✅ Manual | ✅ Automatic |
| **Schema** | ❌ None | ✅ [JSON Schema](../rx-schema.md) |
| **Migrations** | ⚠️ Manual | ✅ [Declarative](../migration-schema.md) |
| **Multi-Tab Sync**| ❌ Manual | ✅ Automatic |
| **Encryption** | ❌ None | ✅ [Built-in](../encryption.md) |
| **TypeScript** | ⚠️ Partial | ✅ Full Support |

## Conclusion

If you are building a toy project, `localStorage` or a simple wrappers like `idb-keyval` might suffice.
But if you are building a **production application** that needs to be fast, reliable, and maintainable, relying on raw IndexedDB is a premature optimization that costs you development time.

**RxDB** is the "Battery Included" alternative that handles the hard parts of local data (sync, reactivity, queries) so you can focus on building your product. For further reading, check out [Why Local-First Software Is the Future](../articles/local-first-future.md) or [RxDB as a Database for Browsers](../articles/browser-database.md).
