Stop retrying the send and copy the exact error text first, because retries can count against the same window. Email rate limit exceeded is one message used by 4 layers: your auth service’s built-in mailer, your email provider’s plan quota, a mailbox host such as Gmail or Microsoft 365, and the receiving server. The wording tells you which.

Email rate limit exceeded: what to do right now

An email rate limit exceeded error is handled in 5 steps: stop every retry, save the full error with its status code and time, identify which layer refused the send, count the users who are stuck, and get them signed in another way while the window runs. Change providers after that, not before.

  1. 01 Stop the retries. Turn off any loop, scheduled job, test script or repeated clicking that is sending again, because a retry can count against the same window.
  2. 02 Save the evidence before it scrolls away: the full error object, the HTTP status, the response headers (a Retry-After header if there is one) and the time, from the browser's network tab or the server log.
  3. 03 Identify the layer from the wording and the status code, using the table in the next section.
  4. 04 Count who is stuck: unconfirmed users created in the last few hours in the auth provider's user list, or refused and queued sends in the email provider's activity log. Write the number down.
  5. 05 Get the stuck users through while the window runs, where your auth provider lets a server confirm a user or generate a sign-in or reset link that you send another way. That works for a handful of people, not for a thousand.

A refused send is one branch of how to improve email deliverability, and the branch where the fix depends most on reading the message before touching anything.

The fifth step has a real route on some stacks. Supabase’s admin API has generateLink, which “Generates email links and OTPs to be sent via a custom email provider”, and updateUserById, whose changes “are applied directly without confirmation flows”; both need the secret key and belong on a trusted server. Firebase’s Admin SDK generates password reset, verification and sign-in links that you can send through your own delivery service. For a user stuck unconfirmed, Lovable’s docs say you can create the account for them with Add user → Create new user in More → Cloud → Users, and users created that way are confirmed automatically; a way to copy a link is not stated.

I put them in this order because switching provider feels like the fix, and it throws away the error text that says which limit fired. If you are a user of someone else’s app and see this at signup, only that app’s owner can fix it. Wait, then try once.

What the message means: the four layers that send it

Email rate limit exceeded means a sender or receiver refused a message because too many were sent in its window. Four layers use the wording: an auth service’s built-in mailer, an email provider’s plan quota, a mailbox host such as Gmail or Microsoft 365, and the receiving server. An HTTP 429 points at the first two.

Which of them printed it decides what to do next, so start from the text and the status code you already have.

LayerThe wording and code you seeWhere you see itThe windowWho can raise it
Auth service’s built-in mailerSupabase: HTTP 429 with an error code that names email sends. Lovable: new emails rejected “until the hour resets”Browser console or the auth response, at signup or password resetPer hour. Lovable per workspace: Pro 100 app and 500 authentication emails, Business 300 and 3,000, Enterprise 1,000 and 10,000Supabase: you, by moving to custom SMTP or a Send Email hook. Lovable: Lovable Support; authentication emails also have a per-project limit you can adjust yourself
Email provider’s planHTTP 429 with the provider’s error type, such as Resend’s rate_limit_exceeded or daily_quota_exceeded; Amazon SES returns ThrottlingExceptionYour server logs and the provider’s logPer second, per day or per month, by plan (figures in the provider table below)You, by upgrading, or the provider’s support where its docs offer a rate increase
Mailbox host used as SMTPGoogle Workspace: “You have reached a limit for sending email.”; Microsoft 365: “the sender’s submission quota was exceeded”A bounce in that mailbox, or the SMTP reply in your app’s logPer day: Google Workspace blocks sending “for up to 24 hours”; Microsoft counts the past 24 hoursMicrosoft: nobody (“can’t be increased”). Google: a raise on request is not stated in Google’s docs
Receiving serverSMTP 421 4.7.28 (“Gmail has detected an unusual rate of email”) or 450 4.2.1Only in the provider’s activity log, as deferred or delayedSet by the receiver; no figure is stated in Google’s SMTP error referenceOnly the receiver; your side can slow down and check authentication
Your own codeWhatever message your resend button printsYour appWhatever you setYou. It is working as intended

Reading the code takes two rules. A 429 is HTTP’s “Too Many Requests”, which RFC 6585’s 429 status code defines as “the user has sent too many requests in a given amount of time”, so it came from an API sitting in front of the mail. SMTP replies that start with 4 are transient, meaning “the action may be requested again”, and replies that start with 5 are permanent; Google’s SMTP error reference lists its rate deferrals under 421 and 450.

The fourth layer is the one people misread, because nothing in their own app changed. On 4 September 2026, Clerk, an authentication service, posted on its status page that emails to Microsoft-hosted mailboxes “are being rate limited on the receiving side”. Its update added that the emails “are still accepted but some are delayed by several minutes while they’re retried”, and it reported delivery normal again “since 12:40 UTC” the same day. The refusal names its layer if you keep the exact text, and a fix only works on the layer that refused. As I read it, no plan upgrade or setting on the sender’s side would have moved that one.

Why this happens

These are the causes as I read them, most common first for an app built on a builder platform. The first is the app still sending through the auth service’s built-in mailer, which Supabase’s own docs say “is not meant for production use”. Then come a developer testing signup over and over from one machine, a launch, import or invite blast that sends a day’s volume in a minute, and a retry loop with no backoff that turns one refusal into dozens.

The last two are less obvious. A signup form with no abuse protection lets a stranger enter other people’s addresses, so the attacker spends your quota and your reputation. A new sending domain or a shared IP that the receiver does not trust yet gets deferred even at modest volume.

CauseThe layer it hitsHow you confirm it
Built-in mailer still in useAuth service’s built-in mailerThe auth settings show no custom SMTP or provider connected
Repeated test signups from one machineAuth service’s built-in mailerThe auth logs show the requests coming from one IP or one address
Launch, import or invite blastBuilt-in mailer or provider planThe provider’s log shows that hour’s send count near the plan’s limit
Retry loop with no backoffAny layer with an APIYour server log shows the same request repeated seconds apart
Signup form used by a strangerBuilt-in mailer or provider planNew unconfirmed users with addresses nobody on your team recognizes
New domain or untrusted shared IPReceiving serverDeferrals at one mailbox provider only, with 421 replies in the provider’s log

Supabase, Firebase and builder platforms: the built-in mailer’s hourly cap

Built-in auth mailers are capped per hour or per day. Supabase caps its built-in email service for the whole project, Firebase Authentication sets daily limits per email type that rise on the Blaze plan, and Lovable limits how many emails a workspace sends per hour, with separate limits for app emails and authentication emails.

Supabase allows “2 emails per hour with the built-in email provider” for the whole project, plus a separate 60-second window per user that its table lists as its own limit; the two Supabase email rate limits, the error code and what upgrading does and does not change have their own walk-through. The numbers sit on Supabase’s Auth rate limits page.

Firebase Authentication’s limits are daily. On the Spark plan it allows 1000 address verification emails, 150 password reset emails and 5 email link sign-in emails a day; on the Blaze plan those become 100,000, 10,000 and 25,000. For higher limits, Firebase says to “contact Firebase support at least two weeks in advance”. Lovable’s per-plan hourly figures are in the table above.

The pattern, as I read it: a built-in mailer you did not choose is there so you can try the product, and an app with real signups belongs on its own provider, set up along the lines of transactional email best practices. Supabase says its default server exists “To get you started”.

Resend, SendGrid, Postmark and Amazon SES: plan quotas and per-second limits

Transactional email providers usually set two limits: a quota by plan and a speed per second. Resend’s free plan prints 100 emails a day and 3,000 a month. A refusal arrives as an HTTP 429 or the provider’s own error code, and the error type says which limit it was.

