Backups
Por que seu dump do Supabase não tem usuários dentro
Rode supabase db dump sozinho e você recebe a forma do seu banco e nenhuma das linhas dele, sem o schema auth onde seus usuários moram.

Em resumo
- O Supabase publica o backup dele como três comandos. O que você provavelmente rodou é o segundo, e seus usuários estão no terceiro.
- Rode supabase db dump sem outras flags e você recebe a forma das suas tabelas e nada do conteúdo delas, e o schema auth onde seus usuários moram fica de fora até disso.
- Uma única busca no arquivo que você já tem diz qual de três coisas você está segurando.
Você fez a coisa responsável. Procurou como fazer backup de um banco Supabase, rodou o comando que encontrou e guardou o arquivo em um lugar seguro.
Aí um dia você precisa dele. Você despeja o arquivo em um projeto novo e a
restauração termina sem um único erro. Cada tabela que você já criou está lá, e
cada uma delas está vazia. Seus usuários estão pior ainda: a parte do banco onde
eles moram, um schema chamado auth, nunca chegou ao arquivo.
Aqui está a parte que quase todo guia pula: supabase db dump sozinho não é
uma cópia dos seus dados. Sem outras flags ele escreve a forma do seu banco e
nada do conteúdo, e deixa auth de fora até disso. O Supabase publica o backup
como três comandos, e suas contas viajam no terceiro.
Ajuda pensar em um hotel. Suas tabelas são os quartos e tudo que está dentro deles. O registro da recepção, aquele com o nome de cada hóspede, é do hotel. E uma planta te mostra cada quarto do prédio sem colocar um único hóspede lá dentro.
Um backup do Supabase inclui meus usuários?
Depende de qual comando escreveu o arquivo, e o comando que a maioria roda não inclui.
Seus usuários não são linhas de uma tabela sua. O Supabase guarda eles em uma
gaveta separada do mesmo banco, o schema auth, junto com as senhas com hash,
os provedores pelos quais entraram e as sessões que mantêm. Suas tabelas ficam
em uma gaveta chamada public, e cada coluna user_id nelas é uma referência
para dentro de auth.
Um schema é exatamente isso: uma gaveta com nome dentro de um banco. public é
seu. auth é do Supabase, e storage também, que guarda a linha que descreve
cada arquivo enviado. A documentação do próprio Supabase chama esses de schemas
gerenciados e diz que
normalmente não precisam ser puxados a menos que você os tenha modificado,
que é por que as ferramentas tratam eles diferente das suas tabelas.
Essa divisão é o que permite a um comando produzir dois arquivos que se parecem e contêm coisas completamente diferentes.
O que o comando de dump escreve sozinho
A planta. Nenhuma linha, e nada de auth.
A página de referência do Supabase para o comando diz isso em duas frases. Ele
roda pg_dump com flags extras para excluir os schemas gerenciados pelo
Supabase, e entre os ignorados
estão auth, storage e os criados por extensões.
A mesma página diz depois que o dump padrão não contém dados nem papéis
próprios, e que você consegue esses pedindo com --data-only e --role-only.
Então isto, que é o que você provavelmente rodou:
supabase db dump --db-url "postgresql://…your connection string…" -f backup.sql
produz um arquivo cheio de instruções CREATE TABLE. Cada coluna, cada índice,
cada policy que você escreveu nas suas tabelas, e nenhuma linha de nada.
A razão de isso ser pior que um arquivo obviamente vazio é que funciona. E ele também não parece pequeno: cada definição de tabela, cada índice e cada policy que você já escreveu estão ali, e para um app de verdade isso é muito texto. Um backup vazio se anuncia sozinho. Este restaura limpo, e a primeira coisa que te diz o contrário é uma tela de login que nenhuma conta consegue passar.
Como confiro o dump que eu já tenho?
Abra em um editor de texto e busque por auth. O que aparecer coloca seu
arquivo em um de três grupos.
- Nenhuma ocorrência. O schema
authnão está nesse arquivo de forma alguma. É isso que umsupabase db dumppuro escreve. - Ocorrências, mas só em linhas que começam com
CREATE,ALTERouGRANT. Você tem o desenho do registro e ninguém dentro. - Uma linha
COPY "auth"."users"ouCOPY auth.users, com linhas de dados embaixo até uma linha com\.Ou uma sequência de linhas começando comINSERT INTO "auth"."users". Suas contas estão aí.
Se você preferir fazer na linha de comando, dois greps respondem a mesma pergunta:
grep -c 'auth.*users' backup.sql
grep -n 'COPY .*auth.*users\|INSERT INTO .*auth.*users' backup.sql
O primeiro diz se o schema chegou no arquivo. O segundo diz se as pessoas chegaram. Um zero dos dois, em um arquivo com que você contava, é melhor descobrir hoje do que na manhã em que você precisa dele.
Busque por storage já que está aí, e leia com atenção o que encontrar. Essas
linhas são a lista dos seus arquivos enviados, que é uma coisa diferente dos
arquivos, e
nenhum backup de banco em nenhum plano contém aqueles.
Como exporto os usuários auth do Supabase?
Com o comando de dados, que é um comando diferente do que escreve o schema.
O guia de backup e restauração do Supabase publica o backup como três arquivos, e vale ver os três juntos porque o formato disso é a resposta:
supabase db dump --db-url "postgresql://…" -f roles.sql --role-only
supabase db dump --db-url "postgresql://…" -f schema.sql
supabase db dump --db-url "postgresql://…" -f data.sql --use-copy --data-only \
-x "storage.buckets_vectors" -x "storage.vector_indexes"
A segunda linha é a que é rodada sozinha. A terceira é a que tem seus usuários dentro.
Esses dois fatos parecem uma contradição e não são. A frase da página de
referência do Supabase sobre excluir auth descreve o dump de schema, e o dump
de dados percorre esse schema também.
Se você só quer as contas, nomeie o schema e recebe aquela gaveta sozinha:
supabase db dump --db-url "postgresql://…" -f users.sql --data-only --use-copy --schema auth
Antes de confiar em qualquer um desses, adicione --dry-run e leia o que
volta. Ele imprime o comando pg_dump que a ferramenta vai rodar sem rodar,
então você vê com os próprios olhos quais schemas entram e quais ficam de fora
na versão que você instalou. Leia essa saída uma vez e você nunca mais precisa
acreditar neste artigo, nem em nenhum outro, o que importa porque as flags
realmente se mexem entre versões e o arquivo fica com a mesma cara dos dois
jeitos.
Tem também o caminho direto, e
é para isso que serve um pg_dump simples:
nomeie as gavetas que você quer e ele leva.
pg_dump "postgresql://…" --schema public --schema auth --schema storage \
--no-owner --file backup.sql
Uma coisa para notar sobre o arquivo de schema, porque explica por que isso tudo
é separado. Um projeto Supabase novo chega com um schema auth já construído,
na versão que o serviço de login roda hoje. Despejar por cima a versão do seu
projeto antigo colocaria um desenho mais velho em cima de um que funciona. O que
você quer levar é o conteúdo do registro, e é isso que o arquivo de dados tem.
O que quebra na hora de devolver os usuários
Duas coisas, e o Supabase documenta as duas.
Os triggers, que podem criptografar uma coluna duas vezes. O comando de restauração do guia do Supabase tem no meio uma instrução fácil de ler como enfeite:
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://…"
Essa linha do meio desliga os triggers pelo tempo da operação, e o guia diz que ela está ali para impedir que colunas sejam criptografadas uma segunda vez na entrada. Despeje um arquivo de dados sem ela e as senhas chegam já embaralhadas por um processo que já tinha sido aplicado nelas, e nada depois desfaz isso.
Propriedade e permissões, que param o despejo. Um dump tirado de um projeto
Supabase carrega linhas que se referem a papéis que o projeto novo não deixa
você tocar. As notas de solução de problemas do mesmo guia dizem para comentar
qualquer linha com ALTER ... OWNER TO "supabase_admin" em schema.sql, e uma
linha específica GRANT "postgres" TO "cli_login_postgres" em roles.sql. As
duas são uma edição de texto antes de começar, e as duas param o despejo com a
linha em que ele engasgou impressa na sua tela.
Meus usuários vão ter que entrar de novo?
As senhas deles passam. As sessões não, a menos que você leve mais uma coisa junto.
O Supabase diz que você pode migrar cada tabela do schema auth,
usuários e suas senhas com hash incluídos,
então ninguém precisa redefinir uma senha que já tinha. Nenhuma senha é legível
em ponto nenhum disso; o que se move é o hash dela.
Uma sessão é outra coisa. Ela é provada por um token assinado com o segredo JWT
do seu projeto, e cada projeto tem o seu. O Supabase diz que se o projeto novo
assinar com outro segredo, cada token que já está no navegador de alguém fica
inválido e é pedido àquela pessoa que entre de novo. Você pode evitar isso
colocando o segredo do projeto antigo no novo, e o preço está escrito na mesma
página: trocar o segredo JWT regenera as chaves anon e service_role daquele
projeto, então seu app precisa receber as novas antes de conseguir falar com
qualquer coisa. Qual chave é qual, e qual delas pode estar no seu app, é
o que convém ter claro antes de colar qualquer uma.
Então a versão honesta é que uma restauração normalmente pede a todo mundo que
entre uma vez. Isso é um e-mail para o suporte. Não é uma conta perdida, e a
diferença entre as duas coisas é se o schema auth estava no seu arquivo.
Três coisas continuam de fora, faça o que fizer com as flags. Seus arquivos enviados, porque o Storage guarda os bytes fora do banco e nenhum dump em nenhum plano alcança eles. Suas edge functions, que são um download à parte e cujos import maps, observa o Supabase, não são buscados automaticamente. E as configurações do seu projeto, que são configuração e não dados e são redigitadas à mão.
O que fazer esta semana
O que fazer
- Pegue o arquivo de backup mais recente que você tem e busque
authdentro dele. Grupo um, dois ou três da seção acima, e você sabe em um minuto. - Se for grupo um ou dois, tire hoje um dump de dados com
--data-onlye--use-copy, e guarde ao lado do arquivo de schema em vez de no lugar dele. Você precisa dos dois. - Adicione
--dry-runao comando que você escolher e leia a saída uma vez, para saber quais gavetas a sua versão da ferramenta leva. - Anote a ordem da restauração onde você vá encontrar: roles, depois schema, depois
SET session_replication_role = replica, depois data. - Restaure uma vez em um projeto descartável e então tente entrar como um usuário de verdade. É a única conferência que testa aquilo de que este artigo trata.
Fazer isso uma vez na mão vale a pena de qualquer jeito que você acabe fazendo backup, porque enquanto você não abriu um dump só teve a palavra backup. Se você continua fazendo na mão é outra pergunta, e os três caminhos e quanto cada um custa é onde ela é respondida.
Onde o Reeve Care entra
O Care tira a cópia em um calendário, e o registro vai dentro.
- Suas contas estão na cópia. O schema
authviaja junto com suas tabelas, porque uma cópia de um app Supabase sem os usuários dele é uma cópia da metade. As linhas destorageque descrevem seus arquivos vêm também, e os próprios arquivos assim que você conecta uma credencial do Storage. - O botão de restaurar devolve suas tabelas e deixa as contas em paz. Despejar
auth.usersem cima de um projeto vivo desloga todo mundo e traz de volta contas que alguém apagou de propósito, então isso continua sendo um pedido com uma pessoa em cima. Assim apertar o botão no desespero não consegue deslogar os clientes que você estava tentando ajudar. - A cópia é relida antes de contar como tirada. A data no seu painel é a última vez que uma cópia foi aberta e verificada, nunca a hora em que um job começou ou um arquivo chegou.
- Restaurar tira antes uma foto do estado atual, então a própria restauração tem um desfazer.
O Care começa em $49 por mês para um app. Esse é um preço de tabela, e a página de preços às vezes está abaixo do número daqui e nunca acima.
Como uma cópia é tirada, conferida e devolvida está desenhado passo a passo na página de backups do Supabase.
Antes de fechar esta aba, abra seu dump mais recente e busque auth nele. É o
jeito mais rápido de descobrir se aquilo que você vinha chamando de backup
devolveria seus clientes, e se a resposta for não,
restaurar um do jeito certo é a
próxima leitura.
Perguntas frequentes
Um backup do Supabase inclui meus usuários?
Depende de qual comando escreveu o arquivo. Seus usuários moram em um schema chamado auth, que pertence ao serviço de login. Um supabase db dump puro deixa auth de fora e não contém nenhuma linha de nada, porque o dump padrão é só o schema. A metade de dados do dump, que é um segundo comando com a flag --data-only, é a que carrega seus usuários. É exatamente por isso que o Supabase publica o backup como três comandos.
Por que auth.users está faltando no meu dump?
Porque você quase certamente rodou o dump de schema. O Supabase documenta que o comando exclui os schemas gerenciados por ele, que entre os ignorados estão auth e storage, e que o dump padrão não contém dado nenhum. Isso é proposital: um projeto novo chega com o próprio schema auth já construído pelo serviço de login, então despejar por cima uma cópia mais velha substituiria algo que funciona. O que você quer mover é o conteúdo, e quem carrega isso é o dump de dados.
Como exporto os usuários auth do Supabase?
Com o comando de dados, que é separado do comando de schema. Rode supabase db dump com --data-only e --use-copy para escrever um arquivo de dados, e as tabelas de auth vêm junto. Se você só quer as contas, adicione --schema auth e recebe um arquivo com aquele schema sozinho. Antes de confiar em qualquer um dos dois, adicione --dry-run: ele imprime o comando pg_dump que a CLI vai rodar sem rodar, então você lê quais schemas entram na versão que você tem.
As senhas sobrevivem a uma restauração do Supabase?
Sim, se o schema auth estava no arquivo. O Supabase diz que você pode migrar cada tabela do schema auth, senhas com hash incluídas, então ninguém precisa redefinir nem recriar. A única coisa que pode estragar isso é despejar os dados sem desligar os triggers antes, que é a razão de o Supabase colocar SET session_replication_role = replica no meio do próprio comando de restauração dele. Pule essa linha e uma coluna já criptografada é criptografada uma segunda vez na entrada.
Meus usuários vão continuar logados depois de uma restauração?
Não, se o projeto novo assinar com outro segredo. Uma sessão é provada por um token assinado com o segredo JWT do projeto, e o Supabase diz que um segredo novo invalida os tokens existentes, então é pedido a todo mundo que entre de novo. Você pode levar o segredo antigo junto e manter todos logados, mas o Supabase também diz que trocar o segredo JWT regenera as chaves anon e service_role daquele projeto, então seu app precisa das novas.
O que mais um dump do Supabase deixa de fora?
Seus arquivos enviados, antes de tudo. O Storage guarda uma linha no seu banco para cada arquivo e o arquivo em si em outro lugar, então nenhum dump de banco em nenhum plano contém os bytes. As edge functions são um download à parte, e o Supabase observa que os import maps e os arquivos deno.json não são buscados automaticamente. As configurações do projeto, os provedores de auth e os segredos são configuração e não dados e moram no dashboard, então são redigitados à mão em um projeto novo.