Noções de segurança
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á?

Em resumo
- O Supabase agora emite chaves sb_publishable_ e sb_secret_. Elas substituem anon e service_role e fazem exatamente os mesmos dois trabalhos.
- A chave publicável pertence ao seu app. A secreta nunca, e agora dá para diferenciar lendo os primeiros caracteres.
- Suas chaves antigas ainda funcionam hoje. O Supabase disse que todos os projetos vão ter que sair delas no fim de 2026.
Se você abriu o painel do Supabase há pouco e encontrou chaves começando com
sb_publishable_ e sb_secret_ onde antes ficavam anon e service_role, não
quebrou nada. O Supabase renomeou suas chaves de API, e o par que você conhecia
está de saída.
A mudança é pequena no que faz e grande no que evita. As duas chaves continuam cumprindo exatamente os dois papéis de sempre. O que é novo é que agora você vê qual é qual sem abrir nada.
O que o Supabase mudou de fato
O Supabase anunciou as chaves novas em julho de 2025, junto com uma mudança em como ele assina os tokens de login. Duas coisas substituíram duas coisas:
- A chave publicável,
sb_publishable_…, substitui a chaveanon. - Chaves secretas,
sb_secret_…, substituem a chaveservice_role.
As permissões continuam iguais. Uma chave publicável ainda só identifica o seu projeto e não carrega permissão própria; uma secreta ainda ignora todas as regras que você escreveu. Se você já sabe quais chaves são seguras num frontend, nada dessa intuição ficou errado.
Duas diferenças práticas valem a pena. Você pode ter várias chaves secretas ao mesmo tempo e revogar uma de cada vez, então girar uma chave não significa mais um momento em que tudo o que a usava fica quebrado. E as chaves antigas tinham uma característica que quase ninguém notou: eram JWTs que expiram dez anos depois de você criar o projeto. As novas não carregam validade por dentro.
A chave anon é a mesma coisa que a chave publicável?
Sim no que ela faz, não no que ela é.
sb_publishable_… faz exatamente o trabalho da chave anon: nomeia o seu projeto
para que um pedido saiba para onde ir, não carrega permissões próprias, e é feita
para ficar no seu app onde qualquer um pode ler. Tudo o que você já entendia da
chave anon continua verdadeiro. Se você trocar uma pela outra, nenhuma tabela
fica mais ou menos legível, porque nenhuma das duas nunca protegeu as suas
linhas. Quem faz isso é a Row Level Security.
O que muda é o valor em si. São strings diferentes em formatos diferentes, emitidas separadamente, e um projeto pode ter os dois pares ao mesmo tempo durante a migração. Então «a mesma chave com um nome novo» é a imagem errada. É uma chave nova fazendo um trabalho antigo, e o seu app precisa ser avisado.
Uma consequência pega muita gente: ativar as chaves novas não troca o seu app. O Supabase emite as chaves e deixa o seu app rodando com o que você deu a ele. A troca é uma mudança de uma linha que você mesmo faz, no ponto em que o seu app cria o cliente Supabase.
Qual das duas pertence ao seu app
A publicável, e só ela.
Seu app roda no navegador do seu visitante, e o pedido ao seu banco sai dali. Ele
precisa dizer a qual projeto pertence, e esse identificador chega a todo
visitante por projeto. sb_publishable_… é a chave feita para isso: encontrá-la
no seu app não é um achado, e nunca foi.
sb_secret_… é o oposto. Ela lê e escreve em toda linha de toda tabela, de
qualquer lugar, ignorando por completo as suas políticas, e é exatamente para
isso que ela existe. O lugar dela é um servidor, uma edge function, um worker:
nenhum lugar que um navegador alcance. Se alguma já foi colada em código de
frontend, troque a chave no painel antes de mexer em qualquer outra coisa, porque
apagar a linha não fecha a porta.
Como é uma chave sb_publishable_?
Uma única string contínua que começa com o literal sb_publishable_, seguido de
um meio aleatório. Nenhum ponto dentro dela, e nada ali que dê para decodificar.
A contraparte secreta se lê igual, com sb_secret_ na frente.
O par antigo não se parece nada com isso. anon e service_role são JWTs: três
blocos separados por pontos, com algumas centenas de caracteres, começando com
eyJ. O bloco do meio não é criptografado, só codificado, então qualquer um cola
num decodificador e lê o campo role lá dentro. Era assim que se distinguia os
dois antes, e é por isso que tanta gente nunca distinguiu.
Ler os primeiros quinze caracteres é a verificação inteira agora. A chave perigosa se anuncia na parte da string onde o seu olho cai primeiro, em vez de no meio de uma coisa que você precisa abrir.
Como saber qual delas você tem
Leia os primeiros caracteres. Hoje essa é toda a conferência.
| O que você vê | O que é | Segura no navegador? |
|---|---|---|
sb_publishable_… | chave publicável atual | É o lugar dela |
sb_secret_… | chave secreta atual | Nunca |
eyJ… com anon | chave publicável antiga | É o lugar dela |
eyJ… com service_role | chave secreta antiga | Nunca |
Uma chave atual é uma sequência longa em duas metades: um miolo aleatório e uma
soma de verificação curta no fim. Uma chave antiga são três blocos separados por
pontos, e o do meio é texto legível em vez de criptografia, e por isso diferenciar
o par antigo passava por decodificá-lo e ler o campo role.
Se você achou uma chave no seu app e não sabe qual é, nosso scan gratuito lê o seu site no ar por fora e diz o que consegue ver. Leva uns 20 segundos e não precisa de conta: escaneie seu app.
Minhas chaves anon e service_role antigas ainda funcionam?
Hoje, sim. O Supabase publicou um cronograma, não um botão de desligar:
| Quando | O que acontece |
|---|---|
| 1 de novembro de 2025 | Projetos restaurados depois dessa data não ganham mais anon nem service_role. |
| Fim de 2026, sem data exata | Todos os projetos vão precisar usar as chaves novas. |
Ou seja: não há emergência esta semana, e há um prazo este ano. Se o seu app foi feito antes da renomeação e não foi tocado desde então, ele está rodando com chaves antigas agora e vai continuar por um tempo.
O argumento para mudar cedo não é o prazo. É o dia em que alguém cola a chave
errada num prompt: sb_secret_ se entrega, eyJ… não.
O que são as chaves de API legadas do Supabase?
Legadas é como o Supabase chama hoje o par original, anon e service_role,
junto com o segredo JWT que assina as duas. Todo projeto criado antes de meados
de 2025 começou com elas, o que é a maioria dos apps feitos com vibe coding.
Elas diferem do par novo em pontos que vale conhecer. Sendo JWTs, carregam uma expiração dez anos depois da criação do projeto, dentro da própria chave, onde ninguém olha. Não dá para trocá-las de jeito nenhum: o Supabase disse que trocar os segredos legados anon, service_role e JWT não é mais possível, então invalidar uma que vazou significa migrar para as chaves novas e desativar o par antigo. E um projeto restaurado depois de 1 de novembro de 2025 nem recebe elas.
Se uma das suas já vazou, essa migração é a única forma de invalidar a chave, e a ordem para fazer isso depende de a chave já estar num bundle que os seus visitantes baixam.
Como trocar sem quebrar o seu app
O guia de migração do próprio Supabase é a referência. A versão curta, para um app que você não escreveu na mão, partindo do princípio de que você já sabe achar a página onde ficam as suas chaves:
- No painel, abra Settings → API Keys e crie as chaves novas. Isso adiciona as novas; não tira as antigas, e os dois pares funcionam ao mesmo tempo.
- Ache onde o seu app cria o cliente do Supabase e troque a chave publicável. Num builder como Lovable ou Bolt isso costuma ser um valor nas configurações do projeto, não uma linha de código.
- Troque a chave secreta em todo lugar onde ela é usada num servidor: edge functions, webhooks, tarefas agendadas, qualquer coisa que não seja o navegador.
- Abra o seu app e passe pelas partes que leem e escrevem dados. Uma chave publicável errada falha na hora e alto, que é o caso bom.
- Só quando tudo estiver funcionando, desative as chaves antigas.
O passo 5 é o que fica por último, e vale fazer de propósito em vez de nunca:
projetos meio migrados, em que o app ainda carrega uma chave anon velha ao lado
de uma sb_publishable_ viva, são comuns e confusos de depurar.
O que fazer esta semana
O que fazer
- Abra Settings → API Keys e veja quais pares o seu projeto tem. Leva um minuto e já diz onde você está.
- Se achar
sb_secret_…ouservice_roleem qualquer lugar do código do frontend, troque a chave hoje. É o único item urgente desta lista. - Crie as chaves novas e passe o seu app para elas quando tiver meia hora, não por causa do prazo, e sim porque o prefixo deixa o próximo erro óbvio.
- Aproveite e olhe o Row Level Security. A chave nova não muda nada do que as suas políticas permitem, e ligar o RLS não é a mesma coisa que estar protegido.
Se quiser a versão específica da plataforma sobre o que conferir, temos um guia em linguagem simples para apps com Supabase, e o checklist de segurança de 10 minutos cobre isso junto com as outras coisas que vale desligar num app recém-lançado.
Perguntas frequentes
sb_publishable_ é a mesma coisa que a chave anon?
Ela faz o mesmo trabalho. Diz qual é o seu projeto para o pedido saber para onde ir, não carrega permissão nenhuma própria e foi feita para ficar no seu app, onde qualquer pessoa pode ler. O que protege seus dados nos dois casos é o Row Level Security, não a chave.
Minhas chaves anon e service_role ainda funcionam?
Sim, hoje. O Supabase manteve as duas no ar durante a migração e você pode ter os dois pares ao mesmo tempo. O que foi anunciado é que no fim de 2026 todos os projetos vão precisar usar as chaves novas, sem uma data exata ainda.
Tenho os dois pares no painel. Qual o meu app deve usar?
A publicável, sb_publishable_. A troca é de uma linha: substitua a chave que o seu app passa quando cria o cliente do Supabase. Nada muda nas suas tabelas nem nas suas políticas, porque a chave nova tem exatamente as permissões que a anon tinha.
O formato novo deixa meu app mais seguro sozinho?
Não. Ele torna a chave perigosa fácil de reconhecer, e isso vale dinheiro em erros que deixam de acontecer, mas uma chave publicável continua lendo tudo o que as suas políticas deixarem. Se o Row Level Security estiver desligado, a chave nova abre o seu banco exatamente tanto quanto a antiga abria.
O que é uma chave publicável do Supabase?
É a chave que o seu app deve entregar: sb_publishable_ seguido de uma string aleatória, emitida pelo Supabase para identificar o seu projeto em cada pedido. Ela não carrega privilégios próprios, então o que consegue ler é exatamente o que as suas políticas de Row Level Security permitem e nada além. Ela substituiu a chave anon, faz o mesmo trabalho, e pode ficar em código que qualquer um lê.
O que são as chaves de API legadas do Supabase?
Legadas é como o Supabase chama hoje o par original, anon e service_role, junto com o segredo JWT que assina as duas. São JWTs em vez de strings opacas, carregam uma expiração dez anos depois da criação do projeto, e projetos restaurados depois de 1 de novembro de 2025 não recebem mais elas. Projetos existentes seguem com elas funcionando até a virada do fim de 2026.