ProviderThe quota the docs printThe per-second limitWhat the refusal looks likeHow to raise it
ResendFree: 100 emails a day, 3,000 a month; paid plans have no daily quota10 requests per second per teamHTTP 429 with rate_limit_exceeded, daily_quota_exceeded or monthly_quota_exceededUpgrade the plan; contact support for a rate increase
SendGridFree trial: 100 emails a day for 60 daysA fixed number of requests per refresh period per endpoint; up to 10,000 requests per second to v3 Mail SendHTTP 429 with “too many requests” and an X-RateLimit-Reset headerUpgrade to a paid plan
PostmarkFree Developer plan: 100 emails every monthNot stated in Postmark’s docs as a number; the API answers 429 at “a rate that exceeds acceptable use”HTTP 429 “Rate Limit Exceeded”Move to a paid plan; paid tiers start at 10,000 emails a month
Amazon SESSandbox: 200 messages per rolling 24-hour period, per RegionSandbox: 1 message per secondThrottlingException with “Daily message quota exceeded” or “Maximum sending rate exceeded”; over SMTP, “454 Throttling failure”Request production access, then quota increases through the AWS Support Center

Limits checked on 4 October 2026, on each provider’s own docs and pricing pages: Resend’s rate limit docs, SendGrid’s rate limits, Postmark’s API overview and support center, and Amazon SES sending quotas.

Two details change what a retry does. Amazon SES says that when a quota is reached it “drops the message and doesn’t attempt to redeliver it”, so a refused password reset is gone and has to be sent again later. In the sandbox, SES also sends only to verified addresses and domains or its mailbox simulator, so a launch from a sandboxed account fails for real customers before any quota is reached. Which provider fits an app is a separate question; this table carries only the limits.

Gmail and Microsoft 365 as the app’s SMTP: the mailbox limit

A Gmail or Microsoft 365 mailbox used as an app’s SMTP server has a daily limit meant for a person, which a busy app day can pass. Google Workspace then blocks sending for up to 24 hours, and Microsoft 365 until the past 24 hours’ recipients drop below the limit. Move app mail to a transactional provider.

Google Workspace sending limits give a user account 2,000 messages a day (500 on a trial account) and 100 recipients per message for mail sent over SMTP, counted over “a rolling 24-hour period”; Google’s SMTP relay service has limits of its own. Past a limit, Google says “users can’t send new messages for up to 24 hours”. A personal Gmail account has a lower limit with its own message, which may appear past 500 emails sent in a day; its wording and wait are in the last question below.

Exchange Online limits are 10,000 recipients per day and 30 messages per minute per mailbox, and Microsoft calls both “hard limits enforced at the service level” that “can’t be increased”. Messages submitted over SMTP faster than the message rate “will be rejected and the client will need to retry”.

I would not fix it with a bigger mailbox or a second account, and the mailbox stays with the people who read it.

How to fix it, by layer, and how to confirm it worked

The fix for an email rate limit depends on the layer: your own provider for a built-in mailer, a plan or rate increase for a provider quota, moving app mail off a mailbox host, and slower sending for receiver deferrals. The proof is one delivered message of each critical type, found in the provider’s log with its time.

LayerThe fixThe proof it worked
Built-in mailerConnect your own provider by SMTP or API in the auth service’s settings, after verifying the sending domain, then check the auth service’s own hourly email settingA real signup email shows as delivered in the new provider’s log
Provider planUpgrade the plan or request a higher rate; on Amazon SES, request production access before launchThe send that failed now appears in the provider’s log as delivered
Mailbox hostMove app mail to a transactional providerThe provider’s log shows the app’s messages delivered, sent from the provider, not the mailbox
Receiving serverSlow sending to that domain, let the provider’s retries run, check authentication and reputationDeferrals for that domain stop and the delayed messages show as delivered
Your own codeShow the user the wait time instead of a raw errorA second click inside the window shows the wait, not an error

For a built-in mailer, verify the sending domain before you switch; SPF, DKIM and DMARC setup comes first, or the new provider’s mail lands somewhere worse. Then open the auth service’s own emails-per-hour setting. On Supabase it stays low after you connect custom SMTP until you change it, which is part of the Supabase walk-through above.

For Amazon SES, the production access request is made from the account dashboard, where you choose “Marketing or Transactional”, give a website URL and agree “to only send email to individuals who’ve explicitly requested it”. AWS says its support team gives “an initial response to your request within 24 hours”, which is the reason to file it before a launch, not on the day.

