Supabase’s email rate limit exceeded message covers two documented limits: a project-wide cap of 2 emails per hour on the built-in provider and 60-second windows per user on resends. Both return HTTP 429. Only the project-wide cap is changed by custom SMTP.

That is why the advice circulating on this error works for some people and not others. The most-shared write-ups give one number and one fix, and the number they give is 3 emails per hour, which Supabase’s own documentation contradicts. The diagnostic page that ranked highest on the query gives no number at all and recommends exponential backoff, which cannot rescue a ceiling of two an hour.

The numbers below come from Supabase’s own auth documentation, which I opened and checked on 17 August 2026. Those pages carry no last-updated date of their own, so the date here marks when I looked, not when Supabase last changed anything.

”Supabase email rate limit exceeded”: which limit actually fired

Two documented limits, two different fixes, plus one restriction that is not a rate limit at all. Supabase returns 429 Too Many Requests when any auth rate limit is exceeded, so the status code alone tells you nothing about which one fired. The symptom and recent request history narrow it down.

SymptomLikely causeFirst check
Signup or a magic link fails for an address outside your team, on a project that has sent almost nothingThe built-in service refuses addresses that are not on the project’s team; whether the refused request also counts against the hourly cap is not documentedOpen the Authentication settings page and see whether custom SMTP is enabled
The third email in an hour fails, across different usersThe project-wide cap of 2 emails per hour on the built-in providerSame check. This one counts the whole project, not one user
The error includes over_email_send_rate_limitThe label describes the failed email send, but does not establish a separate recipient counterCheck the documented project-wide and per-user limits. Do not assume another address bypasses the active limit
A user taps “resend” twice and the second tap failsThe 60-second window per user on signup confirmation, password reset, and OTP or magic-link resendAuthentication > Rate Limits shows the configured windows
The account is created fine and the first write is refused insteadA different Supabase error entirelyRead the message. If the database refused the row rather than the mail, that is the other error every new Supabase app hits right after signup, and it needs a database fix, not an email one

Everything in that last column happens in the browser. The status code and the counting rules behind it are set out on Supabase’s rate-limits page, which is also where most of the figures below come from. Before changing a line of config or code, three dashboard pages settle most of it:

  1. 01 Authentication settings: is custom SMTP on, or is the project still on Supabase's built-in service?
  2. 02 The Team tab of the organization's settings: the addresses the built-in service will actually deliver to.
  3. 03 Authentication > Rate Limits: what the configurable windows are currently set to.

If requests are not failing but crawling, that is a different question: whether Supabase is throttling you or something in your own app is slow. This page is only about the refusal.

Every Supabase Auth rate limit, and which ones send email

Supabase publishes the full table. The column it does not have is the one that matters when an email did not arrive, so the last column below is mine.

OperationPathLimited byDefault limitCustomizableSends email
Endpoints that trigger email sends/auth/v1/signup, /auth/v1/recover, /auth/v1/userSum of combined requests project-wide2 emails per hour on the built-in providerCustom SMTP OnlyYes
Send One-Time-Passwords (OTP)/auth/v1/otpSum of combined requests project-wide30 OTPs per hourYesYes
Send OTPs or magic links/auth/v1/otpLast request of the user60 seconds before a new requestYesYes
Signup confirmation request/auth/v1/signupLast request of the user60 seconds before a new requestYesYes
Password reset request/auth/v1/recoverLast request of the user60 seconds before a new requestYesYes
Verification requests/auth/v1/verifyIP address360 requests per hourNoNo
Token refresh requests/auth/v1/tokenIP address1800 requests per hourNoNo
Create or verify an MFA challenge/auth/v1/factors/:id/challenge, /auth/v1/factors/:id/verifyIP address15 requests per hourNoNo
Anonymous sign-ins/auth/v1/signupIP address30 requests per hour, and only when the endpoint is called without an email or phone number in the request bodyNoNo

Read the “limited by” column before anything else. Three different counting rules are stacked in one table: some limits count the whole project, some count one user’s last request, and some count an IP address. A limit that counts the project cannot be dodged by asking the user to try a different address, and a limit that counts one user cannot be the reason a second user is blocked.

The IP-limited rows behave differently again. Supabase describes those as a token bucket with a capacity of 30 requests, which is where the burst allowances in its own table come from: an idle client tolerates a short spike, then sustained traffic above the refill rate is denied.

Two other project-wide ceilings sit next to these and get confused with them, because both also produce a sudden stop on a project that was working yesterday: the ceiling on how many database sessions a project can hold open at once, and what is actually eating your Supabase egress. Neither has anything to do with mail delivery.

Limit 1: the built-in email service sends 2 an hour, for the whole project

Supabase’s rate-limits table gives the figure without hedging. On the row for the three endpoints that trigger email sends, the limit reads:

2 emails per hour with the built-in email provider. You can only change this with a custom SMTP setup. …

Two things in that row do the damage. The first is what it counts. The “limited by” cell reads “Sum of combined requests project-wide”, so this is not two emails per user. One developer testing signup with three throwaway addresses has spent the project’s hour for every real visitor as well.

The second is the word “requests”. The counter sits on requests to /auth/v1/signup, /auth/v1/recover and /auth/v1/user, not on messages that were successfully delivered. Supabase does not document whether a request that fails for some other reason is excluded from the count, so I will not claim it is. What the documentation does say is that the ceiling is measured on the endpoints, which is enough to explain the reports below from projects that believed they had sent nothing.

The custom SMTP guide states the same number from the other side, describing the default sending service’s limits as significant, subject to change without notice, and “Currently this value is set to 2 messages per hour.”

The number circulating in the top editorial results is 3. A widely shared September 2024 walkthrough at dev.to/devyoma/bypassing-supabases-email-rate-limits-in-user-registration-a-practical-guide-217o opens on the line that you can only send 3 emails per hour on user registration, and the same figure appears in the community threads above it. It goes unlinked here for that reason: it carries a number Supabase’s own documentation contradicts, and it recommends routing auth mail through a personal Gmail account without mentioning Gmail’s own sending caps.

The other message: the built-in service will not email anyone outside your project team

This is the failure nobody on the first page of results names, and it is the one that makes the error look impossible. Supabase’s custom SMTP guide lists it first among the restrictions on the default service:

Send messages only to pre-authorized addresses.

The guide is specific about what “pre-authorized” means: unless custom SMTP is configured, Supabase Auth refuses to deliver to any address that is not part of the project’s team, managed in the Team tab of the organization’s settings. If the organization has three member accounts, those three addresses are the only ones the default service will mail. The guide states that all other addresses fail with the error message Email address not authorized.

So there are two distinct failures here and it is worth separating them, because the fix is the same but the diagnosis is not. An address outside the team gets the not-authorized message. The rate-limit message is what you get once the hourly ceiling is reached. Supabase documents a project-wide request counter, but it does not say whether a request rejected as not authorized consumes that counter.

That combination is what produces the reports that read like a bug. A March 2025 issue on Supabase’s repository was opened by someone getting a 429 on the Free plan while, by their own reading of their auth logs, sending nothing. The thread never resolved the hosted case. It did resolve a different one: several people arriving on the same error were running locally through the CLI, and a Supabase contributor traced those to a CLI bug that was fixed in a later release. The issue is now closed with the hosted report still unexplained on the page, so treat it as a symptom record, not a documented cause.

Supabase is direct about what the built-in service is for. The guide calls it best-effort with no delivery or uptime guarantee, and names three intended uses: exploring and getting started with Supabase Auth, setting up and testing email templates with the members of the project’s team, and building toy projects, demos, or any non-mission-critical application. Nothing in that list is “the signup flow of an app with real users”.

The default SMTP service is provided as best-effort only…

What over_email_send_rate_limit does and does not tell you

Supabase’s error-codes reference gives the code you can see in the error object. Its description tells the user to wait:

Too many emails have been sent to this email address. Ask the user to wait a while before trying again.

That description does not publish a separate recipient counter or a threshold for one. The rate-limits page documents the project-wide email counter and the 60-second per-user windows. The error label alone does not prove that a different address is unaffected.

Reading the code is the falsifiable check, and it takes one line. The reference states that server errors classed as AuthApiError always carry a code property identifying the error:

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

if (error?.code === 'over_email_send_rate_limit') {
  // Inspect the project-wide and per-user limits before retrying.
  // Do not assume another address bypasses the active counter.
}

A comment on that March 2025 issue, posted in May 2026, shows the whole shape arriving at once from a client library: AuthApiException: email rate limit exceeded (429, over_email_send_rate_limit). It confirms the error surface, not a separate recipient counter.

Limit 2: the 60-second window per user, which custom SMTP does not touch

The second documented limit is the smallest one and it catches the most people. Signup confirmation, password reset, and OTP or magic-link resend each default to 60 seconds before the same user may request again. It counts one user’s last request and nothing else, so a second user is never affected by it.

A user who taps “resend” twice, or a React effect that fires the request on a re-render, hits that window and gets the same family of error. Nothing about custom SMTP changes it, because it is configured separately at Authentication > Rate Limits.

Does upgrading raise the Supabase email rate limit?

No. The built-in email provider sets that limit and the plan tier never enters into it. Supabase’s rate-limits table conditions the 2-an-hour row on the provider and names custom SMTP as the only way to change it. Paying more, then waiting, moves nothing.

The place to watch somebody find this out is an April 2025 thread in Supabase’s own GitHub discussions, titled around still getting the error after upgrading to the Pro plan. The reply marked as the thread’s answer, from GaryAustin1, says in substance what the documentation says: there is no difference between Pro and Free on the built-in provider’s email limit, and the way forward is your own SMTP provider with the limit raised in the dashboard’s rate-limit settings under Authentication.

Both statements point the same direction, one from the primary side and one from the community side, and they agree. If you want the separate question of what the Supabase plans actually cost and what upgrading does and does not buy, that is a pricing question and it belongs on a pricing page. It does not belong in this diagnosis, because the answer here does not depend on it.

The fix: custom SMTP, and the number it actually sets

Custom SMTP is the documented fix for the project-wide cap, and it is a dashboard job, not a code change. Supabase’s guide says its Auth works with any email sending service that supports the SMTP protocol, and the fields it asks for are the ordinary ones: host, port, user, password, and a default From address such as no-reply@example.com. The guide names several services that work, and I am not recommending one over another here; deliverability, pricing, and domain verification differ enough that the choice is yours to make.

Configuration lives on the Authentication settings page, on its SMTP section. Once the settings are saved, the guide states that the project’s Auth server will send messages to all addresses, which is the pre-authorized-address restriction being lifted.

Then comes the part most walkthroughs leave out. The new ceiling is not “unlimited”:

To protect the reputation of your newly set up service a low rate-limit of 30 messages per hour is imposed.

Thirty an hour is fifteen times the built-in figure and still low for a real signup flow on a busy day. The guide says to adjust it to an acceptable value for your use case on the Rate Limits configuration page, which is the same Authentication > Rate Limits screen from the checks at the top of this page.

Two honest caveats. Custom SMTP moves the project-wide ceiling and removes the pre-authorized-address restriction. It does not remove the 60-second per-user windows, because those are configured separately. And the rate limit protecting a brand-new sending domain exists for a reason: Supabase’s guide devotes a whole section to bots signing up users in bulk to damage a sender’s reputation, and recommends CAPTCHA protection as the most effective control.

What does not fix “email rate limit exceeded” in Supabase

Five things people try, in roughly the order they try them.

Waiting for a reset. There is no documented reset button and no documented button for clearing the counter. The window elapses; that is the whole mechanism. For the project-wide cap that is an hour, for the per-user windows it is 60 seconds by default. Anyone who tells you there is a “reset email rate limit” control in the dashboard should be asked to name the page it lives on.

Trying a different email address. This does not diagnose the active limit. The documented project-wide counter follows the project, while the 60-second windows follow the user’s last request. The error label does not prove that a fresh address is unaffected.

Creating a fresh project. It works, which is exactly why it is misleading. A new project has a fresh hourly counter, so the first two emails go through and the original project looks flagged or broken. It was not. You have moved the problem forward by an hour and split your data across two projects.

Exponential backoff. This is the advice on a diagnostic page that ranked in the top ten when checked on 16 August 2026, published by DrDroid, which sells an automated debugging product. Backoff is the right tool against a burst limit that refills quickly. Against a ceiling of two messages an hour it just spaces out the failures. Retry logic cannot manufacture quota.

Turning off email confirmation. This is the fix that circulates most and it is a trade, not a repair. Signups stop failing because signups stop sending mail, and you are left with accounts nobody proved they own, on an app where a password reset is now the only path to an address you never verified. Supabase’s own abuse section lists forcing a project to disable email confirmations as an attacker goal, and advises against doing it under pressure. If you are weighing it anyway, weigh it as what turning email confirmation off actually leaves open, not as a rate-limit setting.

