Pular para o conteúdo

Noções de segurança

Supabase "Email Rate Limit Exceeded": dois limites, um só código

Supabase "Email Rate Limit Exceeded" limita cada email que seu projeto envia: 2 por hora no remetente embutido. O que conta e como aumentar.

Vlad Tkachenko11 min de leitura
Uma folha de selos da qual todos os selos já foram arrancados, ao lado de uma pilha de envelopes fechados sem nada no canto.

Em resumo

  • Supabase "Email Rate Limit Exceeded" significa que seu projeto já enviou nesta hora todos os emails a que tem direito. No remetente embutido são 2 por hora, e conta cada confirmação de cadastro, cada magic link e cada redefinição de senha.
  • O mesmo código, over_email_send_rate_limit, também volta como "For security purposes, you can only request this after N seconds", uma espera de 60 segundos para um único endereço. Só a mensagem diferencia os dois.
  • Seu próprio provedor SMTP tira o teto por hora quando você também aumenta o limite na página Rate Limits, que começa em 30 por hora. A espera de 60 segundos continua, e o seu formulário deve explicá-la.

Você está testando o formulário de cadastro antes de divulgar o app. Você se cadastra com seu próprio endereço, depois com voce+2@gmail.com, e depois mais uma vez para ver se o email de confirmação está bonito. Uma dessas tentativas para nisto:

AuthApiError: email rate limit exceeded

Supabase "Email Rate Limit Exceeded" significa que seu projeto gastou a cota de emails da hora, então o Supabase Auth, a parte do Supabase que faz o login das pessoas, se recusou a enviar mais um. No serviço de email com que todo projeto começa, essa cota é de dois emails por hora para o projeto inteiro.

Esta é a parte fácil de entender ao contrário: o código de erro cobre dois limites diferentes. A própria lista de códigos de erro do Auth do Supabase descreve over_email_send_rate_limit como "Too many emails have been sent to this email address." Isso vale para um dos dois. O mesmo código também volta quando o projeto inteiro ficou sem cota, seja quem for o destinatário, então tentar outro endereço não muda nada. E o conselho de sempre, "conecte seu próprio SMTP", é metade da solução, porque o Supabase começa um servidor de email recém-conectado em 30 emails por hora.

O que significa "Email rate limit exceeded" no Supabase?

Que seu projeto já enviou nesta hora todos os emails que o Supabase Auth permite, e o próximo foi recusado.

Pense na cota como uma folha de selos. O Supabase dá a cada projeto um número fixo de selos por hora, e cada email que o Supabase Auth envia gasta um, seja de que tipo for e seja para quem for:

  • o link de confirmação depois que alguém se cadastra
  • um magic link ou um código de uso único para entrar
  • uma redefinição de senha
  • um convite que você envia pela página Users
  • a confirmação quando alguém troca o endereço de email

Quando a folha acaba, o Supabase Auth responde com HTTP 429, que significa "requisições demais", o código over_email_send_rate_limit e a mensagem email rate limit exceeded. Essas palavras vêm do próprio código do servidor do Supabase Auth.

No remetente embutido, o serviço de email com que um projeto novo começa, a folha tem dois selos por hora. É o número da página de limites do Supabase quando a lemos em 20 de outubro de 2026, e o guia de SMTP do Supabase diz que ele "can change without notice". A dois por hora, um cadastro e uma redefinição de senha são a cota inteira da hora.

Cada email que o Supabase Auth envia gasta um selo da mesma folha. No remetente embutido, a folha tem dois por hora.

Se ninguém consegue entrar, ou o app inteiro está em branco, o problema é outro, e o Supabase caiu ou é o seu app? é por onde começar.

Dois limites dividem um código de erro

A mensagem diz qual limite você atingiu. O código é o mesmo para os dois:

A mensagemO que limitaO que contaO padrão
email rate limit exceededO projeto inteiroCada email que o Supabase Auth envia, por hora2 por hora no remetente embutido, 30 quando você conecta o seu
For security purposes, you can only request this after N seconds.Um endereçoO mesmo tipo de email, enviado de novo ao mesmo endereçoUm a cada 60 segundos

