DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. IndexedDB: Client-Side Database for Web Apps
XLinkedInReddit
MediumFrontend Engineering

IndexedDB: Client-Side Database for Web Apps

D
DevPrep Team
February 10, 2026·1 min read·0
Table of Contents
  • Why IndexedDB?
  • Basic Operations with idb Library
  • Transactions
  • Offline-First Pattern
  • Best Practices

IndexedDB is a full NoSQL database in the browser. At Google, we use it for offline-first applications and caching large datasets.

Why IndexedDB?

StorageCapacitySync/AsyncData Type
localStorage5MBSynchronousStrings only
sessionStorage5MBSynchronousStrings only
IndexedDBGBsAsynchronousAny structured data

Basic Operations with idb Library

import { openDB } from "idb";

// Create/upgrade database
const db = await openDB("MyApp", 1, {
  upgrade(db) {
    const store = db.createObjectStore("articles", { keyPath: "id" });
    store.createIndex("by-date", "publishedAt");
    store.createIndex("by-category", "categoryId");
  }
});

// Create
await db.put("articles", {
  id: "article-1",
  title: "Hello World",
  publishedAt: new Date(),
  categoryId: "tech"
});

// Read
const article = await db.get("articles", "article-1");

// Read all
const allArticles = await db.getAll("articles");

// Query by index
const techArticles = await db.getAllFromIndex("articles", "by-category", "tech");

// Delete
await db.delete("articles", "article-1");

Transactions

const tx = db.transaction("articles", "readwrite");
const store = tx.objectStore("articles");
await Promise.all([
  store.put({ id: "1", title: "First" }),
  store.put({ id: "2", title: "Second" }),
  tx.done // Wait for transaction to complete
]);

Offline-First Pattern

async function getArticles() {
  // Try network first
  try {
    const response = await fetch("/api/articles");
    const articles = await response.json();
    // Cache in IndexedDB
    const tx = db.transaction("articles", "readwrite");
    articles.forEach(a => tx.objectStore("articles").put(a));
    await tx.done;
    return articles;
  } catch {
    // Fall back to cached data
    return db.getAll("articles");
  }
}

Best Practices

  • Always use a wrapper library like idb — the raw API is callback-based and painful
  • Version your schema and handle upgrades carefully
  • Use indexes for any field you query by
  • Keep transactions short — they auto-commit when idle
  • Handle QuotaExceededError gracefully

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • Why IndexedDB?
  • Basic Operations with idb Library
  • Transactions
  • Offline-First Pattern
  • Best Practices

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.