Что такое IndexedDB и для чего он нужен?

MiddleJavaScript · Frontend·Обновлено 15 августа 2026
Коротко
IndexedDB — это встроенное в браузер асинхронное транзакционное NoSQL-хранилище для структурированных данных (включая файлы и blob), которое в отличие от localStorage не блокирует главный поток и поддерживает объектные хранилища, индексы и большие объёмы данных.

Что такое IndexedDB

IndexedDB — низкоуровневое браузерное API для хранения структурированных данных на клиенте, включая файлы и blob-объекты. Это полноценная транзакционная объектная база данных (NoSQL), которая работает асинхронно и позволяет хранить существенно больший объём данных, чем localStorage — лимит обычно зависит от свободного места на диске, а не фиксирован жёстко.

Основные понятия

  • База данных (database) — именованное хранилище с номером версии, открывается через indexedDB.open(name, version).
  • Хранилище объектов (object store) — аналог таблицы в реляционной БД, хранит JS-объекты по ключу.
  • Индекс (index) — позволяет искать записи не только по первичному ключу, но и по значению другого поля объекта.
  • Транзакция (transaction) — все операции чтения и записи выполняются в рамках транзакции с режимом readonly или readwrite над одним или несколькими object store.
  • Курсор (cursor) — механизм последовательного перебора записей хранилища.

Асинхронность и событийная модель

API построено на событиях, а не на промисах: методы add, get, put, delete возвращают объект IDBRequest, у которого нужно слушать onsuccess и onerror. Это исторически неудобно, поэтому на практике почти всегда используют обёртки — библиотеку idb или собственный Promise-wrapper.

Версионирование схемы

При открытии базы указывается номер версии. Если он больше текущей версии в браузере, срабатывает событие onupgradeneeded — единственное место, где разрешено создавать или удалять object store и индексы. Попытка изменить схему вне этого колбэка приведёт к ошибке.

Отличие от localStorage

  • localStorage хранит только строки, работает синхронно и блокирует главный поток, лимит около 5-10 МБ.
  • IndexedDB хранит структурированные данные (объекты, Blob, File, ArrayBuffer), работает асинхронно, лимит значительно больше, поддерживает индексы и полноценные транзакции.

Когда использовать

  • Offline-first приложения и PWA — хранение данных для работы без сети.
  • Кеширование в связке с Service Worker, например по стратегии cache-then-network.
  • Хранение больших объёмов данных: файлов, изображений, результатов сложных запросов.

Ограничения

Doступ к базе ограничен same-origin политикой, квоты различаются между браузерами, а для гарантии, что браузер не очистит хранилище автоматически, стоит запрашивать persistent storage через navigator.storage.persist().

Что хочет услышать интервьюер

Понимание, что это асинхронная транзакционная NoSQL база данных в браузере, а не просто «localStorage побольше»

Знание ключевых сущностей: database, object store, index, transaction, cursor

Понимание событийной природы API и того, зачем нужны обёртки вроде библиотеки idb

Знание механизма версионирования и назначения onupgradeneeded

Понимание сценариев использования (offline, PWA, большие данные) и отличий от localStorage/sessionStorage

Пример: Работа с IndexedDB через нативное API

// Открываем (или создаём) базу данных версии 1
const request = indexedDB.open('shop', 1);

// Вызывается только при создании базы или повышении версии
request.onupgradeneeded = (event) => {
  const db = (event.target as IDBOpenDBRequest).result;
  // создаём хранилище объектов с ключевым полем id
  const store = db.createObjectStore('products', { keyPath: 'id' });
  // добавляем индекс для поиска по названию товара
  store.createIndex('byName', 'name', { unique: false });
};

request.onsuccess = (event) => {
  const db = (event.target as IDBOpenDBRequest).result;

  const tx = db.transaction('products', 'readwrite');
  const store = tx.objectStore('products');

  store.add({ id: 1, name: 'Клавиатура', price: 2500 });

  tx.oncomplete = () => console.log('Транзакция завершена');
};

request.onerror = (event) => {
  console.error('Ошибка открытия базы данных', (event.target as IDBOpenDBRequest).error);
};

Пример: Тот же код с промис-обёрткой idb

import { openDB } from 'idb';

async function getProducts() {
  const db = await openDB('shop', 1, {
    upgrade(db) {
      const store = db.createObjectStore('products', { keyPath: 'id' });
      store.createIndex('byName', 'name');
    },
  });

  // читаем все записи из хранилища одним асинхронным вызовом
  return db.getAll('products');
}

Типичные ошибки

Путают IndexedDB с localStorage, называя её просто key-value хранилищем для строк

Считают API синхронным и пытаются использовать await напрямую без промис-обёртки

Забывают, что менять схему (создавать object store, индексы) можно только внутри onupgradeneeded

Не знают, что транзакция автоматически завершается, как только не остаётся активных запросов

Не упоминают ограничения: same-origin политику, различия квот между браузерами и возможность автоматической очистки данных

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее