Fundamentos de seguridad
Supabase "Email Rate Limit Exceeded": dos límites, un solo código
Supabase "Email Rate Limit Exceeded" limita cada email que envía tu proyecto: 2 por hora con el remitente integrado. Qué cuenta y cómo subirlo.

En resumen
- Supabase "Email Rate Limit Exceeded" significa que tu proyecto ya envió en esta hora todos los emails que tiene permitidos. Con el remitente integrado son 2 por hora, y cuenta cada confirmación de registro, cada magic link y cada restablecimiento de contraseña.
- El mismo código, over_email_send_rate_limit, también vuelve como "For security purposes, you can only request this after N seconds", una espera de 60 segundos para una sola dirección. Solo el mensaje distingue uno de otro.
- Tu propio proveedor SMTP quita el tope por hora una vez que también subes el límite en la página Rate Limits, que lo empieza en 30 por hora. La espera de 60 segundos se queda, y tu formulario debería explicarla.
Estás probando tu formulario de registro antes de compartir la app. Te registras
con tu propia dirección, luego con tu+2@gmail.com, y luego una vez más para ver
si el email de confirmación se ve bien. Uno de esos intentos se detiene aquí:
AuthApiError: email rate limit exceeded
Supabase "Email Rate Limit Exceeded" significa que tu proyecto gastó su cupo de emails de la hora, así que Supabase Auth, la parte de Supabase que inicia la sesión de la gente, se negó a enviar otro. Con el servicio de email con el que arranca todo proyecto, ese cupo es de dos emails por hora para todo el proyecto.
Aquí está la parte que es fácil entender al revés: el código de error cubre dos
límites distintos. La propia lista de códigos de error de Auth de Supabase
describe over_email_send_rate_limit como "Too many emails have been sent to this
email address." Eso es cierto para uno de los dos. El mismo código también vuelve
cuando todo el proyecto se quedó sin cupo, sea quien sea el destinatario, así que
probar con otra dirección no cambia nada. Y el consejo habitual, "conecta tu
propio SMTP", es la mitad del arreglo, porque Supabase arranca un servidor de
email recién conectado en 30 emails por hora.
¿Qué significa "Email rate limit exceeded" en Supabase?
Que tu proyecto ya envió en esta hora todos los emails que Supabase Auth permite, y el siguiente fue rechazado.
Piensa en el cupo como una hoja de sellos. Supabase le da a cada proyecto un número fijo de sellos por hora, y cada email que envía Supabase Auth gasta uno, sea del tipo que sea y vaya para quien vaya:
- el enlace de confirmación después de que alguien se registra
- un magic link o un código de un solo uso para iniciar sesión
- un restablecimiento de contraseña
- una invitación que envías desde la página Users
- la confirmación cuando alguien cambia su dirección de email
Cuando la hoja se vacía, Supabase Auth responde con HTTP 429, que significa
"demasiadas solicitudes", el código over_email_send_rate_limit y el mensaje
email rate limit exceeded. Esas palabras salen
del propio código del servidor de Supabase Auth.
Con el remitente integrado, el servicio de email con el que arranca un proyecto nuevo, la hoja tiene dos sellos por hora. Es la cifra de la página de límites de Supabase cuando la leímos el 20 de octubre de 2026, y la guía de SMTP de Supabase dice que "can change without notice". A dos por hora, un registro y un restablecimiento de contraseña son todo el cupo de la hora.
Si nadie puede iniciar sesión, o toda la app está en blanco, lo que tienes es otra cosa, y ¿Supabase está caído o es tu app? es por donde empezar.
Dos límites comparten un código de error
El mensaje te dice qué límite alcanzaste. El código es el mismo para los dos:
| El mensaje | Qué limita | Qué cuenta | El valor por defecto |
|---|---|---|---|
email rate limit exceeded | Todo el proyecto | Cada email que envía Supabase Auth, por hora | 2 por hora con el remitente integrado, 30 cuando conectas el tuyo |
For security purposes, you can only request this after N seconds. | Una dirección | El mismo tipo de email, enviado otra vez a la misma dirección | Uno cada 60 segundos |
Los dos responden HTTP 429 con over_email_send_rate_limit. La
lista de códigos de error de Auth
de Supabase te pide identificar los errores por su código y "not string matching
on error messages". Eso está bien para el código de tu app, y aquí deja un hueco:
solo el mensaje dice qué límite alcanzaste. Así que lee el mensaje para entender
qué pasó, y deja que tu app reaccione al código.
Si tu app solo dice "algo salió mal", el mensaje exacto está en la respuesta a la
solicitud fallida, en la pestaña Red de las herramientas para desarrolladores de
tu navegador. Un código over_request_rate_limit es un tercer límite, sobre las
solicitudes desde una misma dirección IP, y la lista de Supabase dice que puede
señalar un fallo en tu app que envía demasiadas.
¿Por qué dice "you can only request this after 0 seconds"?
Porque quedaba menos de un segundo de espera. El límite por dirección permite un email de cada tipo a la misma dirección cada 60 segundos: una confirmación de registro, un restablecimiento de contraseña, un magic link o un código. Si lo pides antes, Supabase Auth calcula cuánto falta y lo pone en el mensaje.
Cuenta en segundos enteros y descarta el resto. La función del servidor de Auth
que escribe este mensaje
(errors.go)
divide el tiempo restante entre un segundo, así que 0,8 segundos se muestra como
0. Vuelve a intentarlo un momento después y pasa, siempre que al tope por hora
del proyecto le quede un sello.
Esta espera funciona como debe. Es lo que impide que un botón de reenviar, pulsado veinte veces, envíe veinte emails. Déjala en 60 segundos y deja que tu formulario la explique.
El tope por hora, y para quién es
El remitente integrado es para probar Supabase, y Supabase lo dice en su guía de SMTP. Ahí enumera para qué está pensado el servicio: "Exploring and getting started with Supabase Auth", "Setting up and testing email templates with the members of the project's team" y "Building toy projects, demos or any non-mission-critical application". También viene con "No SLA guarantee on message delivery or uptime".
La misma guía tiene una segunda regla, y es la que decide quién ve cada error. Mientras no conectes tu propio servidor de email, Supabase Auth "will refuse to deliver messages to addresses that are not part of the project's team". Un cliente que se registra con su propia dirección queda rechazado antes de que se cuente ningún sello, con otro mensaje:
Email address "customer@example.com" cannot be used as it is not authorized
Eso es HTTP 400 con el código email_address_not_authorized, y en el código del
servidor de Auth esta comprobación va antes que los dos límites. Si el registro
funciona cuando lo pruebas tú y falla para todos los demás, este es el motivo.
Así que, con el remitente integrado, email rate limit exceeded le toca sobre
todo a ti y a tu equipo, al probar. Cuando el servidor de Auth comprueba si una
dirección es de tu equipo, ignora todo lo que haya entre un + y la @. Por eso
tu+test1@gmail.com y tu+test2@gmail.com cuentan los dos como tú, y cada
registro de prueba gasta uno de los mismos dos sellos.
¿Cómo subo el límite de emails de Supabase?
Conecta tu propio proveedor de email y luego sube el límite que Supabase le pone. Son dos pasos separados, y el segundo es el que se olvida.
- Elige un servicio de envío y consigue sus datos SMTP. La guía de Supabase
nombra Resend, AWS SES, Postmark, Twilio SendGrid, ZeptoMail y Brevo, y dice
que cualquier servicio que admita SMTP funcionará. Necesitas el host, el
puerto, un usuario y una contraseña, además de una dirección de remitente como
no-reply@tudominio.com. - Activa el SMTP personalizado en los ajustes de Authentication de tu proyecto y escribe esos datos. Desde entonces Supabase envía a cualquier dirección.
- Sube el límite de emails en la página Rate Limits, también dentro de Authentication. La guía dice que un servidor recién conectado recibe "a low rate-limit of 30 messages per hour" para proteger su reputación, y que se cambia ahí. Ponlo en lo que tu proveedor permita y en lo que necesite tu hora de más movimiento.
Otras tres cosas de la misma guía van con este cambio:
- Configura DKIM, DMARC y SPF para tu dominio de envío, con tu proveedor. Supabase dice que esto "will significantly increase the deliverability of your messages".
- Activa CAPTCHA en los registros. La guía señala a los bots que registran listas de direcciones como "a common source of abuse", y cada uno de esos registros es un email sacado de tu hora. Llama a CAPTCHA "the most effective way" de frenarlos.
- Comprueba que no se esté cerrando la sesión de tus usuarios. Según la guía, las sesiones cortas obligan a "active users to sign in frequently, increasing the number of messages", y si tus usuarios entran con un enlace por email, cada cierre de sesión inesperado cuesta un sello. Por qué Supabase cierra la sesión de tus usuarios explica las causas.
Para los otros límites con los que se topa un proyecto gratuito, mira qué incluye el plan gratuito de Supabase.
Manejar el error en tu formulario de registro
Atrápalo por su código y dile a la persona qué hacer, con palabras claras. El
cliente de JavaScript de Supabase pone el código del servidor en el error que
devuelve, como error.code, así que la comprobación es una línea:
const { error } = await supabase.auth.signUp({ email, password })
if (error?.code === 'over_email_send_rate_limit') {
// mostrar: "No pudimos enviar tu email ahora mismo. Vuelve a intentarlo en un minuto."
}
Pídele a tu herramienta, sea Lovable, Bolt, v0, Cursor, Claude Code o Replit, tres cosas:
- la misma comprobación en cada formulario que envía un email: registro, "olvidé mi contraseña", inicio de sesión con enlace por email y "reenviar"
- un mensaje que pida a la persona volver a intentarlo en un rato, en lugar del error en bruto o de un formulario que no hace nada sin avisar
- el botón de reenviar desactivado 60 segundos después de cada envío, para que nadie pueda pulsarlo dentro de la espera por dirección
No pongas reintentos automáticos. Mientras la hoja esté vacía, cada reintento se
rechaza, y las solicitudes de registro además están limitadas por dirección IP, a
30 cada 5 minutos por defecto. Un bucle de reintentos también puede activar ese
límite, que responde con over_request_rate_limit.
Qué no cambiar mientras los registros están atascados
La confirmación por email, y desde dónde salen los emails. Hay dos atajos que hacen desaparecer el error y te dejan peor.
Deja activada la confirmación por email. Si desactivas "Confirm email", los registros dejan de enviar nada y el error se va. La guía de SMTP de Supabase incluye "Do not disable email confirmations under pressure" entre sus defensas, porque sin confirmación alguien puede crear una cuenta a nombre de otra persona.
Mantén los emails fuera del navegador. Pídele a un asistente que "envíe la confirmación con Resend y ya" y puede meter la clave de API del proveedor en el código frontend de tu app, donde cualquier visitante puede leerla y enviar correos en tu nombre. Envía los emails con los ajustes SMTP de Supabase o con una función del lado del servidor, nunca con una clave en la página. Si no estás seguro de que no se coló ninguna, nuestro escaneo gratuito lee el código que tu app en vivo envía a cada visitante y marca las claves secretas que encuentra ahí. Tarda unos 20 segundos y no pide cuenta: escanea tu app.
Vigilar la app mientras cambias cómo envía los emails
Dos cosas pueden salir mal mientras rehaces el envío de emails: una clave acaba en el código de tu app, y un mensaje que dice "nadie puede registrarse" te manda a buscar una caída.
Reeve Monitor sigue comprobando desde fuera:
- si tu app responde, comprobado cada minuto, para saber enseguida si una queja sobre el registro es una caída o algo más acotado
- la comprobación de seguridad completa cada hora, en hasta tres apps, incluidas las claves secretas en el código que tu app envía a los visitantes
- un mensaje cuando un resultado cambia, para que una clave que sale con un despliegue posterior te llegue sin que tengas que ir a mirar
- un informe mensual, en lenguaje claro, de lo que vio
Reeve Care guarda una copia de tu base de datos de Supabase:
- una copia cifrada según un calendario, en el almacenamiento propio de Reeve en la UE, fuera de tu cuenta de Supabase
- el esquema auth, donde vive cada cuenta que sí logró registrarse
- cada copia verificada antes de contar, contando las filas de cada tabla
- también tus archivos subidos, en cuanto conectas una credencial de Storage
- una restauración con un clic, con una copia de seguridad del estado actual tomada antes
- todo lo que hace Monitor
Qué hacer ahora
Qué hacer
- Lee el mensaje además del código:
email rate limit exceededes el tope por hora del proyecto, yFor security purposes…es la espera de 60 segundos para una dirección. - Si tus clientes ven
Email address … cannot be used as it is not authorized, tu proyecto sigue con el remitente integrado de Supabase, que solo escribe a tu equipo. - Conecta tu propio proveedor SMTP y luego sube el límite de emails en la página Rate Limits, que empieza en 30 por hora.
- Configura DKIM, DMARC y SPF con tu proveedor, y activa CAPTCHA en los registros.
- Haz que cada formulario que envía un email compruebe
over_email_send_rate_limit, muestre un mensaje claro y bloquee el botón de reenviar 60 segundos. - Deja activada la confirmación por email, y nunca pongas la clave de un proveedor de email en tu frontend.
Empieza por el mensaje de la respuesta fallida, porque te dice cuál de los dos límites alcanzaste. Luego, cuando los emails ya salgan por tu propio proveedor, escanea tu app para comprobar que no se coló ninguna clave por el camino.
Preguntas frecuentes
¿Qué significa "email rate limit exceeded" en Supabase?
Que tu proyecto ya envió en esta hora todos los emails que Supabase Auth permite, así que el siguiente fue rechazado. La cuenta incluye cada email que envía Auth, a quien sea: confirmaciones de registro, magic links, restablecimientos de contraseña e invitaciones. Con el remitente integrado son 2 por hora. Con tu propio proveedor SMTP el número lo pones tú.
¿Por qué dice que solo puedo volver a pedirlo después de 0 segundos?
Porque quedaba menos de un segundo de la espera de 60. Supabase Auth cuenta el tiempo restante en segundos enteros y descarta el resto, así que el último segundo se muestra como 0. Vuelve a intentarlo un momento después y el email sale, siempre que el tope por hora todavía tenga sitio.
¿Cuántos emails puede enviar Supabase por mí?
Con el remitente integrado, 2 por hora para todo el proyecto, y solo a personas de tu equipo de Supabase. Supabase dice que esa cifra puede cambiar sin aviso. Con tu propio proveedor SMTP no hay una cifra fija: Supabase empieza en 30 por hora y tú la subes en la página Rate Limits.
¿Necesito mi propio proveedor SMTP?
Sí, en cuanto alguien de fuera de tu equipo se registre por email. El remitente integrado rechaza las direcciones que no están en tu equipo, y Supabase lo describe como pensado para probar, para ensayar plantillas y para demos. Resend, AWS SES, Postmark, SendGrid, ZeptoMail y Brevo están entre los servicios que Supabase menciona como compatibles.
¿Cómo evito que esto rompa mi formulario de registro?
Revisa el código del error antes de que nada llegue a la pantalla. Si es over_email_send_rate_limit, muestra un mensaje claro que pida volver a intentarlo en un minuto, y deja el botón de reenviar desactivado 60 segundos después de cada envío, para que nadie pueda pulsarlo dentro de la espera.
¿Por qué mis clientes reciben "Email address not authorized"?
Porque tu proyecto todavía envía con el remitente integrado de Supabase, que solo entrega a miembros de tu organización de Supabase. A todos los demás los rechaza con el código email_address_not_authorized. Conectar tu propio proveedor SMTP lo arregla, y es el mismo cambio que quita el tope por hora.