Os dois respondem HTTP 429 com over_email_send_rate_limit. A lista de códigos de erro do Auth do Supabase pede que você identifique os erros pelo código e "not string matching on error messages". Isso está certo para o código do seu app, e aqui deixa uma lacuna: só a mensagem diz qual limite você atingiu. Então leia a mensagem para entender o que aconteceu, e deixe o seu app reagir ao código.

Se o seu app só diz "algo deu errado", a mensagem exata está na resposta à requisição que falhou, na aba Rede das ferramentas de desenvolvedor do seu navegador. Um código over_request_rate_limit é um terceiro limite, sobre requisições vindas de um mesmo endereço IP, e a lista do Supabase diz que ele pode apontar para um bug no seu app que envia requisições demais.

Uma folha vazia e uma espera de 60 segundos são recusas diferentes, e o Supabase informa as duas com o mesmo código.

Por que diz "you can only request this after 0 seconds"?

Porque faltava menos de um segundo de espera. O limite por endereço permite um email de cada tipo para o mesmo endereço a cada 60 segundos: uma confirmação de cadastro, uma redefinição de senha, um magic link ou código. Peça de novo antes e o Supabase Auth calcula quanto falta e coloca isso na mensagem.

Ele conta em segundos inteiros e descarta o resto. A função do servidor do Auth que escreve essa mensagem (errors.go) divide o tempo restante por um segundo, então 0,8 segundo aparece como 0. Tente de novo um instante depois e passa, desde que o teto por hora do projeto ainda tenha um selo.

Essa espera está fazendo o que deve. É ela que impede um botão de reenviar, apertado vinte vezes, de mandar vinte emails. Deixe em 60 segundos e deixe o seu formulário explicá-la.

O teto por hora, e para quem ele é

O remetente embutido serve para experimentar o Supabase, e o Supabase diz isso no seu guia de SMTP. O guia lista para que o serviço é pensado: "Exploring and getting started with Supabase Auth", "Setting up and testing email templates with the members of the project's team" e "Building toy projects, demos or any non-mission-critical application". Ele também vem com "No SLA guarantee on message delivery or uptime".

O mesmo guia tem uma segunda regra, e é ela que decide quem vê cada erro. Enquanto você não conecta seu próprio servidor de email, o Supabase Auth "will refuse to deliver messages to addresses that are not part of the project's team". Um cliente que se cadastra com o próprio endereço é recusado antes de qualquer selo ser contado, com outra mensagem:

Email address "customer@example.com" cannot be used as it is not authorized

Isso é HTTP 400 com o código email_address_not_authorized, e no código do servidor do Auth essa verificação vem antes dos dois limites. Se o cadastro funciona quando você testa e falha para todo mundo, é por isso.

Então, no remetente embutido, email rate limit exceeded cai principalmente em você e na sua equipe, testando. Quando o servidor do Auth verifica se um endereço é da sua equipe, ele ignora tudo o que estiver entre um + e o @. Assim voce+teste1@gmail.com e voce+teste2@gmail.com contam os dois como você, e cada cadastro de teste gasta um dos mesmos dois selos.

Como aumento o limite de emails do Supabase?

Conecte seu próprio provedor de email e depois aumente o limite que o Supabase coloca nele. São dois passos separados, e o segundo é o que as pessoas esquecem.

  1. Escolha um serviço de envio e pegue os dados SMTP dele. O guia do Supabase cita Resend, AWS SES, Postmark, Twilio SendGrid, ZeptoMail e Brevo, e diz que qualquer serviço que suporte SMTP funciona. Você precisa do host, da porta, de um usuário e de uma senha, mais um endereço de remetente como no-reply@seudominio.com.br.
  2. Ative o SMTP personalizado nas configurações de Authentication do seu projeto e preencha esses dados. A partir daí o Supabase envia para qualquer endereço.
  3. Aumente o limite de emails na página Rate Limits, também em Authentication. O guia diz que um servidor recém-conectado recebe "a low rate-limit of 30 messages per hour" para proteger a reputação dele, e que é ali que você muda. Coloque o que o seu provedor permite e o que a sua hora mais movimentada precisa.