For receiver deferrals, the provider’s retries usually clear the backlog, as they did in the incident above. If deferrals keep coming at one mailbox provider, the problem is reputation or authentication, and mail that is deferred and then filtered is a different failure: transactional emails landing in spam.

The proof has to pass when the limit is cleared and fail while it is live, so run it on the deployed production app, not on a local dev server with its own mail settings. Send one real message of each critical type (signup, password reset, receipt) to a mailbox you control. Find each send in the provider’s log and check that its status is delivered, not only sent: Resend’s email.sent means “the API request was successful”, while email.delivered means it “successfully delivered the email to the recipient’s mail server”. On SES in the sandbox, the mailbox must be a verified address. Save the log entry and the received message with their times. Then repeat the step that failed, the signup that threw the error, once and not in a loop. If the provider log shows the message delivered and the inbox does not, the limit is cleared and the problem has changed to delivery, the spam-folder failure above.

For an API that answers 429 with a Retry-After header, as Resend does, a sender can wait the stated seconds instead of hammering the endpoint. Here send() is your own call to the provider’s API:

let res = await send();
for (let i = 1; i <= 3 && res.status === 429; i++) {
  const secs = Number(res.headers.get('retry-after')) || 2 ** i;
  await new Promise((r) => setTimeout(r, secs * 1000));
  res = await send();
}
// still 429 after three waits: stop, keep the error, find the layer

Amazon SES asks for something slower: on a ThrottlingException, its docs say to “wait for an interval of up to 10 minutes, and then retry”.

How to stop it happening again

These five controls are the ones I rely on, and each keeps one of the causes above from coming back.

  1. 01 Send app mail through a dedicated transactional email provider with delivery tracking, never the auth service's built-in mailer or a person's mailbox.
  2. 02 Put every send through a queue that honors Retry-After and backs off, so one refusal never becomes a hundred attempts.
  3. 03 Throttle the resend button and the signup form per user and per IP address, so a stranger cannot spend your quota.
  4. 04 Alert on the first 429 or the first spike in deferrals from the provider, not on the first customer complaint, and test the alert once with the provider's own test path or a copy of the alert with its threshold lowered until it fires.
  5. 05 Before a launch, an import or an invite campaign, compare the expected sends per hour with your plan's limit and ask for the raise well ahead.

The third control sits on the resend button, which belongs to the larger job of how to send a verification email; the wording of the message is a matter for an email verification email template. If the quota was spent by an abuser, the stuck users are the small problem: check what else that form lets a stranger do.

Common questions about email sending limits

How many emails can I send in 24 hours?

A Google Workspace user can send up to 2,000 messages in 24 hours, a Microsoft 365 mailbox can send to 10,000 recipients, and an email provider sets its own figure by plan, such as 100 a day on Resend’s free plan. A personal Gmail account may show its limit message past 500 emails sent in a day.

How many emails can I send with Office 365 per day?

An Office 365 mailbox can send to 10,000 recipients per day, counted over the past 24 hours, and no more than 30 messages a minute. The daily limit counts recipients, not messages, so one message to several people uses several, and Microsoft says it can’t be increased.

What does the “365 email sending limit exceeded” message mean?

It means the Microsoft 365 mailbox passed its recipient rate limit of 10,000 recipients in 24 hours, and Microsoft’s bounce reads “The message can’t be submitted because the sender’s submission quota was exceeded.” Sending resumes once the recipients from the past 24 hours drop below the limit. If you didn’t send those messages and suspect the account has been compromised, Microsoft says to reset the password. My position is that an app should not be sending from a person’s mailbox in the first place.

How to bypass rate limit exceeded?

There is no bypass worth having. Rotating accounts, addresses or IPs to dodge a limit puts the sending domain’s reputation at risk, as I read it, and the receivers that defer you will notice. The legitimate routes are a higher plan, a rate increase request where the provider offers one, or your own email provider in place of a built-in mailer.

How to solve you have reached a limit for sending mail?

Wait, then move app mail off the mailbox. That wording is personal Gmail’s, which Google says you may see past 500 recipients in a single email or 500 emails sent in a day, and after it you “should be able to send emails again within 1 to 24 hours”.