← Назад к вопросам

Какое ограничение места в IndexedDB?

2.0 Middle🔥 91 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Общие лимиты IndexedDB и их природа

IndexedDB — это низкоуровневое API для хранения больших объемов структурированных данных в браузере. В отличие от Web Storage (локальное хранилище), IndexedDB не имеет жесткого, единого лимита вроде «5 МБ» или «10 МБ». Его ограничения определяются комбинацией факторов: свободным местом на диске, глобальными квотами хранилища браузера, политикой «группы происхождения» (origin) и реализацией в конкретном браузере.

Ключевые принципы квотирования

1. Квота на источник (Origin Storage Quota)

Браузеры выделяют каждому источнику (протокол + домен + порт) общий лимит для всех типов постоянного хранилища: IndexedDB, Cache API, локальное хранилище файловой системы (File System Access API). Эта квота обычно динамическая.

  • Chrome/Edge: примерно 80% свободного места на диске делится между всеми посещенными сайтами. На практике это может составлять гигабайты на современных устройствах, если диск почти пуст.
  • Firefox: использует гибридную модель — минимум 2 ГБ на источник, но может быть больше в зависимости от свободного места.
  • Safari: традиционно более консервативен — примерно 1 ГБ на источник (но может меняться в новых версиях).

2. Принцип «просить нельзя, брать» (Quota Management API)

Чтобы записать данные сверх небольшого начального лимита (обычно несколько десятков МБ), сайт должен явно запросить увеличение квоты через navigator.storage.estimate() и navigator.storage.persist(). Пользователь при этом не видит стандартного диалога подтверждения — браузер принимает решение на основе эвристик (частота посещений, важность сайта).

// Пример проверки и запроса квоты
async function checkAndRequestQuota() {
  // Получаем текущее использование и квоту
  const estimation = await navigator.storage.estimate();
  console.log(`Используется: ${estimation.usage} байт`);
  console.log(`Квота: ${estimation.quota} байт`);

  // Просим браузер сохранить данные персистентно
  const isPersisted = await navigator.storage.persist();
  console.log(`Данные сохранятся после очистки? ${isPersisted}`);
}

checkAndRequestQuota();

3. Лимиты на уровне базы данных и объекта

  • Размер одной записи: теоретически ограничен размером квоты, но на практике лучше не хранить объекты > 100-200 МБ из-за производительности и ограничений сериализации.
  • Количество баз данных: обычно несколько десятков на источник.
  • Количество хранилищ объектов (Object Stores): сотни на базу данных.

Практические ограничения и обходные пути

Стратегии работы с большими объемами

  1. Разбивка данных: вместо одного огромного объекта храните связанные данные в отдельных записях.

    // Плохо: один огромный объект
    // await store.put({ id: 1, hugeData: ... });
    
    // Лучше: разбить на части
    await store.put({ id: 1, part: 0, data: chunk1 });
    await store.put({ id: 1, part: 1, data: chunk2 });
    
  2. Компрессия данных: сжатие массивов, строк перед сохранением.

    // Пример с простой компрессией JSON
    const data = { /* большой объект */ };
    const compressedString = LZString.compress(JSON.stringify(data));
    await store.put({ id: 1, compressed: compressedString });
    
  3. Инкрементальное хранение: сохранять только дельты изменений.

Ограничения по производительности

  • Транзакции имеют timeout (по умолчанию 60 секунд в некоторых браузерах).
  • Синхронные операции отсутствуют — все асинхронное.
  • Параллельные транзакции на одном хранилище могут блокировать друг друга.

Пример обработки переполнения

async function safePut(store, data) {
  try {
    await store.put(data);
  } catch (error) {
    if (error.name === 'QuotaExceededError') {
      // 1. Пробуем очистить устаревшие данные
      await clearOldData(store);
      
      // 2. Пробуем снова
      try {
        await store.put(data);
      } catch (retryError) {
        // 3. Запрашиваем больше места
        const granted = await requestMoreQuota();
        if (granted) {
          await store.put(data);
        } else {
          throw new Error('Недостаточно места даже после запроса');
        }
      }
    } else {
      throw error;
    }
  }
}

Важные нюансы

  • Режим инкогнито: квоты обычно значительно меньше (50-100 МБ), данные удаляются после закрытия окна.
  • Мобильные браузеры: могут иметь более агрессивные политики очистки при нехватке места.
  • Прогрессивные веб-приложения (PWA): могут получить повышенные лимиты через beforeinstallprompt и явный запрос персистентности.

Рекомендации для разработчиков

  1. Всегда обрабатывайте QuotaExceededError.
  2. Используйте navigator.storage.estimate() для мониторинга.
  3. Реализуйте graceful degradation при нехватке места.
  4. Для критичных данных используйте navigator.storage.persist().
  5. Тестируйте на реальных устройствах с разным заполнением диска.

В итоге, практический лимит IndexedDB составляет от 1 до 10+ ГБ для обычных сайтов при наличии свободного места на диске, но успешная работа с объемами > 100 МБ требует тщательного проектирования архитектуры хранения и обработки ошибок.

Какое ограничение места в IndexedDB? | PrepBro