Mais três coisas do mesmo guia combinam com essa mudança:

  • Configure DKIM, DMARC e SPF para o seu domínio de envio, no seu provedor. O Supabase diz que isso "will significantly increase the deliverability of your messages".
  • Ative CAPTCHA nos cadastros. O guia aponta bots que cadastram listas de endereços como "a common source of abuse", e cada um desses cadastros é um email tirado da sua hora. Ele chama o CAPTCHA de "the most effective way" de barrá-los.
  • Confira se os seus usuários não estão sendo desconectados. Segundo o guia, sessões curtas forçam "active users to sign in frequently, increasing the number of messages", e se os seus usuários entram por link de email, cada desconexão inesperada custa um selo. Por que os usuários do Supabase são desconectados explica as causas.

Para os outros limites que um projeto gratuito encontra, veja o que o plano gratuito do Supabase inclui.

Tratando o erro no seu formulário de cadastro

Pegue o erro pelo código e diga à pessoa o que fazer, em palavras simples. O cliente JavaScript do Supabase coloca o código do servidor no erro que devolve, como error.code, então a verificação é uma linha:

const { error } = await supabase.auth.signUp({ email, password })

if (error?.code === 'over_email_send_rate_limit') {
  // mostrar: "Não conseguimos enviar seu email agora. Tente de novo em um minuto."
}

Peça à sua ferramenta, seja Lovable, Bolt, v0, Cursor, Claude Code ou Replit, três coisas:

  • a mesma verificação em todo formulário que envia email: cadastro, "esqueci a senha", login por link de email e "reenviar"
  • uma mensagem que peça à pessoa para tentar de novo daqui a pouco, no lugar do erro cru ou de um formulário que não faz nada sem avisar
  • o botão de reenviar desativado por 60 segundos depois de cada envio, para ninguém conseguir apertá-lo dentro da espera por endereço

Não coloque novas tentativas automáticas. Enquanto a folha estiver vazia, cada tentativa é recusada, e as requisições de cadastro também são limitadas por endereço IP, a 30 a cada 5 minutos por padrão. Um loop de tentativas pode disparar esse limite também, e ele responde com over_request_rate_limit.

O que não mudar enquanto os cadastros estão travados

A confirmação por email, e de onde os emails saem. Dois atalhos fazem o erro sumir e deixam você numa situação pior.

Deixe a confirmação por email ligada. Desligar "Confirm email" faz os cadastros pararem de enviar qualquer coisa, então o erro some. O guia de SMTP do Supabase lista "Do not disable email confirmations under pressure" entre as suas defesas, porque sem confirmação alguém pode criar uma conta no nome de outra pessoa.

Mantenha os emails fora do navegador. Peça a um assistente para "só mandar a confirmação com o Resend" e ele pode colocar a chave de API do provedor no código frontend do seu app, onde qualquer visitante consegue ler e mandar emails em seu nome. Envie os emails pelas configurações SMTP do Supabase ou por uma função no servidor, nunca com uma chave na página. Se você não tem certeza de que nenhuma escapou, nosso scan gratuito lê o código que o seu app no ar envia para cada visitante e aponta as chaves secretas que encontra ali. Leva uns 20 segundos e não pede conta: escaneie seu app.

De olho no app enquanto você muda o envio de emails

Duas coisas podem dar errado enquanto você refaz o envio de emails: uma chave vai parar no código do seu app, e uma mensagem dizendo "ninguém consegue se cadastrar" manda você atrás de uma queda.

O Reeve Monitor continua verificando de fora:

  • se o seu app está no ar, verificado a cada minuto, para você saber na hora se uma reclamação sobre o cadastro é uma queda ou algo mais restrito
  • a verificação de segurança completa a cada hora, em até três apps, incluindo chaves secretas no código que o seu app envia aos visitantes
  • uma mensagem quando um resultado muda, para que uma chave que sai num deploy posterior chegue até você sem você precisar ir olhar
  • um relatório mensal, em linguagem clara, do que ele viu

