Backups
Перевірте резервну копію Supabase до того, як вона знадобиться
Як перевірити резервну копію Supabase: відновити в тестовий проєкт, порахувати рядки, увійти й знайти рядок, якого бракує обрізаному файлу.

Коротко
- Щоб перевірити резервну копію Supabase, відновіть її в проєкт, який нічого не важить, порівняйте кількість рядків із робочою базою і увійдіть під власним обліковим записом. Лише відновлення відрізняє добрий файл від зламаного.
- Ми обрізали дамп посеред таблиці й залили його з параметрами, які радить Supabase. psql завершився без жодної помилки, а таблиці повернулися неповними.
- Проведіть таке навчання раз зараз, далі раз на три місяці й після будь-якої зміни в тому, як робиться копія, і щоразу записуйте дату.
Десь лежить файл, у якому ваша база даних. GitHub Action пише такий щоночі, або ви колись один раз запустили три команди резервного копіювання Supabase, або ваш тариф робить щоденні копії. У нього правильна назва й приблизно той розмір, якого ви очікуєте. Ніхто ніколи його не відкривав.
Ось та частина, яку посібники з налаштування відкладають на потім: резервна копія, яку ніколи не відновлювали, це обіцянка, а не копія. Єдиний спосіб перевірити резервну копію Supabase: навмисно відновити її там, де нічого від цього не залежить, і подивитися, що повернеться. Дамп, обрізаний посередині, дамп без жодного рядка й дамп не того проєкту лежать у сховищі й виглядають точнісінько як добрий.
Згадайте навчальну пожежну тривогу. Будівля проводить її звичайного ранку, коли нічого не горить, бо ніхто не мав би вперше спускатися тими сходами в день, коли вони наповнюються димом. Надворі хтось робить перекличку за списком тих, хто був усередині, а хтось записує дату на аркуші біля дверей. Навчальне відновлення влаштоване так само: пройти маршрут, порахувати, записати.
Як дізнатися, що моя резервна копія Supabase справді працює?
Відновіть її й подивіться. Іншої перевірки не існує, бо сам файл ніяк не відрізняє доброї копії від зламаної.
Навчання бере вашу найновішу копію, заливає її в проєкт, який нічого не важить, і ставить результатові три питання. Чи є кожна таблиця, і приблизно з такою ж кількістю рядків, як робоча? Чи датований найновіший рядок ніччю, коли робили копію? Чи можете ви увійти під власним обліковим записом? Добрий файл відповідає «так» на всі три, а кожен спосіб, у який копія псується, провалює принаймні одне з них.
П’ять способів, у які копія неправильна, але виглядає правильно
Усі п’ять завершуються вночі без жодної помилки, і всі п’ять лишають файл зі звичною назвою у звичному місці. Відрізнити їх можна лише тоді, коли файл заливають.
| Що не так із файлом | Як до цього зазвичай доходить | Крок навчання, який це виявляє |
|---|---|---|
| Він уривається посередині | Скрипт, що передає pg_dump у gzip, повідомляє те, що зробив gzip. Дамп, який помер на півдорозі, зберігається, а завдання звітує про успіх. Повний диск чи обірване завантаження роблять те саме | Завершальний рядок, потім підрахунки |
| У ньому ваші таблиці й жодного рядка | supabase db dump запустили без --data-only, і тоді він пише лише структуру | Підрахунки: кожна таблиця на нулі |
| У ньому рядки й жодного облікового запису | Дамп назвав лише вашу власну схему, а ваші користувачі живуть у схемі auth | Пошук auth.users, потім вхід |
| Це дані іншого проєкту | Рядок підключення вказує на staging-копію чи старий проєкт | Найновіший рядок, не з того дня |
| Він узагалі не заливається | Дамп із Postgres 17, залитий у Postgres 15, або рядки про власника, які новий проєкт відкидає | Відновлення зупиняється з помилкою |
Другий і третій описано в статті чому у вашому дампі Supabase немає користувачів, і обидва виникають через команду дампа, запущену з меншою кількістю параметрів, ніж їй було потрібно. Перший нас здивував, тож він отримує окремий розділ.
Чи падає відновлення обрізаного файлу резервної копії?
Не завжди. Ми обрізали файл посеред таблиці, залили його з параметрами, які
використовує сам посібник Supabase, і psql завершився без жодної помилки.
Тест був невеликий, і його легко повторити. 27 вересня 2026 року ми зробили
дамп бази з двома таблицями, одна на 5 000 рядків, друга на 300, обрізали файл
у трьох різних місцях і залили кожну версію через psql із Postgres 17.11.
Кожна заливка використовувала --single-transaction і
--variable ON_ERROR_STOP=1, два параметри, які мають зупинити відновлення на
першій проблемі й скасувати все зроблене.
- Обрізано посеред значення:
psqlзупинився з помилкою й нічого не записав. На такий результат ви й сподівалися б. - Обрізано в останній колонці рядка: завершився з кодом виходу 0, так програма повідомляє про успіх. Перша таблиця повернулася з 2 596 рядками з 5 000, в останнього з них бракувало половини тексту, а друга таблиця повернулася порожньою.
- Обрізано точно між двома таблицями: теж завершився з 0. Перша таблиця була повна, друга порожня.
Причина в тому, як дамп зберігає рядки. Рядки кожної таблиці лежать в одному
блоці, що закінчується рядком файлу, у якому стоїть лише \., і коли файл
закінчується раніше за цей рядок, psql сприймає кінець файлу як кінець
блоку. Єдина ознака того, що мало бути продовження, це рядок, який мав стояти
в самому кінці.
Цей рядок і є підписом pg_dump. Повний дамп містить ближче до кінця слова
PostgreSQL database dump complete, а обрізаний не містить. Із трьох файлів,
які пише Supabase CLI, цей рядок виживає лише в data.sql, бо CLI вилучає з
файлу схеми всі коментарі (перевірено на версії 2.111 CLI). Отже, шукати треба
в data.sql, і цей пошук є другим кроком навчання.
Куди її відновлювати?
У проєкт Supabase, який нічого не важить: тестовий проєкт у вашому обліковому записі або Supabase, запущений на вашому власному комп’ютері. Ніколи не в проєкт, яким користується ваш застосунок.
Тестовий проєкт у Supabase найближчий до вашого справжнього, і саме для нього написано посібник Supabase про резервне копіювання й відновлення: його перший крок полягає в тому, щоб створити новий проєкт. На безкоштовному тарифі вам належать два активні безкоштовні проєкти, а призупинені не рахуються, тож тестовий проєкт зазвичай нічого не коштує, поки ваша база вміщається в безкоштовний тариф. У платній організації обчислювальні ресурси нового проєкту оплачуються щогодини, тож видаліть його, коли навчання закінчиться.
Supabase на вашому власному комп’ютері нічого не коштує й не потребує
облікового запису. Supabase CLI запускає весь стек локально в Docker:
supabase init, потім supabase start,
і показує адресу бази на порту 54322 та publishable key для локального
проєкту. Перш ніж запускати, відкрийте supabase/config.toml і встановіть
major_version на основну версію Postgres вашого проєкту. Коментар над цим
параметром каже, що вони мають збігатися, а версію вашого проєкту видно в
Project Settings, потім General.
На Postgres 15 є підступ. Якщо завдання резервного копіювання не задало версію,
копію зроблено через pg_dump 17 з CLI, і файл даних тоді містить біля початку
SET transaction_timeout = 0, параметр, якого Postgres 15 не знає, тож
відтворення зупиняється на цьому рядку. Для навчання встановіть major_version
на 17. Потім додайте в завдання резервного копіювання виправлення в один рядок
зі статті про GitHub Action, бо проєкт, у
який ви відновлюватимете насправді, досі на 15.
Голого Postgres у Docker, без нічого від Supabase всередині, замало. Дамп
Supabase посилається на речі, які створює лише Supabase, як-от схема auth, де
живуть ваші користувачі, і роль authenticated, яку називають ваші правила
безпеки, і відновлення зупиняється на першому ж рядку, що згадує одну з них.
Одне застереження, бо в тестовому проєкті тепер справжня копія. У ньому адреси електронної пошти ваших користувачів, тож не спрямовуйте на нього ні застосунок, ні його вебхуки, і видаліть його, коли закінчите.
Заплановані завдання не переносяться. Якщо ваш проєкт виконує їх через
розширення pg_cron, три файли CLI повертають саме розширення і жодного з його
завдань, бо завдання є рядками в cron.job, а дамп даних ці рядки пропускає. Ми
перевірили це 4 жовтня 2026 року з версією CLI 2.119, відновивши базу, у якій
було заплановане завдання. Тож тестовий проєкт мовчить, а справжнє відновлення з
цих файлів так само починається без жодного запланованого завдання, тому
зберігайте свої виклики cron.schedule там, звідки зможете запустити їх знову.
Як перевірити резервну копію Supabase, крок за кроком
Шість кроків, і перші три відбуваються ще до будь-якого відновлення.
- Знайдіть найновішу копію й подивіться на її дату. Якщо вона старша за останній запланований запуск, завдання зупинилося, і це ваша перша знахідка.
- Пошукайте в
data.sqlсловаdump complete. Один збіг означає, що файл дійшов до кінця. Жодного означає, що його обрізано, хоч би яким був розмір. Пошук у текстовому редакторі працює не гірше за термінал:grep -c 'dump complete' data.sql - Пошукайте в ньому своїх користувачів. Рядок, що починається з
COPY "auth"."users"і має під собою дані, означає, що ваші облікові записи у файлі:grep -n 'COPY .*auth.*users' data.sql - Залийте його в тестовий проєкт командою з посібника Supabase,
спрямованою на рядок підключення тестового проєкту. Для локального Supabase
цей рядок такий:
postgresql://postgres:postgres@127.0.0.1:54322/postgres.psql \ --single-transaction \ --variable ON_ERROR_STOP=1 \ --file roles.sql \ --file schema.sql \ --command 'SET session_replication_role = replica' \ --file data.sql \ --dbname "postgresql://…the spare's connection string…" - Порахуйте рядки й подивіться на найновіший, в обох базах. Запит у наступному розділі.
- Увійдіть у тестовий проєкт під власним обліковим записом. Команда в розділі після нього.
Якщо крок 4 зупиняється з помилкою, навчання зробило свою справу завчасно. Нотатки з усунення проблем унизу посібника Supabase описують дві найчастіші помилки, обидві про ролі, а як відновити резервну копію Supabase пояснює, від чого захищає кожен параметр цієї команди.
Ще двох зупинок у roles.sql у цих нотатках немає. Ми натрапили на обидві 4
жовтня 2026 року, відтворюючи файли двох баз Postgres 17, одна з яких є проєктом
Supabase, у свіжій локальній копії Supabase:
"supabase_admin" is a reserved role, only superusers can modify it на рядку,
що починається з ALTER ROLE "supabase_admin", і
permission denied for parameter log_min_messages на рядку, що починається з
GRANT SET ON PARAMETER. Обидва рядки налаштовують ролі, які Supabase сам
створює в кожному проєкті, тож поставте -- на початку кожного з них, щоб
зробити його коментарем, і запустіть команду знову.
Наша Action для резервного копіювання
коментує їх уже під час створення копії.
Що рахувати і з чим порівнювати
Порахуйте кожну таблицю в тестовому проєкті й у робочому проєкті тим самим запитом і покладіть обидва списки поруч. Копія має відставати від робочої бази на одну ніч: трохи менше в таблиці, що росте, і ніколи не нуль у таблиці, де були рядки.
Це перекличка за списком тих, хто був усередині. Вставте запит у SQL-редактор
кожного проєкту й натисніть Run. Він рахує рядки в кожній таблиці вашої
власної схеми та схеми auth:
select table_schema, table_name,
(xpath('/row/n/text()',
query_to_xml(format('select count(*) as n from %I.%I', table_schema, table_name),
false, true, '')))[1]::text::bigint as row_count
from information_schema.tables
where table_schema in ('public', 'auth')
and table_type = 'BASE TABLE'
order by table_schema, table_name;
Він читає кожен рядок кожної таблиці, тож на великій базі запускайте його поза найнавантаженішими годинами.
Потім подивіться на найновіший рядок у таблиці, яку ви знаєте, лише в
тестовому проєкті. Підійде будь-яка таблиця з колонкою created_at; поставте
її назву замість orders:
select max(created_at) from public.orders;
Відповідь має бути близькою до часу, коли працювало резервне копіювання. Дата, старша на тижні, або рядки, яких ви не впізнаєте, означають, що файл прийшов з іншого проєкту.
| Перевірка | Де | Що показує добра копія |
|---|---|---|
| Рядки в кожній таблиці | В обох | Ті самі таблиці, кожна трохи позаду робочої, жодна не порожня, якщо в ній були рядки |
| Найновіший рядок | Тестовий проєкт | Час із тієї ночі, коли робили копію |
| Ваш власний обліковий запис | Тестовий проєкт | Ваша адреса в auth.users |
| Вхід | Тестовий проєкт | Повертається токен |
Чому вхід є тією перевіркою, що доводить ваші облікові записи
Підрахунок auth.users доводить, що рядки доїхали. Вхід доводить, що вони
працюють: що збережений пароль, служба входу тестового проєкту й ваша адреса
електронної пошти досі узгоджуються між собою.
Візьміть свій власний обліковий запис із паролем, який ви знаєте. Адреса
проєкту й publishable key тестового проєкту є в його панелі Connect, а для
локального Supabase у виводі supabase start:
curl -X POST 'https://…the spare's project ref….supabase.co/auth/v1/token?grant_type=password' \
-H "apikey: sb_publishable_…" \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "…"}'
Це виклик входу з
документації самого Supabase,
спрямований на тестовий проєкт. Відповідь, у якій є access_token, означає,
що ваш обліковий запис доїхав разом із робочим паролем.
Invalid login credentials для облікового запису, який без проблем входить у
ваш робочий застосунок, означає, що не доїхав, і
чому дамп приходить без облікових записів
є статтею саме про такий результат.
Якщо всі входять у ваш застосунок через Google, цьому виклику нічого
перевіряти, бо в тестовому проєкті вхід через Google не налаштовано. Натомість
пошукайте свою адресу у відновленій auth.users. Це показує, що рядок
облікового запису доїхав, хоч і не доводить, що його пароль працює.
Файли: половина, яку відновлення бази перевірити не може
Копія бази містить рядок для кожного завантаженого файлу й жодного самого файлу. Якщо ви копіюєте свої бакети Storage окремим завданням, а інакше вони взагалі не копіюються, проведіть навчання й для цієї копії.
Візьміть три найновіші рядки з відновленої бази:
select bucket_id, name from storage.objects order by created_at desc limit 3;
Знайдіть ці три шляхи у своїй копії файлів і відкрийте кожен. Шлях, за яким немає файлу, це зображення, яке ваші користувачі побачили б зламаним після справжнього відновлення.
Чи можна перевірити резервні копії, які Supabase робить для мене?
На платному тарифі так, через Restore to a New Project. Це єдиний спосіб відкрити одну з щоденних копій самого Supabase, бо в поточних проєктах їх неможливо завантажити.
Supabase описує цю функцію як спосіб
безпечно проводити тести.
Виберіть копію на вкладці Restore to a New Project сторінки Backups, і Supabase
збудує з неї новий проєкт із вашими користувачами та їхніми хешованими
паролями, готовий до тих самих підрахунків і того самого входу. Дві речі варто
знати, перш ніж натискати. Новий проєкт оплачується як окремий, і Supabase
показує вам вартість перед початком. І він копіює все, разом із
запланованими завданнями: Supabase пише, що завдання pg_cron, pg_net і
wrappers починають працювати одразу після завершення відновлення, і
призупинити їх заздалегідь неможливо. Якщо завдання у вашому застосунку
надсилає листи чи списує гроші з картки, тестовий проєкт теж це зробить.
Якщо ви додатково зберігаєте файл поза обліковим записом, цьому файлу потрібне власне навчання.
Як часто треба перевіряти відновлення?
Раз зараз, далі раз на три місяці і знову щоразу, коли щось змінюється в тому, як робиться копія.
Важать зміни, які тихо ламають резервну копію: новий чи відредагований workflow, скинутий пароль бази, перехід на новий тариф чи нову версію Postgres, нова таблиця, у яку ваш застосунок почав писати. Після кожної з них навчання минулого кварталу вже не описує файл цього кварталу.
Потім запишіть результат, це і є аркуш біля дверей. Один рядок на кожне навчання, у місці, до якого ви дістанетеся без того, що зламалося: дата, який файл, підрахунки, що мали значення, чи спрацював вхід і скільки тривало все навчання. Підійде текстовий файл у репозиторії з копіями, а так само повторювана подія в календарі з вставленими результатами. Дата відповідає на «коли ми востаннє це доводили» саме тієї години, коли комусь треба це знати, а тривалість стає вашою першою оцінкою того, на скільки справжнє відновлення зупинить ваш застосунок.
Де тут Reeve Care
Care зберігає копії вашої бази даних Supabase поза вашим обліковим записом Supabase за розкладом вашого тарифу, перевіряє кожну копію під час створення і повертає її на місце однією кнопкою.
- Копії робляться за розкладом вашого тарифу, від одного разу на день до кожних шести годин.
- Обрізану копію виявляють уже під час створення. Завершальний рядок
pg_dumpмає бути у файлі, інакше копія не проходить перевірку й ніколи не стає датою на вашій панелі. - Кожну таблицю рахують, поки копія пишеться. Коли таблиця, у якій були рядки в попередній копії, у цій не має жодного, про це дізнається людина в Reeve.
- Ваші облікові записи в ній є, а завантажені файли теж потрапляють туди, щойно ви підключите доступ до Storage.
- Відновлення робиться однією кнопкою, і перш ніж щось замінити, робиться копія поточного стану.
- Будь-яку копію можна завантажити як zip із
schema.sql,data.sql,roles.sqlі маніфестом із кількістю рядків у кожній таблиці, тобто з тією половиною цієї статті, що відповідає на «з чим порівнювати», уже записаною.
Щоквартальне навчання доводить ту копію, яку ви вибрали того дня, а перевірка відбувається з кожною копією під час її створення. Копію, перевірку й відновлення покроково намальовано на сторінці про резервні копії Supabase, а що входить у кожен тариф, разом із розкладом, написано на сторінці цін.
Що зробити цього тижня
Що робити
- Знайдіть найновішу резервну копію й подивіться на її дату. Якщо вона старша за останній запланований запуск, спершу полагодьте завдання.
- Пошукайте в
data.sqlсловаdump completeі рядокCOPY "auth"."users". Два пошуки скажуть, чи файл доходить до кінця і чи є в ньому ваші облікові записи. - Створіть тестовий проєкт або запустіть Supabase на своєму комп’ютері й залийте файл командою
psqlз посібника Supabase. - Виконайте запит підрахунку в обох базах і покладіть два списки поруч. Подивіться на найновіший рядок у таблиці, яку ви знаєте.
- Увійдіть у тестовий проєкт під власним обліковим записом.
- Запишіть дату, підрахунки й тривалість, а потім видаліть тестовий проєкт.
Перш ніж закрити цю вкладку, пошукайте dump complete у своєму найновішому
data.sql. Це один пошук, і він скаже, чи доходить файл, який ви називаєте
резервною копією, до свого останнього рядка. Якщо файлу для пошуку у вас ще
немає, безкоштовна GitHub Action є
найшвидшим способом почати їх робити.
Поширені запитання
Як дізнатися, що моя резервна копія Supabase справді працює?
Відновіть її в проєкт, який нічого не важить, і подивіться, що повернулося. Порівняйте кількість рядків у кожній таблиці з робочою базою, перевірте, що найновіший рядок датований ніччю, коли робили копію, і увійдіть під власним обліковим записом. Сам файл не відрізняє доброго дампа від зламаного: назва, розмір і зелена позначка біля завдання однакові в обох випадках.
Як часто треба перевіряти відновлення?
Раз зараз, далі раз на три місяці і знову щоразу, коли змінюється те, як робиться копія: новий чи відредагований workflow, скинутий пароль бази, новий тариф чи нова версія Postgres або нова таблиця, у яку пише ваш застосунок. Щоразу записуйте дату разом із підрахунками й тривалістю, щоб на питання, коли це востаннє доводили, була відповідь.
Чи можна перевірити відновлення, не чіпаючи робочу базу?
Так, і саме так це завжди і слід робити. Відновлюйте в тестовий проєкт Supabase, що дозволяє безкоштовний тариф, або в Supabase, запущений на вашому комп’ютері через CLI і Docker. Робочу базу навчання лише один раз читає, щоб порахувати її рядки. Потім видаліть тестовий проєкт, бо в ньому справжня копія ваших користувачів.
Що перевірити після відновлення резервної копії?
Чотири речі. Кількість рядків у кожній таблиці поруч із робочою, де копія має трохи відставати й ніколи не бути нулем для таблиці, у якій були рядки. Найновіший рядок у таблиці, яку ви знаєте, датований ніччю копії. Вашу власну адресу в auth.users. І вхід під вашим обліковим записом, єдину перевірку, яка доводить, що облікові записи працюють, а не просто приїхали.
Відновлення вдалося, але ніхто не може увійти. Чому?
Найчастіше тому, що у файлі ніколи не було ваших облікових записів. Supabase тримає їх у схемі auth, і дамп, який назвав лише вашу власну схему, або голий supabase db dump залишає їх поза файлом, хоча кожна ваша таблиця відновлюється без проблем. Спершу пошукайте у файлі COPY "auth"."users". Якщо цього рядка немає, зробіть дамп даних із --data-only, який проходить схему auth і забирає ваших користувачів.
Чи падає відновлення обрізаного файлу резервної копії?
Не завжди. Ми обрізали файл pg_dump у трьох місцях і залили кожну версію з --single-transaction та ON_ERROR_STOP, параметрами з посібника Supabase про відновлення. Обрізання посеред значення зупинилося з помилкою. Обрізання в останній колонці рядка й обрізання між двома таблицями обидва завершилися без помилок, із неповними таблицями. Повний дамп містить ближче до кінця рядок PostgreSQL database dump complete, тож шукайте його, перш ніж довіряти файлу.