[{"data":1,"prerenderedAt":1226},["ShallowReactive",2],{"blog-pt-test-your-supabase-backup":3,"blog-index-pt":873},{"id":4,"title":5,"body":6,"category":828,"cover":829,"coverAlt":830,"description":831,"draft":832,"extension":833,"faq":834,"image":850,"keywords":851,"meta":860,"navigation":861,"ogTitle":862,"path":863,"published":864,"seo":865,"stem":866,"tldr":867,"updated":871,"__hash__":872},"blog_pt\u002Fblog\u002Ftest-your-supabase-backup.md","Teste o backup do seu Supabase antes do dia em que precisar",{"type":7,"value":8,"toc":812},"minimark",[9,13,21,24,29,32,35,39,42,147,156,162,166,173,187,212,222,239,244,248,251,276,302,320,330,333,348,352,355,430,438,471,475,478,484,492,495,505,511,514,575,579,585,591,597,618,624,628,636,639,645,648,652,659,675,678,682,685,688,691,695,700,751,763,767,799],[10,11,12],"p",{},"Em algum lugar existe um arquivo com o seu banco de dados dentro. Uma GitHub\nAction grava um toda noite, ou você rodou uma vez os três comandos de backup do\nSupabase, ou o seu plano faz cópias diárias. Ele tem o nome certo e mais ou\nmenos o tamanho que você esperaria. Ninguém nunca abriu.",[10,14,15,16,20],{},"Esta é a parte que os guias de configuração deixam para depois: ",[17,18,19],"strong",{},"um backup que\nnunca foi restaurado é uma promessa, não uma cópia."," O único jeito de testar\num backup do Supabase é restaurá-lo, de propósito, num lugar onde nada depende\ndele, e olhar o que volta. Um dump cortado no meio, um dump sem nenhuma linha e\num dump do projeto errado ficam todos no armazenamento com a mesma cara de um\nbom.",[10,22,23],{},"Pense num simulado de incêndio. Um prédio faz o simulado numa manhã qualquer,\nquando nada está pegando fogo, porque ninguém deveria descer aquela escada\npela primeira vez no dia em que ela se enche de fumaça. Lá fora, alguém faz a\nchamada pela lista de quem estava dentro, e alguém anota a data na folha ao\nlado da porta. Um simulado de restauração é a mesma coisa: fazer o caminho,\ncontar e anotar.",[25,26,28],"h2",{"id":27},"como-eu-sei-se-o-backup-do-meu-supabase-funciona-mesmo","Como eu sei se o backup do meu Supabase funciona mesmo?",[10,30,31],{},"Restaure e olhe. É o único teste que existe, porque nada no próprio arquivo\nsepara um backup bom de um quebrado.",[10,33,34],{},"O simulado pega a sua cópia mais recente, carrega num projeto que não importa\ne faz três perguntas ao resultado. Cada tabela está lá, com mais ou menos\ntantas linhas quanto a de produção? A linha mais recente é da noite em que a\ncópia foi feita? Você consegue entrar com a sua própria conta? Um arquivo bom\nresponde sim às três, e cada jeito de um backup dar errado falha em pelo menos\numa delas.",[25,36,38],{"id":37},"cinco-jeitos-de-um-backup-estar-errado-e-ainda-parecer-certo","Cinco jeitos de um backup estar errado e ainda parecer certo",[10,40,41],{},"Os cinco terminam na noite sem nenhum erro, e os cinco deixam um arquivo com o\nnome de sempre no lugar de sempre. Eles só se separam quando o arquivo é\ncarregado.",[43,44,45,61],"table",{},[46,47,48],"thead",{},[49,50,51,55,58],"tr",{},[52,53,54],"th",{},"O que há de errado com o arquivo",[52,56,57],{},"Como ele costuma chegar a isso",[52,59,60],{},"O passo do simulado que pega",[62,63,64,88,107,125,136],"tbody",{},[49,65,66,70,85],{},[67,68,69],"td",{},"Ele para no meio do caminho",[67,71,72,73,77,78,81,82,84],{},"Um script que passa o ",[74,75,76],"code",{},"pg_dump"," para o ",[74,79,80],{},"gzip"," informa o que o ",[74,83,80],{}," 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",[67,86,87],{},"A linha final, depois as contagens",[49,89,90,93,104],{},[67,91,92],{},"Tem as suas tabelas e nenhuma das linhas",[67,94,95,96,99,100,103],{},"O ",[74,97,98],{},"supabase db dump"," rodou sem ",[74,101,102],{},"--data-only",", e assim ele grava só a estrutura",[67,105,106],{},"As contagens: todas as tabelas em zero",[49,108,109,112,118],{},[67,110,111],{},"Tem as linhas e nenhuma das contas",[67,113,114,115],{},"O dump nomeou só o seu próprio schema, e os seus usuários vivem num chamado ",[74,116,117],{},"auth",[67,119,120,121,124],{},"A busca por ",[74,122,123],{},"auth.users",", depois o login",[49,126,127,130,133],{},[67,128,129],{},"São os dados de outro projeto",[67,131,132],{},"A connection string aponta para uma cópia de staging ou para um projeto antigo",[67,134,135],{},"A linha mais recente, do dia errado",[49,137,138,141,144],{},[67,139,140],{},"Não carrega de jeito nenhum",[67,142,143],{},"Um dump do Postgres 17 carregado no Postgres 15, ou linhas de dono que o projeto novo recusa",[67,145,146],{},"A restauração para com um erro",[10,148,149,150,155],{},"O segundo e o terceiro são o assunto de\n",[151,152,154],"a",{"href":153},"\u002Fblog\u002Fsupabase-backup-auth-users","por que o seu dump do Supabase não tem usuários",",\ne os dois vêm de um comando de dump rodado com menos opções do que precisava. O\nprimeiro nos surpreendeu, então ganhou uma seção só dele.",[157,158],"diagram",{"alt":159,"caption":160,"src":161},"Seis arquivos lacrados idênticos em fila, cada um caindo num banco restaurado. O primeiro tem tabelas cheias e um registro de pessoas, com check. Cinco estão riscados: uma tabela cortada ao lado de uma vazia, todas as tabelas vazias, um registro vazio, linhas cinzas marcadas como diferentes e uma carga parada numa barra.","No armazenamento, os seis arquivos parecem iguais. Carregado, só o primeiro devolve o banco que você tinha.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fsix-files-one-good-copy-1600x760.png",[25,163,165],{"id":164},"um-arquivo-de-backup-cortado-falha-na-restauração","Um arquivo de backup cortado falha na restauração?",[10,167,168,169,172],{},"Nem sempre. Cortamos um no meio de uma tabela, carregamos com as opções que o\npróprio guia do Supabase usa, e o ",[74,170,171],{},"psql"," terminou sem nenhum erro.",[10,174,175,176,178,179,182,183,186],{},"O teste foi pequeno e fácil de repetir. Em 27 de setembro de 2026 fizemos o\ndump de um banco com duas tabelas, uma de 5.000 linhas e outra de 300,\ncortamos o arquivo em três pontos diferentes e carregamos cada versão com o\n",[74,177,171],{}," do Postgres 17.11. Toda carga usou ",[74,180,181],{},"--single-transaction"," e\n",[74,184,185],{},"--variable ON_ERROR_STOP=1",", as duas opções que existem para parar uma\nrestauração no primeiro problema e desfazer tudo.",[188,189,190,200,206],"ul",{},[191,192,193,196,197,199],"li",{},[17,194,195],{},"Cortado no meio de um valor",", o ",[74,198,171],{}," parou com um erro e não gravou\nnada. É o resultado que você esperaria.",[191,201,202,205],{},[17,203,204],{},"Cortado dentro da última coluna de uma linha",", terminou com código de\nsaída 0, que é como um programa diz que deu certo. A primeira tabela voltou\ncom 2.596 das suas 5.000 linhas, a última delas sem metade do texto, e a\nsegunda tabela voltou vazia.",[191,207,208,211],{},[17,209,210],{},"Cortado exatamente entre as duas tabelas",", também terminou com 0. A\nprimeira tabela estava completa e a segunda vazia.",[10,213,214,215,218,219,221],{},"O motivo está no jeito como um dump guarda as linhas. As linhas de cada tabela\nficam num bloco que termina com uma linha contendo só ",[74,216,217],{},"\\.",", e quando o arquivo\nacaba antes dessa linha, o ",[74,220,171],{}," toma o fim do arquivo como o fim do bloco. O\núnico sinal de que faltava alguma coisa é uma linha que deveria estar bem no\nfinal.",[10,223,224,225,227,228,231,232,235,236,238],{},"Essa linha é a assinatura do ",[74,226,76],{},". Um dump completo tem as palavras\n",[74,229,230],{},"PostgreSQL database dump complete"," perto do fim, e um cortado não tem. Dos\ntrês arquivos que a CLI do Supabase grava, a linha só sobrevive no ",[74,233,234],{},"data.sql",",\nporque a CLI tira todos os comentários do arquivo de schema (conferido com a\nversão 2.111 da CLI). Então o ",[74,237,234],{}," é o arquivo onde procurar, e essa\nbusca é o segundo passo do simulado.",[157,240],{"alt":241,"caption":242,"src":243},"Um arquivo com a borda de baixo rasgada entra num passo de restauração marcado ON_ERROR_STOP=1 com um check verde. Depois dele, duas tabelas: a primeira cheia até mais ou menos a metade, 2596 de 5000, com a última linha rasgada; a segunda vazia, 0 de 300.","A carga informou sucesso. A primeira tabela voltou pela metade e a segunda voltou vazia.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fa-short-file-restores-clean-1600x680.png",[25,245,247],{"id":246},"onde-devo-restaurar","Onde devo restaurar?",[10,249,250],{},"Num projeto do Supabase que não importa: um projeto de teste na sua conta, ou\num Supabase rodando no seu próprio computador. Nunca no projeto que o seu app\nusa.",[10,252,253,256,257,263,264,269,270,275],{},[17,254,255],{},"Um projeto de teste no Supabase"," é o mais parecido com o seu projeto real,\ne é o destino para o qual\n",[151,258,262],{"href":259,"rel":260},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fmigrating-within-supabase\u002Fbackup-restore",[261],"nofollow","o guia de backup e restauração do Supabase","\nfoi escrito: o primeiro passo dele é criar um projeto novo. No plano gratuito\nvocê\n",[151,265,268],{"href":266,"rel":267},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fbilling-faq",[261],"tem direito a dois projetos gratuitos ativos",",\ne os pausados não contam, então um projeto de teste costuma não custar nada\ndesde que o seu banco caiba no plano gratuito. Numa organização paga, o\nprocessamento de um projeto novo é\n",[151,271,274],{"href":272,"rel":273},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fmanage-your-usage\u002Fcompute",[261],"cobrado por hora",",\nentão apague o projeto quando o simulado terminar.",[10,277,278,281,282,293,294,297,298,301],{},[17,279,280],{},"Supabase no seu próprio computador"," não custa nada e não precisa de conta. A\nCLI do Supabase roda o stack inteiro localmente no Docker:\n",[151,283,286,289,290],{"href":284,"rel":285},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Flocal-development\u002Fcli\u002Fgetting-started",[261],[74,287,288],{},"supabase init",", depois ",[74,291,292],{},"supabase start",",\ne mostra um endereço de banco na porta 54322 e uma publishable key para o\nprojeto local. Antes de iniciar, abra ",[74,295,296],{},"supabase\u002Fconfig.toml"," e coloque em\n",[74,299,300],{},"major_version"," a versão principal do Postgres do seu projeto. O comentário\nacima dessa configuração diz que elas precisam bater, e a versão do seu projeto\nfica em Project Settings, depois General.",[10,303,304,305,307,308,311,312,314,315,319],{},"No Postgres 15 há uma pegadinha. A menos que o job de backup tenha fixado uma\nversão, a CLI fez a cópia com o ",[74,306,76],{}," 17, e o arquivo de dados passa a ter,\nperto do começo, ",[74,309,310],{},"SET transaction_timeout = 0",", uma configuração que o Postgres\n15 não reconhece, então a carga para nessa linha. Para o simulado, coloque\n",[74,313,300],{}," em 17. Depois aplique no job de backup a correção de uma linha\nque ",[151,316,318],{"href":317},"\u002Fblog\u002Fsupabase-backup-github-action","o artigo sobre a GitHub Action","\nmostra, porque o projeto em que você restauraria de verdade continua no 15.",[10,321,322,323,325,326,329],{},"Um Postgres puro no Docker, sem nada do Supabase dentro, não basta. Um dump do\nSupabase faz referência a coisas que só o Supabase cria, como o schema ",[74,324,117],{},"\nonde vivem os seus usuários e o papel ",[74,327,328],{},"authenticated"," que as suas regras de\nsegurança nomeiam, e a restauração para na primeira linha que menciona uma\ndelas.",[10,331,332],{},"Um cuidado, porque o projeto de teste agora guarda uma cópia real. Ele tem os\nemails dos seus usuários, então não aponte o seu app nem os webhooks dele para\nlá, e apague o projeto quando terminar.",[10,334,335,336,339,340,343,344,347],{},"As tarefas agendadas são a parte que não vem junto. Se o seu projeto as roda com\na extensão ",[74,337,338],{},"pg_cron",", os três arquivos da CLI trazem a extensão de volta e\nnenhuma das tarefas, porque as tarefas são linhas de ",[74,341,342],{},"cron.job"," e o dump de\ndados deixa essas linhas de fora. Conferimos isso em 4 de outubro de 2026 com a\nversão 2.119 da CLI, restaurando um banco que tinha uma tarefa agendada. Por\nisso o projeto de teste fica quieto, e uma restauração de verdade a partir\ndesses arquivos também começa sem nenhuma tarefa agendada, então guarde as suas\nchamadas a ",[74,345,346],{},"cron.schedule"," num lugar de onde você possa rodá-las de novo.",[25,349,351],{"id":350},"como-testar-um-backup-do-supabase-passo-a-passo","Como testar um backup do Supabase, passo a passo",[10,353,354],{},"Seis passos, e os três primeiros acontecem antes de você restaurar qualquer\ncoisa.",[356,357,358,364,387,403,418,424],"ol",{},[191,359,360,363],{},[17,361,362],{},"Ache a cópia mais recente e leia a data dela."," Se for mais antiga que a\núltima execução agendada, o job parou, e essa é a sua primeira descoberta.",[191,365,366,376,377],{},[17,367,368,369,372,373,375],{},"Procure ",[74,370,371],{},"dump complete"," no ",[74,374,234],{},"."," Um resultado quer dizer que o\narquivo chegou ao fim. Nenhum quer dizer que ele foi cortado, seja qual for o\ntamanho. A busca de um editor de texto funciona tão bem quanto um terminal:",[378,379,384],"pre",{"className":380,"code":382,"language":383},[381],"language-text","grep -c 'dump complete' data.sql\n","text",[74,385,382],{"__ignoreMap":386},"",[191,388,389,392,393,396,397],{},[17,390,391],{},"Procure nele os seus usuários."," Uma linha que começa com\n",[74,394,395],{},"COPY \"auth\".\"users\""," e tem linhas embaixo quer dizer que as suas contas\nestão no arquivo:",[378,398,401],{"className":399,"code":400,"language":383},[381],"grep -n 'COPY .*auth.*users' data.sql\n",[74,402,400],{"__ignoreMap":386},[191,404,405,408,409,375,412],{},[17,406,407],{},"Carregue o arquivo no projeto de teste"," com o comando do guia do\nSupabase, apontado para a connection string do projeto de teste. Num\nSupabase local essa string é\n",[74,410,411],{},"postgresql:\u002F\u002Fpostgres:postgres@127.0.0.1:54322\u002Fpostgres",[378,413,416],{"className":414,"code":415,"language":383},[381],"psql \\\n  --single-transaction \\\n  --variable ON_ERROR_STOP=1 \\\n  --file roles.sql \\\n  --file schema.sql \\\n  --command 'SET session_replication_role = replica' \\\n  --file data.sql \\\n  --dbname \"postgresql:\u002F\u002F…the spare's connection string…\"\n",[74,417,415],{"__ignoreMap":386},[191,419,420,423],{},[17,421,422],{},"Conte as linhas e leia a mais recente",", nos dois bancos. A consulta está\nna próxima seção.",[191,425,426,429],{},[17,427,428],{},"Entre no projeto de teste com a sua própria conta."," O comando está na\nseção seguinte.",[10,431,432,433,437],{},"Se o passo 4 parar com um erro, o simulado já fez o trabalho dele. As notas de\nsolução de problemas no fim do guia do Supabase cobrem os dois erros mais\ncomuns, os dois sobre papéis, e\n",[151,434,436],{"href":435},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","como restaurar um backup do Supabase","\nexplica do que cada opção desse comando protege você.",[10,439,440,441,444,445,448,449,452,453,456,457,460,461,464,465,470],{},"Faltam nessas notas outras duas paradas em ",[74,442,443],{},"roles.sql",". Topamos com as duas em 4\nde outubro de 2026, ao carregar os arquivos de dois bancos Postgres 17, um deles\num projeto do Supabase, numa cópia local nova do Supabase:\n",[74,446,447],{},"\"supabase_admin\" is a reserved role, only superusers can modify it",", numa linha\nque começa com ",[74,450,451],{},"ALTER ROLE \"supabase_admin\"",", e\n",[74,454,455],{},"permission denied for parameter log_min_messages",", numa linha que começa com\n",[74,458,459],{},"GRANT SET ON PARAMETER",". As duas linhas configuram papéis que o Supabase cria\npor conta própria em todo projeto, então coloque ",[74,462,463],{},"--"," no começo de cada uma para\nvirar comentário e rode o comando de novo.\n",[151,466,469],{"href":467,"rel":468},"https:\u002F\u002Fgithub.com\u002FReeve-page\u002Fsupabase-backup-action",[261],"A nossa Action de backup","\njá comenta essas linhas ao fazer a cópia.",[25,472,474],{"id":473},"o-que-contar-e-contra-o-quê","O que contar, e contra o quê",[10,476,477],{},"Conte cada tabela no projeto de teste e no seu projeto em produção com a mesma\nconsulta, e coloque as duas listas lado a lado. A cópia deve estar uma noite\natrás do banco em produção: um pouco mais baixa numa tabela que cresce, e nunca\nzerada numa tabela que tinha linhas.",[10,479,480,481,483],{},"É a chamada pela lista de quem estava dentro. Cole a consulta no editor SQL de\ncada projeto e aperte Run. Ela conta as linhas de cada tabela do seu próprio\nschema e do ",[74,482,117],{},":",[378,485,490],{"className":486,"code":488,"language":489,"meta":386},[487],"language-sql","select table_schema, table_name,\n       (xpath('\u002Frow\u002Fn\u002Ftext()',\n         query_to_xml(format('select count(*) as n from %I.%I', table_schema, table_name),\n                      false, true, '')))[1]::text::bigint as row_count\n  from information_schema.tables\n where table_schema in ('public', 'auth')\n   and table_type = 'BASE TABLE'\n order by table_schema, table_name;\n","sql",[74,491,488],{"__ignoreMap":386},[10,493,494],{},"Ela lê cada linha de cada tabela, então num banco grande rode fora dos seus\nhorários de mais movimento.",[10,496,497,498,501,502,483],{},"Depois leia a linha mais recente de uma tabela que você conhece, só no projeto\nde teste. Qualquer tabela com uma coluna ",[74,499,500],{},"created_at"," serve; coloque o nome\ndela no lugar de ",[74,503,504],{},"orders",[378,506,509],{"className":507,"code":508,"language":489,"meta":386},[487],"select max(created_at) from public.orders;\n",[74,510,508],{"__ignoreMap":386},[10,512,513],{},"A resposta deve estar perto da hora em que o backup rodou. Uma data semanas\nmais antiga, ou linhas que você não reconhece, querem dizer que o arquivo veio\nde outro projeto.",[43,515,516,529],{},[46,517,518],{},[49,519,520,523,526],{},[52,521,522],{},"Conferência",[52,524,525],{},"Onde",[52,527,528],{},"O que uma cópia boa mostra",[62,530,531,542,553,565],{},[49,532,533,536,539],{},[67,534,535],{},"Linhas em cada tabela",[67,537,538],{},"Nos dois",[67,540,541],{},"As mesmas tabelas, cada uma um pouco atrás da produção, nenhuma vazia que tinha linhas",[49,543,544,547,550],{},[67,545,546],{},"A linha mais recente",[67,548,549],{},"Projeto de teste",[67,551,552],{},"Uma hora da noite em que a cópia foi feita",[49,554,555,558,560],{},[67,556,557],{},"A sua própria conta",[67,559,549],{},[67,561,562,563],{},"O seu email em ",[74,564,123],{},[49,566,567,570,572],{},[67,568,569],{},"Um login",[67,571,549],{},[67,573,574],{},"Volta um token",[25,576,578],{"id":577},"por-que-o-login-é-o-teste-que-prova-as-suas-contas","Por que o login é o teste que prova as suas contas",[10,580,581,582,584],{},"Uma contagem de ",[74,583,123],{}," prova que as linhas chegaram. Um login prova que\nelas funcionam: que a senha guardada, o serviço de login do projeto de teste e\no seu email ainda combinam entre si.",[10,586,587,588,590],{},"Use a sua própria conta, com uma senha que você conhece. O endereço do projeto\ne a publishable key do projeto de teste ficam no painel Connect dele, ou na\nsaída do ",[74,589,292],{}," num Supabase local:",[378,592,595],{"className":593,"code":594,"language":383},[381],"curl -X POST 'https:\u002F\u002F…the spare's project ref….supabase.co\u002Fauth\u002Fv1\u002Ftoken?grant_type=password' \\\n  -H \"apikey: sb_publishable_…\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\": \"you@example.com\", \"password\": \"…\"}'\n",[74,596,594],{"__ignoreMap":386},[10,598,599,600,605,606,609,610,613,614,617],{},"Essa é a chamada de login da\n",[151,601,604],{"href":602,"rel":603},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fpasswords",[261],"própria documentação do Supabase",",\napontada para o projeto de teste. Uma resposta com ",[74,607,608],{},"access_token"," quer dizer\nque a sua conta chegou com uma senha que funciona. ",[74,611,612],{},"Invalid login credentials",",\npara uma conta que entra sem problema no seu app em produção, quer dizer que\nela não chegou, e\n",[151,615,616],{"href":153},"por que um dump chega sem as contas"," é o\nartigo para esse resultado.",[10,619,620,621,623],{},"Se todo mundo entra no seu app com o Google, essa chamada não tem o que testar,\nporque o projeto de teste não tem login com Google configurado. Procure o seu\npróprio email em ",[74,622,123],{}," depois da restauração. Isso mostra que a linha da\nconta chegou, mas não que a senha dela funciona.",[25,625,627],{"id":626},"arquivos-a-metade-que-uma-restauração-do-banco-não-consegue-testar","Arquivos: a metade que uma restauração do banco não consegue testar",[10,629,630,631,635],{},"A cópia do banco guarda uma linha para cada arquivo enviado e nenhum dos\narquivos. Se você copia os seus buckets do Storage num job próprio, que\n",[151,632,634],{"href":633},"\u002Fblog\u002Fsupabase-storage-backup","é o único jeito de eles serem copiados",", faça\num simulado com essa cópia também.",[10,637,638],{},"Pegue as três linhas mais recentes do banco restaurado:",[378,640,643],{"className":641,"code":642,"language":489,"meta":386},[487],"select bucket_id, name from storage.objects order by created_at desc limit 3;\n",[74,644,642],{"__ignoreMap":386},[10,646,647],{},"Ache esses três caminhos na sua cópia dos arquivos e abra cada um. Um caminho\nsem arquivo por trás é uma imagem que os seus usuários veriam quebrada depois\nde uma restauração de verdade.",[25,649,651],{"id":650},"dá-para-testar-os-backups-que-o-supabase-faz-para-mim","Dá para testar os backups que o Supabase faz para mim?",[10,653,654,655,375],{},"Num plano pago, dá, com o Restore to a New Project. É o único jeito de abrir\numa das cópias diárias do próprio Supabase, porque nos projetos atuais\n",[151,656,658],{"href":657},"\u002Fblog\u002Fdownload-your-supabase-backup","você não consegue baixar essas cópias",[10,660,661,662,667,668,670,671,674],{},"O Supabase descreve o recurso como um jeito de\n",[151,663,666],{"href":664,"rel":665},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fplatform\u002Fclone-project",[261],"testar com segurança",".\nEscolha uma cópia na aba Restore to a New Project da página Backups, e o\nSupabase monta um projeto novo com ela, com os seus usuários e as senhas deles\ncom hash, pronto para as mesmas contagens e o mesmo login. Duas coisas para\nsaber antes de apertar. O projeto novo é cobrado como um projeto à parte, e o\nSupabase mostra o custo antes de começar. E ele copia tudo, tarefas agendadas\nincluídas: o Supabase diz que as tarefas do ",[74,669,338],{},", do ",[74,672,673],{},"pg_net"," e dos\nwrappers começam a rodar assim que a restauração termina, sem como pausar\nantes. Se uma tarefa do seu app manda emails ou cobra um cartão, o projeto de\nteste vai fazer isso também.",[10,676,677],{},"Se você também guarda um arquivo fora da conta, esse arquivo precisa de um\nsimulado próprio.",[25,679,681],{"id":680},"com-que-frequência-devo-testar-uma-restauração","Com que frequência devo testar uma restauração?",[10,683,684],{},"Uma vez agora, depois a cada três meses, e de novo sempre que alguma coisa\nmudar no jeito como o backup é feito.",[10,686,687],{},"As mudanças que importam são as que quebram um backup em silêncio: um workflow\nnovo ou editado, uma senha do banco redefinida, uma troca para um plano novo\nou para uma versão nova do Postgres, uma tabela nova em que o seu app começou a\nescrever. Depois de cada uma delas, o simulado do trimestre passado já não\ndescreve o arquivo deste trimestre.",[10,689,690],{},"Depois anote, que é a folha ao lado da porta. Uma linha por simulado, num lugar\nque você alcança sem depender do que quebrou: a data, qual arquivo, as\ncontagens que importavam, se o login funcionou e quanto tempo o simulado\ninteiro levou. Um arquivo de texto no repositório do backup serve, e um evento\nrecorrente na agenda com os resultados colados também. A data responde\n\"quando provamos isso pela última vez\" na hora em que alguém precisa saber, e\no tempo que levou é a sua primeira estimativa de quanto tempo uma restauração\nde verdade deixaria o seu app fora do ar.",[25,692,694],{"id":693},"onde-o-reeve-care-entra","Onde o Reeve Care entra",[10,696,697],{},[17,698,699],{},"O Care guarda cópias do seu banco do Supabase fora da sua conta do Supabase,\nno horário do seu plano, confere cada cópia no momento em que ela é feita e\ncoloca tudo de volta com um botão.",[188,701,702,708,717,723,729,735],{},[191,703,704,707],{},[17,705,706],{},"As cópias seguem o horário do seu plano",", de uma vez por dia até a cada\nseis horas.",[191,709,710,713,714,716],{},[17,711,712],{},"Uma cópia cortada é pega no momento em que é feita."," A linha final do\n",[74,715,76],{}," tem que estar no arquivo, senão a cópia não passa na conferência e\nnunca vira a data no seu painel.",[191,718,719,722],{},[17,720,721],{},"Cada tabela é contada enquanto a cópia é gravada."," Quando uma tabela que\ntinha linhas na cópia anterior não tem nenhuma nesta, uma pessoa da Reeve\nfica sabendo.",[191,724,725,728],{},[17,726,727],{},"Suas contas estão dentro",", e os seus arquivos enviados vêm junto assim que\nvocê conecta uma credencial do Storage.",[191,730,731,734],{},[17,732,733],{},"Restaurar é um botão",", e uma cópia do estado atual é feita antes de\nqualquer coisa ser substituída.",[191,736,737,740,741,744,745,747,748,750],{},[17,738,739],{},"Qualquer cópia pode ser baixada como zip"," com ",[74,742,743],{},"schema.sql",", ",[74,746,234],{},",\n",[74,749,443],{}," e um manifesto com o número de linhas de cada tabela, que é a\nmetade \"contra o quê\" deste artigo, já anotada.",[10,752,753,754,452,758,762],{},"Um simulado trimestral prova a cópia que você escolheu naquele dia, e a\nconferência roda em cada cópia no momento em que ela é feita. A cópia, a\nconferência e a restauração estão desenhadas passo a passo na\n",[151,755,757],{"href":756},"\u002Fsupabase-backups","página de backups do Supabase",[151,759,761],{"href":760},"\u002Fpricing","o que cada plano inclui",", horário e tudo, está na página de preços.",[25,764,766],{"id":765},"o-que-fazer-esta-semana","O que fazer esta semana",[768,769,770],"key-takeaways",{},[188,771,772,775,785,791,794,796],{},[191,773,774],{},"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.",[191,776,368,777,779,780,372,782,784],{},[74,778,371],{}," e ",[74,781,395],{},[74,783,234],{},". Duas buscas dizem se o arquivo chega ao fim e se as suas contas estão nele.",[191,786,787,788,790],{},"Crie um projeto de teste, ou inicie o Supabase no seu próprio computador, e carregue o arquivo com o comando ",[74,789,171],{}," do guia do Supabase.",[191,792,793],{},"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.",[191,795,428],{},[191,797,798],{},"Anote a data, as contagens e quanto tempo levou, e depois apague o projeto de teste.",[10,800,801,802,804,805,807,808,811],{},"Antes de fechar esta aba, procure ",[74,803,371],{}," no seu ",[74,806,234],{}," mais\nrecente. É uma busca só, e ela diz se o arquivo que você chama de backup chega\nà própria última linha. Se você ainda não tem um arquivo para procurar,\n",[151,809,810],{"href":317},"uma GitHub Action gratuita"," é o jeito\nmais rápido de começar a gerar.",{"title":386,"searchDepth":813,"depth":813,"links":814},3,[815,817,818,819,820,821,822,823,824,825,826,827],{"id":27,"depth":816,"text":28},2,{"id":37,"depth":816,"text":38},{"id":164,"depth":816,"text":165},{"id":246,"depth":816,"text":247},{"id":350,"depth":816,"text":351},{"id":473,"depth":816,"text":474},{"id":577,"depth":816,"text":578},{"id":626,"depth":816,"text":627},{"id":650,"depth":816,"text":651},{"id":680,"depth":816,"text":681},{"id":693,"depth":816,"text":694},{"id":765,"depth":816,"text":766},"Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcover-1200x630.png","Uma fila de arquivos de backup lacrados e idênticos, o da frente aceso, ao lado de um banco vazio e tracejado esperando receber um deles.","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.",false,"md",[835,837,839,842,845,848],{"q":28,"a":836},"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.",{"q":681,"a":838},"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.",{"q":840,"a":841},"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.",{"q":843,"a":844},"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.",{"q":846,"a":847},"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.",{"q":165,"a":849},"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.","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",[852,853,854,855,856,857,858,859],"testar backup supabase","verificar backup supabase","teste de restauração supabase","como testar um backup de banco de dados","restaurar backup em banco de teste","meu backup do supabase funciona","verificação de backup supabase","simulado de restauração",{},true,"Teste o backup do Supabase antes de precisar","\u002Fblog\u002Ftest-your-supabase-backup","2026-09-28",{"title":5,"description":831},"blog\u002Ftest-your-supabase-backup",[868,869,870],"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.","2026-10-05","uetDCBQRYPXY6p1zGQtupYHjOsASY1xu21oD0wiWZS8",[874,881,887,893,899,905,911,916,922,928,934,940,946,952,953,958,963,968,974,980,985,991,997,1003,1009,1015,1021,1027,1033,1038,1044,1050,1056,1062,1068,1074,1080,1086,1092,1098,1104,1110,1116,1122,1128,1134,1140,1146,1152,1158,1163,1169,1175,1181,1187,1192,1198,1204,1210,1215,1221],{"path":875,"title":876,"description":877,"published":878,"category":879,"image":880,"draft":832},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" ao enviar","\"New row violates row-level security policy for table objects\" quer dizer que o seu envio não tem regra insert. Deixar o bucket público não cria nenhuma.","2026-10-11","Noções de segurança","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":882,"title":883,"description":884,"published":885,"category":879,"image":886,"draft":832},"\u002Fblog\u002Fbase44-security-scan","Scan de segurança do Base44: o que só ele enxerga","O scan de segurança do Base44 verifica sete tipos de problema por dentro. Esta é a metade que ele lê e mais ninguém, e a metade que ele nunca olha.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":888,"title":889,"description":890,"published":891,"category":879,"image":892,"draft":832},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Sua chave de API vazou. A ordem em que agir","Uma chave de API vazou e você não sabe o que fazer primeiro. Nem toda chave no seu frontend é um vazamento, e a ordem importa mais que a pressa.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":894,"title":895,"description":896,"published":897,"category":879,"image":898,"draft":832},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" sem desligar o RLS","\"Infinite recursion detected in policy for relation\" significa que a sua policy perguntou à tabela que ela protege. Veja como quebrar o círculo.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":900,"title":901,"description":902,"published":903,"category":879,"image":904,"draft":832},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" no Supabase, e a correção errada","\"No API key found in request\" significa que sua requisição chegou ao Supabase sem chave. Quase toda resposta aponta para as regras do seu banco.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":906,"title":907,"description":908,"published":909,"category":879,"image":910,"draft":832},"\u002Fblog\u002Fis-base44-safe","O Base44 é seguro? O que vimos em 5.442 apps Base44","O Base44 é seguro? Rodamos nove verificações em 5.442 apps Base44 no ar. Quase todas tiraram B por motivos que o dono nunca escolheu.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":912,"title":913,"description":914,"published":871,"category":879,"image":915,"draft":832},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Esconder uma chave de API: mova para uma Edge Function do Supabase","Esconder uma chave de API é tirá-la do navegador, e uma Edge Function do Supabase é o menor lugar para guardá-la. Dois passos em volta pesam mais.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":917,"title":918,"description":919,"published":920,"category":879,"image":921,"draft":832},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Seu arquivo .env está exposto? Os doze caminhos para testar","Seu arquivo .env está exposto no seu próprio servidor web? Doze endereços dizem isso em um minuto, e um acerto significa que tudo nele já é público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":923,"title":924,"description":925,"published":926,"category":879,"image":927,"draft":832},"\u002Fblog\u002Fis-v0-safe","Segurança do v0: os 1.790 aplicativos v0 escaneados tiraram A","A segurança do v0 medida em 1.790 aplicativos v0 no ar: todos tiraram A. Só 17 citavam um banco de dados, e é sobretudo isso que esse A mede.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":929,"title":930,"description":931,"published":932,"category":879,"image":933,"draft":832},"\u002Fblog\u002Fis-bolt-safe","O Bolt é seguro? O que vimos em 1.123 aplicativos Bolt","O Bolt é seguro? Passamos 1.123 aplicativos Bolt no ar por nove verificações. A hospedagem saiu limpa. Os achados: chaves e tabelas abertas nos aplicativos.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":935,"title":936,"description":937,"published":938,"category":879,"image":939,"draft":832},"\u002Fblog\u002Fis-supabase-down-or-your-app","O Supabase caiu ou o problema é o seu app? Como saber","O Supabase caiu ou o problema é o seu app? Um projeto pausado, um banco cheio e um erro seu parecem iguais. Quatro verificações separam os casos.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":941,"title":942,"description":943,"published":944,"category":879,"image":945,"draft":832},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","O Supabase criptografa meus dados? Sim. Veja o que isso impede","O Supabase criptografa os dados? Sim: AES-256 em repouso, TLS em trânsito, SOC 2 e ISO 27001. O que cada um cobre, e o vazamento que nenhum deles impede.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":947,"title":948,"description":949,"published":950,"category":879,"image":951,"draft":832},"\u002Fblog\u002Fsupabase-free-plan-limits","Quanto custa o Supabase? Os limites do plano gratuito","Quanto custa o Supabase: o plano gratuito tem 500 MB de banco, 5 GB de egress e nenhum backup. O que acontece em cada limite e o que o Pro de $25 muda.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":863,"title":5,"description":831,"published":864,"category":828,"image":850,"draft":832},{"path":317,"title":954,"description":955,"published":956,"category":828,"image":957,"draft":832},"Backup grátis do Supabase com uma GitHub Action, e a pegadinha","Um backup do Supabase com GitHub Action é grátis e serve para muitos apps. O workflow, a connection string certa e o egress de cada execução.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":657,"title":959,"description":960,"published":961,"category":828,"image":962,"draft":832},"Por que você não consegue baixar seu backup do Supabase","Você não consegue baixar seu backup do Supabase num projeto atual, porque a cópia diária é um snapshot físico. Como conferir e como ter uma cópia só sua.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":964,"title":965,"description":966,"published":961,"category":879,"image":967,"draft":832},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": o grant que falta","A partir de 30 de outubro, uma tabela nova no Supabase responde \"permission denied for table\" até receber um grant. O e-mail mostra só metade.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":969,"title":970,"description":971,"published":972,"category":879,"image":973,"draft":832},"\u002Fblog\u002Fopen-api-endpoint-exposed","Um endpoint de API aberto é um problema? Leia o JSON","Seu scan apontou um endpoint de API aberto. Se isso importa depende do que voltou, e a maioria dos que encontramos era da própria plataforma.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":975,"title":976,"description":977,"published":978,"category":879,"image":979,"draft":832},"\u002Fblog\u002Flovable-security-scan","Escaneamento de segurança do Lovable: o que ele não prova","Escaneamento de segurança do Lovable: o que o Quick scan e o Deep scan checam, quando cada um roda, e a única coisa que nenhum escaneamento por dentro prova.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":153,"title":981,"description":982,"published":983,"category":828,"image":984,"draft":832},"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.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":986,"title":987,"description":988,"published":989,"category":879,"image":990,"draft":832},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domínio expirado, site fora do ar: o que acontece agora","Seu domínio expirou e seu site está fora do ar. O relógio que começa a correr, por que o certificado é o problema menor, e como conferir os dois.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":992,"title":993,"description":994,"published":995,"category":879,"image":996,"draft":832},"\u002Fblog\u002Fis-lovable-safe","O Lovable é seguro? O que vimos em 18.554 aplicativos Lovable","O Lovable é seguro? Passamos 18.554 aplicativos Lovable no ar por nove verificações. A plataforma foi a mais limpa de cinco. Os achados estavam nos aplicativos.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":998,"title":999,"description":1000,"published":1001,"category":879,"image":1002,"draft":832},"\u002Fblog\u002Fvibe-coded-app-security-checklist","O checklist de segurança do vibe coding, em nove verificações","Um checklist de segurança do vibe coding com nove itens, cada um verificável no seu app de fora por qualquer pessoa, e cada um com um teste de uma linha.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":1004,"title":1005,"description":1006,"published":1007,"category":879,"image":1008,"draft":832},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Uma chave secreta da Stripe no frontend pode mover dinheiro","Uma chave secreta da Stripe exposta no seu frontend pode reembolsar, cobrar e ler cada ficha de cliente que você tem. Sua chave pk_live_ é que deve estar aí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":1010,"title":1011,"description":1012,"published":1013,"category":879,"image":1014,"draft":832},"\u002Fblog\u002Fvite-and-next-public-env-vars","Variáveis de ambiente do Vite expostas: o prefixo diz publique isto","Variáveis de ambiente do Vite expostas no seu app: fizeram o que o prefixo pediu. VITE_ e NEXT_PUBLIC_ significam publique isto, e a IA nunca soube o custo.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":1016,"title":1017,"description":1018,"published":1019,"category":879,"image":1020,"draft":832},"\u002Fblog\u002Fbase44-source-maps","Segurança no Base44: o que um scan aponta e o que é seu para corrigir","Segurança no Base44 em 5.438 apps escaneados: três achados em quase todos são da plataforma, o source map é o selo do Base44, e a sua parte é uma lista curta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":1022,"title":1023,"description":1024,"published":1025,"category":879,"image":1026,"draft":832},"\u002Fblog\u002Fis-cursor-ai-safe","O Cursor AI é seguro? O editor, o código e o app que você publicou","O Cursor AI é seguro? Três perguntas em uma busca: o que o Cursor guarda, o que o código que ele escreve erra, e se o app que você publicou está aberto.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1028,"title":1029,"description":1030,"published":1031,"category":879,"image":1032,"draft":832},"\u002Fblog\u002Fis-replit-safe","O Replit é seguro? O que vimos em 3.042 aplicativos Replit no ar","O Replit é seguro? Passamos 3.042 aplicativos Replit no ar por nove verificações externas. Os achados estavam no aplicativo publicado, não no host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":633,"title":1034,"description":1035,"published":1036,"category":828,"image":1037,"draft":832},"Supabase storage backup: sua cópia do banco não tem nenhum arquivo","Um Supabase storage backup é uma tarefa à parte. Os backups do banco guardam a lista dos seus arquivos e nenhum deles, então cada upload fica quebrado.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1039,"title":1040,"description":1041,"published":1042,"category":828,"image":1043,"draft":832},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery do Supabase: preço e limites","O point-in-time recovery do Supabase rebobina seu banco para qualquer segundo da última semana. Custa $100 por mês além do Pro e cobre só o banco.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1045,"title":1046,"description":1047,"published":1048,"category":828,"image":1049,"draft":832},"\u002Fblog\u002Fsupabase-project-paused-recover","Projeto Supabase pausado? Seus dados continuam lá","O Supabase pausou seu projeto depois de uma semana sem atividade. Nada foi apagado, Restaurar fica ao lado do nome e você tem um ano antes disso mudar.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1051,"title":1052,"description":1053,"published":1054,"category":879,"image":1055,"draft":832},"\u002Fblog\u002Fsafest-ai-app-builder","Qual builder de apps com IA é mais seguro? 30.998 apps testados","Qual builder de apps com IA é mais seguro? Escaneamos 30.998 apps no ar do Lovable, Base44, Replit, v0 e Bolt. O builder não é o que decide sua nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":1057,"title":1058,"description":1059,"published":1060,"category":879,"image":1061,"draft":832},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Ative Row Level Security em toda tabela do Supabase e comprove","Ativar Row Level Security no Supabase sem política fecha a tabela por completo. Uma política sem a chave ligada não faz nada. Aqui está o SQL, e o teste.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1063,"title":1064,"description":1065,"published":1066,"category":879,"image":1067,"draft":832},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": o que o aviso não vê","O Supabase marca \"RLS disabled in public\" como erro. Ele não diz nada sobre a política de leitura que deixa a sua tabela igualmente aberta.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1069,"title":1070,"description":1071,"published":1072,"category":879,"image":1073,"draft":832},"\u002Fblog\u002Frotate-supabase-service-role-key","Como rotacionar uma chave service_role do Supabase vazada","O Supabase manda fechar o vazamento primeiro. Outros guias mandam rotacionar agora. O que vale depende de para onde a sua chave service_role vazou.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1075,"title":1076,"description":1077,"published":1078,"category":879,"image":1079,"draft":832},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de segurança para vibe coding comparados, o nosso incluído","O melhor scanner de segurança para vibe coding depende de três perguntas que nenhuma lista de recursos responde. Dez ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1081,"title":1082,"description":1083,"published":1084,"category":879,"image":1085,"draft":832},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: faça você mesmo as cinco verificações","Um Supabase security checker lê o seu app publicado em vez das configurações do projeto. Aqui estão as cinco verificações e como fazer cada uma sozinho.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1087,"title":1088,"description":1089,"published":1090,"category":879,"image":1091,"draft":832},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de segurança para vibe coding: o que ele não vê","Um scanner de segurança para vibe coding lê seu app no ar, de fora. O que isso cobre, as quatro coisas que ele não consegue ver e como ler o resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1093,"title":1094,"description":1095,"published":1096,"category":879,"image":1097,"draft":832},"\u002Fblog\u002Fmissing-security-headers","Cabeçalhos de segurança faltando: quando isso importa","Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1099,"title":1100,"description":1101,"published":1102,"category":879,"image":1103,"draft":832},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Sua chave de API da OpenAI está exposta no frontend. Troque-a.","Uma chave de API da OpenAI exposta no frontend não pode ser presa a um domínio. Troque-a hoje, mova a chamada para o seu servidor e limite o gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1105,"title":1106,"description":1107,"published":1108,"category":879,"image":1109,"draft":832},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chave de API exposta no frontend: o que 30.998 apps entregam","Uma chave de API exposta no seu frontend costuma ser uma chave do Google Maps. Escaneamos 30.998 apps vibe-coded e contamos quais segredos vazam de verdade.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1111,"title":1112,"description":1113,"published":1114,"category":828,"image":1115,"draft":832},"\u002Fblog\u002Fsupabase-backup-tools-compared","Ferramentas de backup do Supabase comparadas, a nossa incluída","Quatro tipos de ferramenta de backup do Supabase, o que cada uma copia de verdade e quando uma GitHub Action gratuita ganha de pagar, nós inclusive.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1117,"title":1118,"description":1119,"published":1120,"category":879,"image":1121,"draft":832},"\u002Fblog\u002Freplit-secrets-explained","Como usar secrets no Replit, e o que ainda assim é publicado","Como usar secrets no Replit: adicionar um, ler de volta e resolver as duas causas do undefined. E as chaves que a ferramenta Secrets não consegue proteger.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1123,"title":1124,"description":1125,"published":1126,"category":828,"image":1127,"draft":832},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups do plano gratuito do Supabase: como fazer sem terminal","No plano gratuito do Supabase não existe backup nenhum: a cópia é você que faz. Como fazer uma pelo painel e o que a rota do CSV deixa para trás.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1129,"title":1130,"description":1131,"published":1132,"category":879,"image":1133,"draft":832},"\u002Fblog\u002Fis-supabase-secure","O Supabase é seguro? É. Seu projeto é outra pergunta","O Supabase é seguro? A plataforma é auditada, criptografada e passa por pentests. A documentação deles diz onde isso termina e começam suas configurações.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1135,"title":1136,"description":1137,"published":1138,"category":879,"image":1139,"draft":832},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Onde ficam as chaves de API do Supabase: anon, service_role e URL","A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1141,"title":1142,"description":1143,"published":1144,"category":879,"image":1145,"draft":832},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1147,"title":1148,"description":1149,"published":1150,"category":879,"image":1151,"draft":832},"\u002Fblog\u002Fcors-wildcard-security-risk","Um curinga CORS é um risco de segurança? Quase nunca.","Um curinga CORS é um risco de segurança? Em geral é o padrão do seu builder e não entrega nada que o seu servidor já não desse a qualquer um que pedisse.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1153,"title":1154,"description":1155,"published":1156,"category":828,"image":1157,"draft":832},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching do Supabase não é backup. Ele só anda para a frente.","Por que o branching do Supabase não é backup: um branch começa sem os seus dados e um merge só leva o esquema. Para que ele serve e o que usar no lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":435,"title":1159,"description":1160,"published":1161,"category":828,"image":1162,"draft":832},"Como restaurar um backup do Supabase, e o que quebra depois","Como restaurar um backup do Supabase pelo painel ou por um arquivo de dump, o que a restauração substitui e por que o seu app pode continuar quebrado no fim.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1164,"title":1165,"description":1166,"published":1167,"category":879,"image":1168,"draft":832},"\u002Fblog\u002Fsupabase-storage-bucket-public","Seu bucket do Supabase Storage é público. Isso é um problema?","Um bucket público do Supabase Storage significa que quem tem a URL de um arquivo pode abri-lo. Não significa que alguém possa listar o que está lá dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1170,"title":1171,"description":1172,"published":1173,"category":879,"image":1174,"draft":832},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Uma chave de API do Google no frontend é um problema?","Uma chave de API do Google exposta no seu frontend é a chave que nosso scanner mais encontra, e quase sempre está tudo bem. Um ajuste gratuito decide isso.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1176,"title":1177,"description":1178,"published":1179,"category":828,"image":1180,"draft":832},"\u002Fblog\u002Fai-agent-deleted-my-database","Um agente de IA apagou meus dados do Supabase. O que eu recupero?","Um agente de IA apagou dados do seu banco. O que você recupera já estava decidido antes de ele rodar, e os próximos minutos decidem o resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1182,"title":1183,"description":1184,"published":1185,"category":879,"image":1186,"draft":832},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Qualquer um consegue ler seu banco Supabase? Testamos 3.680 apps","Qualquer um consegue ler seu banco de dados Supabase sem fazer login? Escaneamos 30.998 apps no ar criadas com builders de IA e medimos quantas dizem que sim.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1188,"title":1189,"description":1190,"published":1185,"category":879,"image":1191,"draft":832},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expostos: seu app está publicando o código original","Um source map exposto deixa qualquer um ler o código original do seu app, comentários incluídos. A verificação de 30 segundos e o que importa de verdade.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1193,"title":1194,"description":1195,"published":1196,"category":879,"image":1197,"draft":832},"\u002Fblog\u002Fsupabase-new-api-keys","As novas chaves de API do Supabase: qual vai no seu app?","O Supabase trocou anon e service_role por chaves publicáveis e secretas. Qual delas pertence ao seu app e qual nunca deve estar lá?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1199,"title":1200,"description":1201,"published":1202,"category":828,"image":1203,"draft":832},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","O Supabase faz backup do meu banco de dados? Depende do plano.","O Supabase faz backup do seu banco de dados? Todo dia nos planos pagos, e nada no gratuito. Como descobrir o que você tem e o que essa cópia não cobre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1205,"title":1206,"description":1207,"published":1208,"category":879,"image":1209,"draft":832},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","O Supabase Row Level Security está ligado. A tabela continua pública.","Ligar o Supabase Row Level Security não protege uma tabela. Quem protege são as políticas, e a que consertou o seu app pode deixar qualquer um entrar.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1211,"title":1212,"description":1213,"published":1208,"category":828,"image":1214,"draft":832},"\u002Fblog\u002Fversion-history-is-not-a-backup","O histórico de versões não é backup. Ele não desfaz um delete.","Lovable e Bolt guardam um histórico de versões do seu código. Seu banco de dados é um serviço à parte, e voltar atrás não traz os seus dados de volta.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1216,"title":1217,"description":1218,"published":1219,"category":828,"image":1220,"draft":832},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Três formas de fazer backup de um banco Supabase, e o que falta","O painel, o pg_dump e um serviço gerenciado. O que cada um salva de verdade, o que deixa de fora sem avisar e qual sobrevive a perder a conta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1222,"title":1223,"description":1224,"published":1219,"category":879,"image":1225,"draft":832},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Quais chaves de API são seguras no navegador e quais não são","Sua chave anon do Supabase foi feita para ser pública. Sua chave service_role não, e ela ignora todas as regras que você criar. Como diferenciar as duas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791705963266]