Backups
Teste o backup do seu Supabase antes do dia em que precisar
Como testar o backup do seu Supabase: restaurar num projeto de teste, contar as linhas, entrar e procurar a linha que falta num arquivo cortado.

Em resumo
- Para testar um backup do Supabase, restaure-o num projeto que não importa, compare o número de linhas com o banco em produção e entre com a sua própria conta. Só uma restauração separa um arquivo bom de um quebrado.
- Cortamos um dump no meio de uma tabela e carregamos com as opções que o Supabase recomenda. O psql terminou sem nenhum erro, e as tabelas voltaram incompletas.
- Faça o simulado uma vez agora, depois a cada três meses e após qualquer mudança no jeito como o backup é feito, e anote a data toda vez.
Em algum lugar existe um arquivo com o seu banco de dados dentro. Uma GitHub Action grava um toda noite, ou você rodou uma vez os três comandos de backup do Supabase, ou o seu plano faz cópias diárias. Ele tem o nome certo e mais ou menos o tamanho que você esperaria. Ninguém nunca abriu.
Esta é a parte que os guias de configuração deixam para depois: um backup que nunca foi restaurado é uma promessa, não uma cópia. O único jeito de testar um backup do Supabase é restaurá-lo, de propósito, num lugar onde nada depende dele, e olhar o que volta. Um dump cortado no meio, um dump sem nenhuma linha e um dump do projeto errado ficam todos no armazenamento com a mesma cara de um bom.
Pense num simulado de incêndio. Um prédio faz o simulado numa manhã qualquer, quando nada está pegando fogo, porque ninguém deveria descer aquela escada pela primeira vez no dia em que ela se enche de fumaça. Lá fora, alguém faz a chamada pela lista de quem estava dentro, e alguém anota a data na folha ao lado da porta. Um simulado de restauração é a mesma coisa: fazer o caminho, contar e anotar.
Como eu sei se o backup do meu Supabase funciona mesmo?
Restaure e olhe. É o único teste que existe, porque nada no próprio arquivo separa um backup bom de um quebrado.
O simulado pega a sua cópia mais recente, carrega num projeto que não importa e faz três perguntas ao resultado. Cada tabela está lá, com mais ou menos tantas linhas quanto a de produção? A linha mais recente é da noite em que a cópia foi feita? Você consegue entrar com a sua própria conta? Um arquivo bom responde sim às três, e cada jeito de um backup dar errado falha em pelo menos uma delas.
Cinco jeitos de um backup estar errado e ainda parecer certo
Os cinco terminam na noite sem nenhum erro, e os cinco deixam um arquivo com o nome de sempre no lugar de sempre. Eles só se separam quando o arquivo é carregado.
| O que há de errado com o arquivo | Como ele costuma chegar a isso | O passo do simulado que pega |
|---|---|---|
| Ele para no meio do caminho | Um script que passa o pg_dump para o gzip informa o que o gzip fez. Um dump que morreu no meio é salvo, e o job diz que deu certo. Um disco cheio ou um upload que desistiu fazem o mesmo | A linha final, depois as contagens |
| Tem as suas tabelas e nenhuma das linhas | O supabase db dump rodou sem --data-only, e assim ele grava só a estrutura | As contagens: todas as tabelas em zero |
| Tem as linhas e nenhuma das contas | O dump nomeou só o seu próprio schema, e os seus usuários vivem num chamado auth | A busca por auth.users, depois o login |
| São os dados de outro projeto | A connection string aponta para uma cópia de staging ou para um projeto antigo | A linha mais recente, do dia errado |
| Não carrega de jeito nenhum | Um dump do Postgres 17 carregado no Postgres 15, ou linhas de dono que o projeto novo recusa | A restauração para com um erro |
O segundo e o terceiro são o assunto de por que o seu dump do Supabase não tem usuários, e os dois vêm de um comando de dump rodado com menos opções do que precisava. O primeiro nos surpreendeu, então ganhou uma seção só dele.
Um arquivo de backup cortado falha na restauração?
Nem sempre. Cortamos um no meio de uma tabela, carregamos com as opções que o
próprio guia do Supabase usa, e o psql terminou sem nenhum erro.
O teste foi pequeno e fácil de repetir. Em 27 de setembro de 2026 fizemos o
dump de um banco com duas tabelas, uma de 5.000 linhas e outra de 300,
cortamos o arquivo em três pontos diferentes e carregamos cada versão com o
psql do Postgres 17.11. Toda carga usou --single-transaction e
--variable ON_ERROR_STOP=1, as duas opções que existem para parar uma
restauração no primeiro problema e desfazer tudo.
- Cortado no meio de um valor, o
psqlparou com um erro e não gravou nada. É o resultado que você esperaria. - Cortado dentro da última coluna de uma linha, terminou com código de saída 0, que é como um programa diz que deu certo. A primeira tabela voltou com 2.596 das suas 5.000 linhas, a última delas sem metade do texto, e a segunda tabela voltou vazia.
- Cortado exatamente entre as duas tabelas, também terminou com 0. A primeira tabela estava completa e a segunda vazia.
O motivo está no jeito como um dump guarda as linhas. As linhas de cada tabela
ficam num bloco que termina com uma linha contendo só \., e quando o arquivo
acaba antes dessa linha, o psql toma o fim do arquivo como o fim do bloco. O
único sinal de que faltava alguma coisa é uma linha que deveria estar bem no
final.
Essa linha é a assinatura do pg_dump. Um dump completo tem as palavras
PostgreSQL database dump complete perto do fim, e um cortado não tem. Dos
três arquivos que a CLI do Supabase grava, a linha só sobrevive no data.sql,
porque a CLI tira todos os comentários do arquivo de schema (conferido com a
versão 2.111 da CLI). Então o data.sql é o arquivo onde procurar, e essa
busca é o segundo passo do simulado.
Onde devo restaurar?
Num projeto do Supabase que não importa: um projeto de teste na sua conta, ou um Supabase rodando no seu próprio computador. Nunca no projeto que o seu app usa.
Um projeto de teste no Supabase é o mais parecido com o seu projeto real, e é o destino para o qual o guia de backup e restauração do Supabase foi escrito: o primeiro passo dele é criar um projeto novo. No plano gratuito você tem direito a dois projetos gratuitos ativos, e os pausados não contam, então um projeto de teste costuma não custar nada desde que o seu banco caiba no plano gratuito. Numa organização paga, o processamento de um projeto novo é cobrado por hora, então apague o projeto quando o simulado terminar.
Supabase no seu próprio computador não custa nada e não precisa de conta. A
CLI do Supabase roda o stack inteiro localmente no Docker:
supabase init, depois supabase start,
e mostra um endereço de banco na porta 54322 e uma publishable key para o
projeto local. Antes de iniciar, abra supabase/config.toml e coloque em
major_version a versão principal do Postgres do seu projeto. O comentário
acima dessa configuração diz que elas precisam bater, e a versão do seu projeto
fica em Project Settings, depois General.
No Postgres 15 há uma pegadinha. A menos que o job de backup tenha fixado uma
versão, a CLI fez a cópia com o pg_dump 17, e o arquivo de dados passa a ter,
perto do começo, SET transaction_timeout = 0, uma configuração que o Postgres
15 não reconhece, então a carga para nessa linha. Para o simulado, coloque
major_version em 17. Depois aplique no job de backup a correção de uma linha
que o artigo sobre a GitHub Action
mostra, porque o projeto em que você restauraria de verdade continua no 15.
Um Postgres puro no Docker, sem nada do Supabase dentro, não basta. Um dump do
Supabase faz referência a coisas que só o Supabase cria, como o schema auth
onde vivem os seus usuários e o papel authenticated que as suas regras de
segurança nomeiam, e a restauração para na primeira linha que menciona uma
delas.
Um cuidado, porque o projeto de teste agora guarda uma cópia real. Ele tem os emails dos seus usuários, então não aponte o seu app nem os webhooks dele para lá, e apague o projeto quando terminar.
As tarefas agendadas são a parte que não vem junto. Se o seu projeto as roda com
a extensão pg_cron, os três arquivos da CLI trazem a extensão de volta e
nenhuma das tarefas, porque as tarefas são linhas de cron.job e o dump de
dados deixa essas linhas de fora. Conferimos isso em 4 de outubro de 2026 com a
versão 2.119 da CLI, restaurando um banco que tinha uma tarefa agendada. Por
isso o projeto de teste fica quieto, e uma restauração de verdade a partir
desses arquivos também começa sem nenhuma tarefa agendada, então guarde as suas
chamadas a cron.schedule num lugar de onde você possa rodá-las de novo.
Como testar um backup do Supabase, passo a passo
Seis passos, e os três primeiros acontecem antes de você restaurar qualquer coisa.
- Ache a cópia mais recente e leia a data dela. Se for mais antiga que a última execução agendada, o job parou, e essa é a sua primeira descoberta.
- Procure
dump completenodata.sql. Um resultado quer dizer que o arquivo chegou ao fim. Nenhum quer dizer que ele foi cortado, seja qual for o tamanho. A busca de um editor de texto funciona tão bem quanto um terminal:grep -c 'dump complete' data.sql - Procure nele os seus usuários. Uma linha que começa com
COPY "auth"."users"e tem linhas embaixo quer dizer que as suas contas estão no arquivo:grep -n 'COPY .*auth.*users' data.sql - Carregue o arquivo no projeto de teste com o comando do guia do
Supabase, apontado para a connection string do projeto de teste. Num
Supabase local essa string é
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…" - Conte as linhas e leia a mais recente, nos dois bancos. A consulta está na próxima seção.
- Entre no projeto de teste com a sua própria conta. O comando está na seção seguinte.
Se o passo 4 parar com um erro, o simulado já fez o trabalho dele. As notas de solução de problemas no fim do guia do Supabase cobrem os dois erros mais comuns, os dois sobre papéis, e como restaurar um backup do Supabase explica do que cada opção desse comando protege você.
Faltam nessas notas outras duas paradas em roles.sql. Topamos com as duas em 4
de outubro de 2026, ao carregar os arquivos de dois bancos Postgres 17, um deles
um projeto do Supabase, numa cópia local nova do Supabase:
"supabase_admin" is a reserved role, only superusers can modify it, numa linha
que começa com ALTER ROLE "supabase_admin", e
permission denied for parameter log_min_messages, numa linha que começa com
GRANT SET ON PARAMETER. As duas linhas configuram papéis que o Supabase cria
por conta própria em todo projeto, então coloque -- no começo de cada uma para
virar comentário e rode o comando de novo.
A nossa Action de backup
já comenta essas linhas ao fazer a cópia.
O que contar, e contra o quê
Conte cada tabela no projeto de teste e no seu projeto em produção com a mesma consulta, e coloque as duas listas lado a lado. A cópia deve estar uma noite atrás do banco em produção: um pouco mais baixa numa tabela que cresce, e nunca zerada numa tabela que tinha linhas.
É a chamada pela lista de quem estava dentro. Cole a consulta no editor SQL de
cada projeto e aperte Run. Ela conta as linhas de cada tabela do seu próprio
schema e do 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;
Ela lê cada linha de cada tabela, então num banco grande rode fora dos seus horários de mais movimento.
Depois leia a linha mais recente de uma tabela que você conhece, só no projeto
de teste. Qualquer tabela com uma coluna created_at serve; coloque o nome
dela no lugar de orders:
select max(created_at) from public.orders;
A resposta deve estar perto da hora em que o backup rodou. Uma data semanas mais antiga, ou linhas que você não reconhece, querem dizer que o arquivo veio de outro projeto.
| Conferência | Onde | O que uma cópia boa mostra |
|---|---|---|
| Linhas em cada tabela | Nos dois | As mesmas tabelas, cada uma um pouco atrás da produção, nenhuma vazia que tinha linhas |
| A linha mais recente | Projeto de teste | Uma hora da noite em que a cópia foi feita |
| A sua própria conta | Projeto de teste | O seu email em auth.users |
| Um login | Projeto de teste | Volta um token |
Por que o login é o teste que prova as suas contas
Uma contagem de auth.users prova que as linhas chegaram. Um login prova que
elas funcionam: que a senha guardada, o serviço de login do projeto de teste e
o seu email ainda combinam entre si.
Use a sua própria conta, com uma senha que você conhece. O endereço do projeto
e a publishable key do projeto de teste ficam no painel Connect dele, ou na
saída do supabase start num Supabase local:
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": "…"}'
Essa é a chamada de login da
própria documentação do Supabase,
apontada para o projeto de teste. Uma resposta com access_token quer dizer
que a sua conta chegou com uma senha que funciona. Invalid login credentials,
para uma conta que entra sem problema no seu app em produção, quer dizer que
ela não chegou, e
por que um dump chega sem as contas é o
artigo para esse resultado.
Se todo mundo entra no seu app com o Google, essa chamada não tem o que testar,
porque o projeto de teste não tem login com Google configurado. Procure o seu
próprio email em auth.users depois da restauração. Isso mostra que a linha da
conta chegou, mas não que a senha dela funciona.
Arquivos: a metade que uma restauração do banco não consegue testar
A cópia do banco guarda uma linha para cada arquivo enviado e nenhum dos arquivos. Se você copia os seus buckets do Storage num job próprio, que é o único jeito de eles serem copiados, faça um simulado com essa cópia também.
Pegue as três linhas mais recentes do banco restaurado:
select bucket_id, name from storage.objects order by created_at desc limit 3;
Ache esses três caminhos na sua cópia dos arquivos e abra cada um. Um caminho sem arquivo por trás é uma imagem que os seus usuários veriam quebrada depois de uma restauração de verdade.
Dá para testar os backups que o Supabase faz para mim?
Num plano pago, dá, com o Restore to a New Project. É o único jeito de abrir uma das cópias diárias do próprio Supabase, porque nos projetos atuais você não consegue baixar essas cópias.
O Supabase descreve o recurso como um jeito de
testar com segurança.
Escolha uma cópia na aba Restore to a New Project da página Backups, e o
Supabase monta um projeto novo com ela, com os seus usuários e as senhas deles
com hash, pronto para as mesmas contagens e o mesmo login. Duas coisas para
saber antes de apertar. O projeto novo é cobrado como um projeto à parte, e o
Supabase mostra o custo antes de começar. E ele copia tudo, tarefas agendadas
incluídas: o Supabase diz que as tarefas do pg_cron, do pg_net e dos
wrappers começam a rodar assim que a restauração termina, sem como pausar
antes. Se uma tarefa do seu app manda emails ou cobra um cartão, o projeto de
teste vai fazer isso também.
Se você também guarda um arquivo fora da conta, esse arquivo precisa de um simulado próprio.
Com que frequência devo testar uma restauração?
Uma vez agora, depois a cada três meses, e de novo sempre que alguma coisa mudar no jeito como o backup é feito.
As mudanças que importam são as que quebram um backup em silêncio: um workflow novo ou editado, uma senha do banco redefinida, uma troca para um plano novo ou para uma versão nova do Postgres, uma tabela nova em que o seu app começou a escrever. Depois de cada uma delas, o simulado do trimestre passado já não descreve o arquivo deste trimestre.
Depois anote, que é a folha ao lado da porta. Uma linha por simulado, num lugar que você alcança sem depender do que quebrou: a data, qual arquivo, as contagens que importavam, se o login funcionou e quanto tempo o simulado inteiro levou. Um arquivo de texto no repositório do backup serve, e um evento recorrente na agenda com os resultados colados também. A data responde "quando provamos isso pela última vez" na hora em que alguém precisa saber, e o tempo que levou é a sua primeira estimativa de quanto tempo uma restauração de verdade deixaria o seu app fora do ar.
Onde o Reeve Care entra
O Care guarda cópias do seu banco do Supabase fora da sua conta do Supabase, no horário do seu plano, confere cada cópia no momento em que ela é feita e coloca tudo de volta com um botão.
- As cópias seguem o horário do seu plano, de uma vez por dia até a cada seis horas.
- Uma cópia cortada é pega no momento em que é feita. A linha final do
pg_dumptem que estar no arquivo, senão a cópia não passa na conferência e nunca vira a data no seu painel. - Cada tabela é contada enquanto a cópia é gravada. Quando uma tabela que tinha linhas na cópia anterior não tem nenhuma nesta, uma pessoa da Reeve fica sabendo.
- Suas contas estão dentro, e os seus arquivos enviados vêm junto assim que você conecta uma credencial do Storage.
- Restaurar é um botão, e uma cópia do estado atual é feita antes de qualquer coisa ser substituída.
- Qualquer cópia pode ser baixada como zip com
schema.sql,data.sql,roles.sqle um manifesto com o número de linhas de cada tabela, que é a metade "contra o quê" deste artigo, já anotada.
Um simulado trimestral prova a cópia que você escolheu naquele dia, e a conferência roda em cada cópia no momento em que ela é feita. A cópia, a conferência e a restauração estão desenhadas passo a passo na página de backups do Supabase, e o que cada plano inclui, horário e tudo, está na página de preços.
O que fazer esta semana
O que fazer
- Ache o seu backup mais recente e leia a data dele. Se for mais antigo que a última execução agendada, conserte o job antes de qualquer coisa.
- Procure
dump completeeCOPY "auth"."users"nodata.sql. Duas buscas dizem se o arquivo chega ao fim e se as suas contas estão nele. - Crie um projeto de teste, ou inicie o Supabase no seu próprio computador, e carregue o arquivo com o comando
psqldo guia do Supabase. - Rode a consulta de contagem nos dois bancos e coloque as duas listas lado a lado. Leia a linha mais recente de uma tabela que você conhece.
- Entre no projeto de teste com a sua própria conta.
- Anote a data, as contagens e quanto tempo levou, e depois apague o projeto de teste.
Antes de fechar esta aba, procure dump complete no seu data.sql mais
recente. É uma busca só, e ela diz se o arquivo que você chama de backup chega
à própria última linha. Se você ainda não tem um arquivo para procurar,
uma GitHub Action gratuita é o jeito
mais rápido de começar a gerar.
Perguntas frequentes
Como eu sei se o backup do meu Supabase funciona mesmo?
Restaure num projeto que não importa e veja o que volta. Compare o número de linhas de cada tabela com o banco em produção, confira se a linha mais recente é da noite em que a cópia foi feita e entre com a sua própria conta. Nada no próprio arquivo separa um dump bom de um quebrado: o nome, o tamanho e o check verde ao lado do job são iguais nos dois casos.
Com que frequência devo testar uma restauração?
Uma vez agora, depois a cada três meses, e de novo sempre que mudar o jeito como o backup é feito: um workflow novo ou editado, uma senha do banco redefinida, um plano ou uma versão do Postgres novos, ou uma tabela nova em que o seu app escreve. Anote a data toda vez, com as contagens e quanto tempo levou, para que a pergunta de quando isso foi provado pela última vez tenha resposta.
Dá para testar uma restauração sem mexer no banco em produção?
Dá, e é sempre assim que você deve fazer. Restaure num projeto de teste no Supabase, o que o plano gratuito permite, ou num Supabase rodando no seu próprio computador com a CLI e o Docker. A única coisa que o simulado faz com o banco em produção é lê-lo uma vez para contar as linhas. Apague o projeto de teste depois, porque ele guarda uma cópia real dos seus usuários.
O que devo conferir depois de restaurar um backup?
Quatro coisas. O número de linhas de cada tabela ao lado do número em produção, com a cópia um pouco atrás e nunca em zero numa tabela que tinha linhas. A linha mais recente de uma tabela que você conhece, que deve ser da noite da cópia. O seu próprio email em auth.users. E um login com a sua conta, a única conferência que prova que as contas funcionam e não só que chegaram.
A restauração funcionou, mas ninguém consegue entrar. Por quê?
Quase sempre porque o arquivo nunca teve as suas contas. O Supabase guarda as contas num schema chamado auth, e um dump que nomeou só o seu próprio schema, ou um supabase db dump sem opções, deixa as contas de fora enquanto cada uma das suas tabelas volta sem problema. Procure primeiro COPY "auth"."users" no arquivo. Se não estiver lá, faça um dump de dados com --data-only, que percorre o schema auth e leva os seus usuários junto.
Um arquivo de backup cortado falha na restauração?
Nem sempre. Cortamos um arquivo do pg_dump em três pontos e carregamos cada versão com --single-transaction e ON_ERROR_STOP, as opções do guia de restauração do Supabase. Um corte no meio de um valor parou com um erro. Um corte dentro da última coluna de uma linha e um corte entre duas tabelas terminaram os dois sem erro, com as tabelas incompletas. Um dump completo traz a linha PostgreSQL database dump complete perto do fim, então procure por ela antes de confiar num arquivo.