O Reeve Care guarda uma cópia do seu banco de dados Supabase:

  • uma cópia criptografada num cronograma, no armazenamento próprio da Reeve na UE, fora da sua conta do Supabase
  • o schema auth, onde fica cada conta que conseguiu se cadastrar
  • cada cópia verificada antes de contar, contando as linhas de cada tabela
  • os seus arquivos enviados também, assim que você conecta uma credencial do Storage
  • uma restauração com um clique, com uma cópia de segurança do estado atual feita antes
  • tudo o que o Monitor faz

O que fazer agora

O que fazer

  • Leia a mensagem além do código: email rate limit exceeded é o teto por hora do projeto, e For security purposes… é a espera de 60 segundos para um endereço.
  • Se clientes veem Email address … cannot be used as it is not authorized, seu projeto ainda está no remetente embutido do Supabase, que só escreve para a sua equipe.
  • Conecte seu próprio provedor SMTP e depois aumente o limite de emails na página Rate Limits, que começa em 30 por hora.
  • Configure DKIM, DMARC e SPF no seu provedor, e ative CAPTCHA nos cadastros.
  • Faça todo formulário que envia email checar over_email_send_rate_limit, mostrar uma mensagem clara e travar o botão de reenviar por 60 segundos.
  • Deixe a confirmação por email ligada, e nunca coloque a chave de um provedor de email no seu frontend.

Comece pela mensagem na resposta que falhou, porque ela diz qual dos dois limites você atingiu. Depois, quando os emails já estiverem saindo pelo seu próprio provedor, escaneie seu app para conferir que nenhuma chave veio junto.

Perguntas frequentes

O que significa "email rate limit exceeded" no Supabase?

Que seu projeto já enviou nesta hora todos os emails que o Supabase Auth permite, então o próximo foi recusado. A conta inclui cada email que o Auth envia, para quem quer que seja: confirmações de cadastro, magic links, redefinições de senha e convites. No remetente embutido são 2 por hora. Com seu próprio provedor SMTP, quem define o número é você.

Por que diz que só posso pedir de novo depois de 0 segundos?

Porque faltava menos de um segundo da espera de 60. O Supabase Auth conta o tempo restante em segundos inteiros e descarta o resto, então o último segundo aparece como 0. Tente de novo um instante depois e o email sai, desde que o teto por hora ainda tenha espaço.

Quantos emails o Supabase pode enviar por mim?

No remetente embutido, 2 por hora para o projeto inteiro, e só para pessoas da sua equipe no Supabase. O Supabase diz que esse número pode mudar sem aviso. Com seu próprio provedor SMTP não há número fixo: o Supabase começa em 30 por hora e você aumenta na página Rate Limits.

Preciso do meu próprio provedor SMTP?

Sim, assim que alguém de fora da sua equipe se cadastrar por email. O remetente embutido recusa endereços que não estão na sua equipe, e o Supabase o descreve como feito para experimentar, testar templates e fazer demos. Resend, AWS SES, Postmark, SendGrid, ZeptoMail e Brevo estão entre os serviços que o Supabase cita como compatíveis.

Como evito que isso quebre meu formulário de cadastro?

Confira o código do erro antes que qualquer coisa chegue à tela. Se for over_email_send_rate_limit, mostre uma mensagem clara pedindo para tentar de novo em um minuto, e mantenha o botão de reenviar desativado por 60 segundos depois de cada envio, para ninguém conseguir apertá-lo dentro da espera.

Por que meus clientes recebem "Email address not authorized"?

Porque seu projeto ainda envia pelo remetente embutido do Supabase, que só entrega para membros da sua organização no Supabase. Todos os outros são recusados com o código email_address_not_authorized. Conectar seu próprio provedor SMTP resolve, e é a mesma mudança que tira o teto por hora.

Escrito por

Vlad Tkachenko

Fundador da Reeve

Passo meus dias olhando apps criados com Lovable, Bolt, v0, Cursor e Replit, e a curta lista de erros que aparecem neles sem parar.

Mais sobre o autor

Leia depois

Todos os artigos

Faça backup do seu banco Supabase antes da próxima mudança

O Reeve guarda uma cópia criptografada em horários programados e a restaura para você se algo quebrar.

Ver backups do Supabase

Verificação externa automatizada, não uma auditoria completa. A ausência de achados não é garantia de segurança.