PocketBase это готовый бэкенд в одном файле. Запустили его, и у приложения есть база, вход пользователей и загрузка файлов. Ниже о том, как он устроен и когда его хватит.
Что внутри
PocketBase написан на Go и распространяется под лицензией MIT. Внутри:
- база SQLite в режиме WAL, файл лежит в каталоге
pb_data; - REST API для каждой коллекции, с фильтрами, сортировкой и пагинацией;
- realtime: подписка на изменения записей через Server-Sent Events;
- вход пользователей: email и пароль, одноразовые коды на почту, двухфакторный вход, OAuth2 (Google, Apple, GitHub, Яндекс и ещё около 30 провайдеров) и произвольный OpenID Connect;
- файлы: поля-файлы в записях, миниатюры картинок, хранение на диске или в S3;
- админка по адресу
/_/: коллекции, записи, настройки, логи запросов.
Официальные SDK есть для JavaScript и Dart (Flutter). Для остальных языков подходит обычный HTTP.
Коллекции и правила доступа
Данные хранятся в коллекциях трёх типов: base для обычных данных, auth для пользователей и view для представлений на основе SQL-запроса.
У каждой коллекции пять правил: listRule, viewRule, createRule, updateRule, deleteRule. Правило это фильтр, который проверяется на каждый запрос:
null(правило не задано): доступ только у суперпользователя;- пустая строка: доступ у всех, включая анонимов;
- выражение: доступ, если выражение истинно.
Типичное правило «пользователь видит только свои записи»:
@request.auth.id != "" && owner = @request.auth.id
Новые коллекции создаются с закрытыми правилами. Это безопасное поведение по умолчанию: данные не утекут, пока правила не открыты явно.
Пример на JavaScript
import PocketBase from "pocketbase";
const pb = new PocketBase("https://pb.example.ru");
// вход
await pb.collection("users").authWithPassword("anna@example.ru", "secret");
// создать запись
await pb.collection("tasks").create({
title: "Позвонить клиенту",
owner: pb.authStore.record.id,
done: false,
});
// список с фильтром и сортировкой
const page = await pb.collection("tasks").getList(1, 20, {
filter: "done = false",
sort: "-created",
});
// подписка на изменения
pb.collection("tasks").subscribe("*", (e) => {
console.log(e.action, e.record);
});
SDK хранит токен в pb.authStore и подставляет его в каждый запрос.
Своя логика без отдельного сервера
Код на JavaScript кладётся в каталог pb_hooks рядом с pb_data. Файлы с расширением .pb.js подхватываются при старте.
// pb_hooks/main.pb.js
// проверка перед созданием записи
onRecordCreate((e) => {
if (e.record.get("title").length > 200) {
throw new BadRequestError("Слишком длинный заголовок");
}
e.next();
}, "tasks");
// свой эндпоинт
routerAdd("GET", "/api/health", (e) => {
return e.json(200, { ok: true });
});
// задача по расписанию: каждый час
cronAdd("cleanup", "0 * * * *", () => {
// удалить устаревшие черновики
});
Для сложной логики PocketBase подключается как Go-библиотека: тогда весь бэкенд собирается в один бинарник со своим кодом.
Где предел
Запись. SQLite допускает одну пишущую транзакцию в момент времени. Чтение идёт параллельно и быстро. Для MVP, внутренних инструментов, мобильных приложений и ботов этого достаточно. Сервис с тысячами записей в секунду из многих потоков упрётся в запись раньше, чем в процессор.
Один сервер. Встроенной репликации и кластера нет. Рост только за счёт ресурсов сервера.
Версия до 1.0. Разработчики прямо предупреждают: до версии 1.0 обратная совместимость не гарантируется. Перед обновлением стоит читать changelog. Переход на v0.23 в 2024 году, например, поменял API хуков и SDK.
Нет полноценного SQL снаружи. Сложные отчёты и аналитику удобнее строить на Postgres.
Бэкапы
В админке, в разделе настроек бэкапов, есть встроенное резервное копирование: архив pb_data по расписанию (cron-выражение), с хранением локально или в S3. Минимальная схема для продакшена:
- Бэкап по расписанию раз в сутки.
- Хранение в S3, а не только на том же диске.
- Проверка восстановления: развернуть архив на чистом PocketBase и открыть админку.
Перенос PocketBase на другой сервер устроен так же: копируется каталог pb_data целиком.
Когда PocketBase, а когда Supabase
| Критерий | PocketBase | Supabase |
|---|---|---|
| База | SQLite | Postgres |
| Память | десятки мегабайт | от 4 GB для self-hosted |
| Сервисов | один процесс | около 13 контейнеров |
| SQL и расширения | ограниченно | полный Postgres, pgvector, PostGIS |
| Масштаб | один сервер | один сервер в self-hosted, больше в облаке |
| Подходит | MVP, внутренние инструменты, мобильные приложения | продукты с данными на Postgres и ростом |
Если приложение уже написано и нужен только бэкенд для данных, входа и файлов, PocketBase запускается быстрее всех. Если данные будут расти и понадобится SQL, сразу стоит смотреть на Supabase или Postgres со своим API.