# Хранилищем становится SQLite с каталогом файлов, а PocketBase уходит целиком - **Дата:** 2026-08-22 - **Источник:** [../research/storage-without-pocketbase.md](../research/storage-without-pocketbase.md) — записка разведки о выборе хранилища ## Решение PocketBase уходит из проекта целиком: состояние записей и метаданные переезжают в SQLite, с которым сервис работает напрямую через `modernc.org/sqlite`, файлы записей — в свой каталог со своей раскладкой, маршруты и слои — на `net/http`, шаги схемы — на свой раннер. Панель администратора теряется и **не заменяется ничем**: пока идёт стройка, остановленную запись возвращает в работу запрос к базе. Запись заменяет три: [ADR-2026-08-11-pocketbase-storage-with-admin-panel](ADR-2026-08-11-pocketbase-storage-with-admin-panel.md), [ADR-2026-08-11-queue-as-pocketbase-collection](ADR-2026-08-11-queue-as-pocketbase-collection.md) и [ADR-2026-08-12-protected-file-behind-session](ADR-2026-08-12-protected-file-behind-session.md). **Что из заменённых решений подтверждается, а не отменяется.** Очередь остаётся своей таблицей, захват — одним запросом с `RETURNING`, готовую библиотеку очереди по-прежнему не берём: замер, которым это решено, снят на `modernc.org/sqlite` — том самом драйвере, который остаётся и после ухода. Отменяется у той записи одно слово: таблица перестаёт быть коллекцией. Приложение остаётся в своём корне `/app/` ([ADR-2026-08-15-app-namespace](ADR-2026-08-15-app-namespace.md)). Файл записи остаётся закрытым — но проверкой владельца в своём обработчике, а не защищённым полем коллекции и коротким токеном. ## Почему Разведка мерила не «хранилище против хранилища», а то, что библиотека держит в этом коде. Цитата из источника: > Разрез «хранилище против хранилища» вопроса не покрывает: библиотека держит > шесть ролей сразу, и только две из них про хранение. Довод, на котором стоял перевод, отпал сам. Источник, раздел о трёх доводах: > Вход делает само приложение с 2026-08-22 […]: пришедшего называет заголовок > прокси, а учётную запись заводит наш `EnsureUser`. Пользователи в коллекции > есть **потому, что их пишет наш код**, а не провайдер библиотеки. Довод, > которым отвергнут отвергнутый вариант, перестал быть верным. Отвергнут вариант «уйти в два шага», оставив панель жить в промежутке, и отвергнут решением владельца: панель на стройке заменяется запросом к базе, а вторая порция работы стоит дороже, чем то, что она сберегает. Обстоятельство, которое назначило момент: > на сервере данных нет и сервис остановлен, поэтому смена стоит только кода. > Дешевле она не станет никогда — каталог `internal/controller/http` прирастает > кодом на чужих типах с каждой задачей. ## Последствия - `+` периметр сервиса становится только нашим. Панель `/_/` исчезает вместе с дефектом `/%5f/` из [../security.md](../security.md), а пространство хранилища `/api/` — вместе с необходимостью держать его открытым ради файлов. - `+` пропадает секрет, которого не было до перевода, — пароль суперпользователя панели. - `+` файлы ложатся своей раскладкой, и загрузка частями, узнавание по хеш-сумме, удаление записи и вторая копия рядом становятся обычной работой с файлами. - `+` из сборки уходят шесть модулей, достижимых только через библиотеку: `imaging`, `mailyak`, `jwt`, `fexpr`, `cobra`, драйвер MySQL. `modernc.org/sqlite` остаётся, и сборка по-прежнему обходится без CGO. - `−` владелец сервиса остаётся без панели. Правку записи, возврат остановленной в работу и просмотр очереди до появления экранов делает запрос к базе руками. Задачи `audiorecord-actions` и `play-recording-in-app` этим становятся не улучшением, а заменой утраченного инструмента. - `−` шаги схемы, отдачу файла, ограничитель частоты и настройку базы пишем и сопровождаем сами. Единственный писатель у `modernc.org/sqlite` — наша забота с этого дня. - `−` раскладка каталога данных меняется необратимо. Цена сегодня нулевая: стройка, на сервере пусто; после первой боевой записи она перестаёт быть нулевой. - `−` 1497 строк контроллера и 3075 строк его проверок написаны на `*core.RequestEvent` и переписываются целиком.