Which Supabase emails this throttles

The limit covers the messages Supabase Auth sends on your behalf, which is most of what a user sees before they are logged in. Supabase’s custom SMTP guide lists the configurations that need a real sending service, and they line up with the endpoints in the table above.

Email and password signup sends a confirmation. Passwordless sign-in sends a magic link or a one-time password over email, both from /auth/v1/otp. Invites sent from the Users page or the Auth admin APIs are email. Password resets go through /auth/v1/recover. Social login with email confirmation sends one too, which surprises people who assume an OAuth flow never touches mail. Email-change confirmations run through /auth/v1/user, which is the reason that endpoint appears on the email row at all and only when the call updates the address.

This is also why the error shows up so often on apps that were built fast with an AI tool. Lovable, Base44, Bolt, Replit, Cursor, Claude Code, v0 and Windsurf all reach Supabase Auth the same way any hand-written client does, several of them wire it up for you, and none of them configures a sending service on your behalf. The generated signup screen works perfectly on the two emails you send while building it. How Supabase ended up underneath so many apps assembled this way, Auth included, is a separate question, and the first real user is usually the one who finds this.

Common questions about the Supabase email rate limit

What is the Supabase email rate limit?

Two emails per hour, project-wide, on Supabase’s built-in email provider. It applies to the endpoints that trigger email sends: /auth/v1/signup, /auth/v1/recover, and /auth/v1/user when the call updates the user’s email address. Custom SMTP is the only documented way to change it. Checked against Supabase’s rate-limits documentation on 17 August 2026.

How do I fix “email rate limit exceeded” in Supabase?

First work out which limit fired. A user tapping resend twice, or a re-render firing the request again, hits the 60-second per-user window, which custom SMTP does not touch: wait out the window or change it at Authentication > Rate Limits. For the project-wide cap, configure custom SMTP on the Authentication settings page. That lifts the project-wide cap of 2 an hour and the restriction that only project-team addresses receive mail. The new starting ceiling is 30 messages per hour, adjustable at Authentication > Rate Limits. No code change is required.

Does the Supabase email rate limit reset, and how long does it take?

It expires rather than resets. The project-wide email limit is measured per hour, and the per-user windows on signup confirmation, password reset, and OTP or magic-link resend default to 60 seconds. Supabase documents no button that clears either counter early, as of 17 August 2026.

Is the email rate limit different on the Pro plan?

No. Supabase’s rate-limits table ties the 2-an-hour figure to the built-in email provider and lists custom SMTP as the only way to change it, with no plan condition attached. An April 2025 thread in Supabase’s GitHub discussions reaches the same conclusion after an upgrade did not help.

Why do I get the error when I have not sent any emails?

The counter is project-wide, so successful email-triggering requests elsewhere in the project can spend the hourly allowance. The built-in service also refuses addresses outside the project team. Supabase does not document whether those rejected requests consume the counter, so a project with no delivered messages still needs both its auth logs and both error surfaces checked.

What does over_email_send_rate_limit mean?

It is an AuthApiError code whose current description says too many emails were sent to the address and tells the user to wait. That wording does not document a separate recipient counter, its threshold, or whether another address is unaffected. Check the project-wide email cap and the per-user request window before retrying.

Can I raise the limit without custom SMTP?

Supabase’s rate-limits table marks the email row “Custom SMTP Only”, so the documented answer is no. The same page also shows a Management API call whose body includes a rate_limit_email_sent field, and it does not explain how that field interacts with the custom-SMTP-only restriction. Read as of 17 August 2026, the documentation does not reconcile the two.

Does custom SMTP mean unlimited emails?

No. Supabase imposes a starting limit of 30 messages per hour on a newly configured SMTP service to protect its sending reputation, adjustable at Authentication > Rate Limits. Your chosen provider will have its own quota and its own reputation rules on top of that.

If your signup form is the thing that broke, the two dashboard pages at the top of this article settle it faster than any code change: whether custom SMTP is on, and which addresses the built-in service is willing to mail. The awkward part is that the built-in provider is documented as a template-testing tool, and a lot of apps discover that only when a stranger tries to sign up.