Dexie.js: A Minimalist Wrapper Around IndexedDB That Actually Makes Sense
If you've ever tried to use IndexedDB directly, you know the pain. The API is verbose, callback-heavy, and full of gotchas. You end up writing tons of boilerplate just to save and retrieve a simple object. That's where Dexie.js comes in. It's a thin, promise-based wrapper that makes IndexedDB feel like a modern database you'd actually want to use.
Dexie.js doesn't try to be everything to everyone. It focuses on one thing: making IndexedDB simple, fast, and reliable. And it nails it.
What It Does
Dexie.js is a lightweight JavaScript library that wraps the native IndexedDB API with a clean, Promise-based interface. You define your database schema using a simple syntax, then use familiar methods like add, put, get, update, delete, and filter to work with your data. It handles all the transaction boilerplate, error edge cases, and version upgrading for you.
Under the hood, it maps your schema to IndexedDB object stores and indexes. But you don't need to think about that. You just write code that looks like this:
// Define a database with a "friends" table
const db = new Dexie('MyDatabase');
db.version(1).stores({
friends: '++id, name, age'
});
// Add a friend
await db.friends.add({ name: 'Alice', age: 30 });
// Query by name
const alice = await db.friends.where('name').equals('Alice').first();
That's it. No onupgradeneeded, no onsuccess, no digging through IDBRequest objects.
Why It's Cool
What makes Dexie.js stand out is how much thought went into the developer experience. Here are a few things that really shine:
Promise-based everything. Every operation returns a native Promise. You can use async/await, .then(), or chain them. No callback hell.
Live queries with React integration. Dexie comes with a useLiveQuery hook for React that automatically re-renders your components when the underlying IndexedDB data changes. No manual invalidation or polling. It just works.
Powerful query API without SQL. You get compound queries, sorting, filtering, limit, offset, and full-text search. But you write it with chainable methods like .where('age').above(18).and(item => item.name.startsWith('A')). It feels natural.
Automatic schema migration. When you change your database schema, Dexie handles version upgrades seamlessly. You don't have to write migration scripts unless you want to.
Works in all modern browsers. It's built on IndexedDB, which has wide support. Dexie also falls back gracefully to in-memory storage in environments without IndexedDB.
Tiny bundle size. Around 12KB minified and gzipped. That's smaller than most state management libraries that do way less.
Dexie is especially useful for offline-first apps, local-first tools, note-taking apps, todo lists, or any client-side data that needs persistence without a backend. It's also a great fit for Electron or Chromium-based apps where you want a local database but SQLite feels heavy.
How to Try It
Getting started is as simple as adding the script or installing via npm:
npm install dexie
Or include it from a CDN:
<script src="https://unpkg.com/dexie/dist/dexie.js"></script>
Then open your browser's dev tools and start playing:
const db = new Dexie('test');
db.version(1).stores({ items: '++id, name' });
await db.items.add({ name: 'Hello World' });
const result = await db.items.toArray();
console.log(result); // Array with your item
The official documentation has a live playground and many examples: dexie.org
Final Thoughts
Dexie.js is one of those libraries that feels like it was written by a developer who actually had to build real applications with IndexedDB. It strips away the accidental complexity and leaves you with something that just works. If you've been avoiding IndexedDB because of the API, give Dexie a shot. It might change your mind about client-side storage entirely.
Whether you're building a quick prototype or a production offline app, Dexie is a solid, well maintained choice. It's not flashy, but it's incredibly practical.
Follow us on X: @githubprojects
Repository: https://github.com/dexie/Dexie.js