Ограничения объёма хранилища в IndexedDB

Модель квотирования в браузерах

IndexedDB не предоставляет фиксированного и заранее известного размера хранилища. Вместо этого используется модель квотирования (storage quota), в которой каждый источник (origin) получает динамически управляемый лимит. Этот лимит зависит от множества факторов: свободного дискового пространства, политики браузера, типа устройства и уровня активности пользователя.

Браузер рассматривает IndexedDB как часть общего хранилища origin, куда также входят:

  • localStorage
  • sessionStorage
  • Cache Storage (Service Workers)
  • другие API хранения

Все эти системы делят общий бюджет, поэтому фактический лимит IndexedDB всегда контекстный.


Примерные ограничения по браузерам

Точные значения не стандартизированы и могут изменяться, но наблюдаются типичные диапазоны:

  • Google Chrome / Chromium-браузеры

    • До ~60% свободного диска
    • На практике часто ограничение начинается около 5–10% общего диска
    • Для отдельных origin может достигать десятков гигабайт
  • Firefox

    • Использует более строгую модель
    • Обычно ограничение порядка 10% свободного места или фиксированный потолок
    • Может применять агрессивную очистку при нехватке места
  • Safari

    • Наиболее ограничительная модель
    • Особенно на iOS: часто 50–500 МБ для неактивных сайтов
    • Возможна автоматическая очистка без уведомления

Разброс значений делает невозможным проектирование системы хранения на основе фиксированного числа мегабайт.


Динамическое перераспределение квоты

Современные браузеры применяют динамическое управление квотой, при котором:

  1. Приложение запрашивает запись данных

  2. Браузер проверяет доступное пространство

  3. При нехватке:

    • операция отклоняется с ошибкой QuotaExceededError
    • или инициируется очистка менее приоритетных данных

Особенность IndexedDB заключается в том, что ошибка переполнения возникает не заранее, а в момент записи транзакции.


Причины появления ограничения

Ограничения обусловлены несколькими факторами:

  • предотвращение неконтролируемого роста данных веб-приложений
  • защита дискового пространства пользователя
  • обеспечение справедливого распределения ресурсов между сайтами
  • предотвращение злоупотреблений (например, скрытого заполнения диска)

Eviction policy: автоматическое удаление данных

Некоторые браузеры используют механизм eviction (вытеснение данных). Он активируется при критической нехватке места.

Типичный порядок удаления:

  1. Кэшированные данные (Cache Storage)
  2. Неактивные origin
  3. IndexedDB с наименьшей активностью
  4. Локальные данные, не помеченные как persistent

Важно, что IndexedDB может быть удалена полностью без запроса к пользователю, особенно на мобильных платформах.


Persistent storage и его влияние

Существуют механизмы повышения устойчивости данных.

navigator.storage.persist().then((granted) => {
  console.log(granted);
});

Если разрешение получено, браузер старается:

  • не удалять данные при очистке памяти
  • не применять агрессивный eviction
  • сохранять IndexedDB даже при нехватке места

Однако это не отменяет квоты полностью, а лишь повышает приоритет хранения.


Поведение при достижении лимита

При переполнении IndexedDB возможны следующие сценарии:

  • QuotaExceededError при записи
  • частичный успех транзакции (в зависимости от реализации)
  • откат операции целиком
  • блокировка дальнейших записей до освобождения места

Библиотеки вроде localForage обычно не управляют квотами напрямую, а лишь пробрасывают ошибки выше уровня абстракции.


Особенности хранения в localForage

localForage использует IndexedDB как основной драйвер, поэтому наследует все ограничения:

  • отсутствие гарантированного объёма хранения
  • зависимость от политики браузера
  • различия между платформами

При этом API localForage скрывает детали транзакций, из-за чего ошибка переполнения проявляется только на уровне промисов:

localforage.setItem('key', largeData)
  .catch(err => {
    console.error(err.name);
  });

При ошибке переполнения обычно возвращается объект ошибки с именем QuotaExceededError.


Различия между десктопом и мобильными устройствами

Мобильные браузеры вводят более строгие ограничения:

  • меньший доступный объём диска
  • агрессивная очистка при нехватке памяти
  • ограничение фоновых приложений
  • возможное удаление данных при перезапуске системы

На десктопе IndexedDB ведёт себя более стабильно, но всё равно зависит от состояния диска.


Фрагментация и косвенные потери пространства

IndexedDB использует внутренние структуры хранения, которые могут приводить к неэффективному использованию диска:

  • B-Tree структуры с накладными расходами
  • хранение ключей и индексов
  • версии объектов и overhead сериализации
  • фрагментация после удаления записей

Это означает, что фактический объём данных на диске всегда больше логического объёма, видимого в приложении.


Сериализация данных и влияние на размер

localForage использует сериализацию значений (обычно через structured clone алгоритм). Это влияет на итоговый размер:

  • числа и строки хранятся относительно эффективно
  • объекты с вложенными структурами увеличиваются экспоненциально
  • бинарные данные (Blob, ArrayBuffer) занимают минимально возможный объём

Выбор формата данных напрямую влияет на вероятность достижения квоты.


Непредсказуемость доступного пространства

Ключевая особенность IndexedDB — отсутствие фиксированного потолка, что приводит к следующим эффектам:

  • одно и то же приложение может работать с 200 МБ или 2 ГБ в зависимости от устройства
  • обновление браузера может изменить доступный лимит
  • пользовательские действия (очистка кэша) мгновенно меняют доступный объём

По этой причине любые численные ограничения в приложениях носят лишь оценочный характер.


Стратегии работы в условиях ограничений

При проектировании хранилищ на базе localForage обычно учитываются следующие принципы:

  • хранение только критически важных данных
  • разбиение больших объектов на части
  • контроль размера сериализованных структур
  • периодическая очистка устаревших ключей
  • использование сжатия перед записью
  • обработка QuotaExceededError как штатного сценария

Эти меры компенсируют неопределённость объёма IndexedDB и позволяют поддерживать стабильную работу приложения даже при резких изменениях доступного пространства.