Supabase чи звичайний Postgres на вашому VPS?
Self-hosted Supabase це 11 сервісів навколо PostgreSQL. Розбираємо, що дає кожен, коли це виправдано на одному VPS, а коли досить чистого Postgres і свого API.
Supabase чи звичайний Postgres: коротка відповідь
Supabase на власному VPS це не інша база даних, а стек сервісів навколо PostgreSQL. У релізі self-hosted/v0.8.1, який я відкрив 22 вересня 2026 року, файл docker-compose.yml описує 11 сервісів, і лише один з них є базою. Тому питання "Supabase чи Postgres" насправді звучить інакше: чи потрібні вам реєстрація користувачів, HTTP API над таблицями, файлове сховище і канал подій у реальному часі як готові сервіси, чи ви напишете цю частину самі.
Якщо ви робите мобільний застосунок або SPA і не хочете писати бекенд, Supabase економить тижні роботи. Якщо у вас уже є застосунок на Django, Laravel, Go чи Node, і від бази даних потрібно лише бути базою даних, звичайний Postgres дешевший у супроводі: один контейнер, один дамп, одне оновлення. Власник одного скромного VPS частіше належить до другої групи, ніж йому здається.
Supabase це СУБД чи ні
Ні. СУБД (система управління базами даних) тут одна, і це PostgreSQL. Образ бази у цьому релізі має тег supabase/postgres:17.6.1.136: це Postgres з набором розширень, заздалегідь створеними ролями та службовими схемами auth, storage, realtime. Ваш SQL залишається SQL. Ваш драйвер залишається драйвером Postgres. pg_dump працює так само, як на будь-якому іншому сервері.
Плутанина походить від маркетингу. Supabase називають відкритою альтернативою Firebase, а Firebase справді є окремою базою даних із власним SDK. Supabase влаштований навпаки: база звичайна, а схожий досвід розробки дають сервіси навколо неї. Якщо ви прийшли саме з цього боку, спершу подивіться огляд відкритих альтернатив Firebase, бо вибір там ширший за один продукт.
Що саме запускає self-hosted реліз
Не вгадуйте склад стека з памʼяті і не довіряйте старим статтям: він змінюється від релізу до релізу. Візьміть конкретний тег і подивіться самі. Офіційна інструкція клонує репозиторій на закріпленій гілці.
git clone --depth 1 --branch self-hosted/v0.8.1 https://github.com/supabase/supabase
mkdir supabase-project
cp -rf supabase/docker/. supabase-project
cd supabase-project && cp .env.example .env
printf 'ref=self-hosted/v0.8.1\n' > .supabase-version
docker compose pullПеред першим запуском згенеруйте власні секрети. Документація прямо попереджає не стартувати стек зі значеннями з .env.example, бо вони однакові у всіх, хто його скопіював.
sh utils/generate-keys.sh
sh utils/add-new-auth-keys.sh
docker compose config --services
docker compose up -d
docker compose psdocker compose config --services друкує список сервісів вашого релізу, а не мого. docker compose ps після старту має показати стан healthy майже для кожного рядка, бо у compose-файлі для більшості сервісів описані healthcheck-и і залежності: auth, rest і realtime стартують лише після того, як db відповість на pg_isready. Контейнер, який нескінченно перезапускається, дивіться через docker compose logs -f <сервіс>. Якщо Docker Compose для вас новий, почніть з основ Docker Compose на VPS, бо далі все керування стеком це саме він.
Що кожен сервіс замінює у вашому бекенді
Нижче склад релізу self-hosted/v0.8.1 і робота, яку кожен контейнер знімає з вас.
db(supabase/postgres:17.6.1.136): сам PostgreSQL з розширеннями. Єдиний сервіс, без якого решта не має сенсу.rest(postgrest/postgrest:v14.17): PostgREST будує HTTP API прямо зі схеми бази. Замінює шар контролерів і серіалізації. Права доступу задаються не в коді, а через RLS (row level security, захист на рівні рядків) у самій базі.auth(supabase/gotrue:v2.196.0): реєстрація, вхід, підтвердження пошти, скидання пароля, OAuth-провайдери, видача JWT (JSON web token). Це найбільший шматок роботи, який Supabase забирає собі.realtime(supabase/realtime:v2.134.10): читає WAL (write ahead log, журнал попереднього запису) Postgres і віддає зміни рядків клієнтам через WebSocket.storage(supabase/storage-api:v1.74.0): файлове сховище з тими самими правилами доступу, що й таблиці. Метадані лежать у Postgres, самі файли на диску або в S3-сумісному сховищі.imgproxy(darthsim/imgproxy:v3.31.4): зміна розміру зображень на льоту для сховища.meta(supabase/postgres-meta:v0.99.0): HTTP API над системним каталогом бази. Потрібен здебільшого Studio, а не вашому застосунку.studio(supabase/studio:2026.09.07-sha-7996410): вебінтерфейс з редактором таблиць, SQL-редактором і переглядом користувачів.api-gw(envoyproxy/envoy:v1.39.1): один вхід на порт8000, який розводить запити міжrest,auth,storageіfunctions. Kong лишився як опція черезsh run.sh config add kong.functions(supabase/edge-runtime:v1.76.2): середовище Deno для серверних функцій.supavisor(supabase/supavisor:2.9.12): пулер зʼєднань, транзакційний режим на порту6543. Завдання те саме, що й у PgBouncer, і обмеження ті самі: детально в розборі пулінгу зʼєднань до Postgres на VPS.
Важливо і те, чого в self-hosted версії немає. Документація перелічує це прямо: гілки (branching), розширені метрики понад логи, керовані бекапи і PITR (point in time recovery, відновлення на момент часу), аналітика, ETL і платформне API керування. Studio працює з одним проєктом і однією організацією. Бекапи, моніторинг і відновлення після збою повністю на вас.
Скільки це важить на одному VPS
The data behind this chart
[
{
"label": "Supabase self-hosted/v0.8.1",
"containers": 11
},
{
"label": "Postgres \u043f\u043b\u044e\u0441 \u0432\u043b\u0430\u0441\u043d\u0438\u0439 API",
"containers": 2
}
]Цифра 11 це кількість сервісів у compose-файлі закріпленого релізу. Друге значення, 2, це база плюс один контейнер вашого застосунку, тобто мінімальний варіант із наступного розділу. Про оперативну памʼять я свідомо не називаю чисел: вони залежать від релізу, від налаштувань пулера і від того, чи лишили ви Studio та functions увімкненими. Виміряйте самі.
docker stats --no-stream
free -mМіряйте двічі: у спокої і під реальними запитами, бо це різні числа. Якщо памʼяті бракує, першими зупиняють studio та imgproxy, бо без них API працює далі, а редактор таблиць вам потрібен не щодня.
Коли звичайного Postgres достатньо на одному VPS
Якщо ваш бекенд уже існує, весь стек зводиться до одного контейнера.
services:
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_PASSWORD: change_me
POSTGRES_DB: app
volumes:
- ./pgdata:/var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432"Зверніть увагу на 127.0.0.1 у публікації порту. Без цієї адреси Docker відкриває порт 5432 на всіх інтерфейсах і сам додає правило в iptables, тому ваш ufw його не закриє: база опиняється в інтернеті, і перебір паролів починається того ж дня. Перевірка після старту:
docker compose up -d
docker compose exec db pg_isready -U postgres
psql -h 127.0.0.1 -U postgres -d app -c 'select version();'pg_isready має відповісти accepting connections, а psql надрукувати рядок версії. Далі ваш застосунок ходить у базу через внутрішню мережу Docker, а назовні дивиться лише ваш HTTP-сервер за TLS (transport layer security, захист транспортного рівня). Оновлення мінорної версії тут це docker compose pull і рестарт. Мажорне оновлення Postgres це дамп і відновлення в нову версію, і воно стосується одного образу, а не одинадцяти.
Що доведеться написати самому
Відмова від Supabase це не відмова від функцій, а рішення написати їх самому. Чесний список того, що доведеться закрити:
- Реєстрація і вхід: хешування паролів, підтвердження пошти, скидання пароля, сесії.
- HTTP API над таблицями: ендпоінти, фільтри, пагінація, перевірка прав.
- Файли: завантаження, обмеження розміру і типу, роздача з правами.
- Події в реальному часі: підписка на зміни і доставка їх у браузер.
Якщо ви закриваєте цей список двома готовими бібліотеками свого фреймворку, вигода Supabase падає майже до нуля: ви платите одинадцятьма контейнерами за те, чого не використовуєте. Якщо ж бекенду ще немає, картина обертається, бо Supabase дає працюючий API в перший день. Покроковий запуск з доменом і сертифікатом описаний окремо в інструкції з self-host Supabase на VPS, а гроші і ліміти в розборі безкоштовного плану Supabase проти self-hosted.
Бекап і оновлення: де справжня різниця
Для чистого Postgres бекап це один файл.
docker compose exec -T db pg_dump -U postgres -Fc app > app-$(date +%F).dumpДля Supabase у бекап входить база, том зі storage-файлами і файл .env. Останній критичний: у ньому лежать POSTGRES_PASSWORD, JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, VAULT_ENC_KEY та інші секрети. Втратите .env, і отримаєте базу, до якої не підходять видані раніше ключі, бо токени підписані старим секретом і сервіси їх більше не приймають.
Оновлення теж відрізняються. У каталозі docker лежить update.sh, і README радить спершу зробити бекап, потім sh update.sh --dry-run, далі sh update.sh і sh run.sh pull && sh run.sh recreate. Це рухає образи всього стека, і кожен з них має власний журнал змін. Сервер з одним Postgres такої координації не потребує взагалі. Якщо навіть це звучить як забагато адміністрування, порівняйте витрати часу з керованою базою в порівнянні керованого Postgres і власного на VPS.
Окремо про доступ ззовні. Не виставляйте порт 8000 в інтернет без TLS: документація вимагає дійсний сертифікат для продакшену, особливо якщо ви вмикаєте OAuth-провайдерів, бо вони повертають користувача на ваш публічний URL. І змініть DASHBOARD_PASSWORD, причому документація радить уникати спецсимволів у ньому, щоб не ловити проблеми з кодуванням URL.
Чи можна повернутися назад: що переносить дамп
Головна страховка в тому, що під Supabase лежить звичайний Postgres, тому вихід існує завжди. Офіційна процедура перенесення проєкту складається з трьох дампів через CLI.
supabase db dump --db-url "$DB_URL" -f roles.sql --role-only
supabase db dump --db-url "$DB_URL" -f schema.sql
supabase db dump --db-url "$DB_URL" -f data.sql --use-copy --data-only \
-x "storage.buckets_vectors" -x "storage.vector_indexes"Відновлення це звичайний psql з --single-transaction, --variable ON_ERROR_STOP=1 і SET session_replication_role = replica перед даними, щоб тригери і зовнішні ключі не заважали заливанню.
З дампом їдуть ваші таблиці, схема public, ролі, а також службові схеми auth і storage разом з метаданими: рядок користувача в auth.users це звичайний рядок таблиці. Не їде наступне. Самі файли зі сховища: документація дає окремий скрипт на supabase-js, який копіює обʼєкти між проєктами, бо в базі лежать лише метадані. Edge-функції: при їх вивантаженні не переносяться import map і deno.json, їх додають руками. Секрети і ключі: вони живуть у .env, а не в базі.
Практичний висновок простий. Якщо ви пішли шляхом Supabase і згодом вирішили, що вам потрібен лише Postgres, свої дані ви заберете повністю. Втратите рівно той шар, заради якого брали Supabase: авторизацію і згенерований API. Їх доведеться замінити власним кодом. Тому рішення варто приймати за питанням "чи пишу я бекенд сам", а не за питанням про моду.
FAQ
Supabase це окрема СУБД чи надбудова над Postgres?
Це надбудова. Всередині працює звичайний PostgreSQL, у релізі self-hosted/v0.8.1 це образ supabase/postgres:17.6.1.136 з розширеннями і службовими схемами auth, storage, realtime. Решта сервісів стека звертаються до нього як звичайні клієнти. Тому ваші знання SQL, драйвери і pg_dump переносяться без змін.
Скільки оперативної памʼяті потрібно для self-hosted Supabase?
Не беріть цифру зі статей, у тому числі з цієї. Склад стека змінюється від релізу до релізу, а споживання залежить від того, які сервіси ви лишили увімкненими. Запустіть свій реліз і подивіться docker stats --no-stream спершу в спокої, потім під навантаженням. Для орієнтира: закріплений тут реліз описує 11 сервісів, тобто це помітно більше за один контейнер Postgres.
Чи можна перенести проєкт із Supabase на звичайний Postgres?
Так. Ролі, схема і дані знімаються трьома командами supabase db dump і заливаються через psql, разом зі службовими схемами auth і storage. Не переносяться файли зі сховища, для яких документація дає окремий скрипт копіювання, а також import map і deno.json для edge-функцій і секрети з .env. Логіку авторизації та автогенерований API доведеться замінити своїм кодом.
У мене вже є бекенд. Чи є сенс ставити Supabase?
Зазвичай ні. Якщо авторизація, API і робота з файлами вже написані у вашому фреймворку, ви запустите 11 сервісів заради одного з них. Поставте звичайний Postgres, опублікуйте порт лише на 127.0.0.1 і робіть pg_dump за розкладом. Supabase виправданий тоді, коли бекенду ще немає і ви не плануєте його писати.