Перейти до вмісту

Основи безпеки

Supabase "Email Rate Limit Exceeded": два ліміти, один код помилки

Supabase "Email Rate Limit Exceeded" обмежує кожен лист вашого проєкту: 2 на годину з вбудованим відправником. Що враховується і як підняти ліміт.

Vlad Tkachenko9 хв читання
Аркуш марок, з якого вже вирвано всі марки, поруч зі стосом запечатаних конвертів без нічого в кутку.

Коротко

  • Supabase "Email Rate Limit Exceeded" означає, що ваш проєкт уже надіслав за цю годину стільки листів, скільки йому дозволено. З вбудованим відправником це 2 на годину, і рахується кожне підтвердження реєстрації, кожен magic link і кожне скидання пароля.
  • Той самий код, over_email_send_rate_limit, повертається і з повідомленням "For security purposes, you can only request this after N seconds", тобто 60 секунд очікування для однієї адреси. Розрізняє їх лише текст повідомлення.
  • Власний SMTP-провайдер знімає годинну межу, коли ви також піднімаєте ліміт на сторінці Rate Limits, де він починається з 30 на годину. 60 секунд очікування лишаються, і ваша форма має це пояснювати.

Ви перевіряєте форму реєстрації, перш ніж показати застосунок людям. Реєструєтеся зі своєю адресою, потім із vy+2@gmail.com, потім ще раз, щоб подивитися, чи гарно виглядає лист підтвердження. Одна з цих спроб зупиняється на цьому:

AuthApiError: email rate limit exceeded

Supabase "Email Rate Limit Exceeded" означає, що ваш проєкт вичерпав свою квоту листів на годину, тож Supabase Auth, частина Supabase, яка відповідає за вхід людей, відмовився надсилати ще один. На поштовому сервісі, з яким стартує кожен проєкт, ця квота становить два листи на годину на весь проєкт.

Ось що легко зрозуміти навпаки: код помилки охоплює два різні ліміти. Власний список кодів помилок Auth від Supabase описує over_email_send_rate_limit як "Too many emails have been sent to this email address." Це правда для одного з них. Той самий код повертається й тоді, коли квоту вичерпав увесь проєкт, хоч би кому був адресований лист, тож спроба з іншою адресою нічого не змінить. А звична порада "підключіть власний SMTP" дає лише половину рішення, бо Supabase запускає щойно підключений поштовий сервер із лімітом 30 листів на годину.

Що означає "Email rate limit exceeded" у Supabase?

Що ваш проєкт уже надіслав за цю годину стільки листів, скільки дозволяє Supabase Auth, і наступний відхилено.

Уявіть квоту як аркуш поштових марок. Supabase дає кожному проєкту фіксовану кількість марок на годину, і кожен лист, який надсилає Supabase Auth, витрачає одну, хоч би який це був лист і хоч би кому він ішов:

  • посилання для підтвердження після реєстрації
  • magic link або одноразовий код для входу
  • скидання пароля
  • запрошення, яке ви надсилаєте зі сторінки Users
  • підтвердження, коли хтось змінює свою адресу email

Коли аркуш порожній, Supabase Auth відповідає HTTP 429, що означає "забагато запитів", кодом over_email_send_rate_limit і повідомленням email rate limit exceeded. Ці слова взято з коду самого сервера Supabase Auth.

На вбудованому відправнику, поштовому сервісі, з яким стартує новий проєкт, на аркуші дві марки на годину. Це число зі сторінки лімітів Supabase на момент, коли ми читали її 20 жовтня 2026 року, а посібник Supabase про власний SMTP каже, що воно "can change without notice". За двох на годину одна реєстрація і одне скидання пароля вже становлять усю квоту години.

Кожен лист, який надсилає Supabase Auth, витрачає марку з того самого аркуша. На вбудованому відправнику на аркуші дві марки на годину.

Якщо ніхто взагалі не може увійти або весь застосунок порожній, справа в іншому, і почати варто з Supabase лежить чи проблема у вашому застосунку.

Два ліміти мають один код помилки

Повідомлення каже, який ліміт ви вичерпали. Код в обох однаковий:

ПовідомленняЩо обмеженоЩо рахуєтьсяТипове значення
email rate limit exceededУвесь проєктКожен лист, який надсилає Supabase Auth, за годину2 на годину з вбудованим відправником, 30 після підключення власного
For security purposes, you can only request this after N seconds.Одна адресаТой самий вид листа, повторно на ту саму адресуОдин раз на 60 секунд

Обидва відповідають HTTP 429 з over_email_send_rate_limit. Список кодів помилок Auth від Supabase радить розпізнавати помилки за кодом і "not string matching on error messages". Для коду вашого застосунку це правильно, але тут лишається прогалина: лише повідомлення каже, який ліміт вичерпано. Тож читайте повідомлення, щоб зрозуміти, що сталося, а застосунок нехай реагує на код.

Якщо застосунок пише лише "щось пішло не так", точне повідомлення є у відповіді на невдалий запит, на вкладці Мережа в інструментах розробника вашого браузера. Код over_request_rate_limit означає третій ліміт, на запити з однієї IP-адреси, і список Supabase каже, що він може вказувати на помилку у вашому застосунку, який надсилає їх забагато.

Порожній аркуш і 60 секунд очікування є двома різними відмовами, і Supabase повідомляє про обидві тим самим кодом.

Чому там написано "you can only request this after 0 seconds"?

Бо з очікування лишалося менше секунди. Ліміт на адресу дозволяє один лист кожного виду на ту саму адресу раз на 60 секунд: одне підтвердження реєстрації, одне скидання пароля, один magic link чи код. Якщо запитати раніше, Supabase Auth підраховує, скільки ще лишилося, і пише це в повідомленні.

Він рахує цілими секундами й відкидає решту. Функція сервера Auth, яка пише це повідомлення (errors.go), ділить залишок часу на одну секунду, тож 0,8 секунди виводиться як 0. Спробуйте ще раз за мить, і запит пройде, якщо в годинній межі проєкту ще лишилася марка.

Це очікування працює так, як задумано. Саме воно не дає кнопці повторного надсилання, натиснутій двадцять разів, відправити двадцять листів. Лишіть його на 60 секундах, а пояснення нехай дає ваша форма.

Годинна межа, і для кого вона

Вбудований відправник призначений для знайомства з Supabase, і Supabase прямо каже це у своєму посібнику з SMTP. Там перелічено, для чого цей сервіс: "Exploring and getting started with Supabase Auth", "Setting up and testing email templates with the members of the project's team" і "Building toy projects, demos or any non-mission-critical application". До нього також іде "No SLA guarantee on message delivery or uptime".

У тому самому посібнику є друге правило, і саме воно вирішує, хто яку помилку бачить. Доки ви не підключили власний поштовий сервер, Supabase Auth "will refuse to deliver messages to addresses that are not part of the project's team". Клієнта, який реєструється зі своєю адресою, відхиляють ще до того, як буде витрачено хоч одну марку, з іншим повідомленням:

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

Це HTTP 400 з кодом email_address_not_authorized, і в коді сервера Auth ця перевірка йде перед обома лімітами. Якщо реєстрація працює, коли пробуєте ви, і не працює для всіх інших, причина саме в цьому.

Тож на вбудованому відправнику email rate limit exceeded здебільшого бачите ви і ваша команда, коли тестуєте. Перевіряючи, чи належить адреса до вашої команди, сервер Auth ігнорує все між + і @. Через це vy+test1@gmail.com і vy+test2@gmail.com обидві рахуються як ви, і кожна тестова реєстрація витрачає одну з тих самих двох марок.

Як підняти ліміт листів у Supabase?

Підключіть власного поштового провайдера, а потім підніміть ліміт, який на нього ставить Supabase. Це два окремі кроки, і про другий часто забувають.

  1. Оберіть сервіс розсилки й візьміть його налаштування SMTP. Посібник Supabase називає Resend, AWS SES, Postmark, Twilio SendGrid, ZeptoMail і Brevo і каже, що підійде будь-який сервіс із підтримкою SMTP. Вам потрібні хост, порт, ім'я користувача і пароль, а також адреса відправника на кшталт no-reply@vashdomen.com.
  2. Увімкніть власний SMTP у налаштуваннях Authentication вашого проєкту й введіть ці дані. Відтоді Supabase надсилає на будь-яку адресу.
  3. Підніміть ліміт листів на сторінці Rate Limits, теж у розділі Authentication. За посібником, щойно підключений сервер отримує "a low rate-limit of 30 messages per hour", щоб захистити його репутацію, і змінюють його саме там. Поставте стільки, скільки дозволяє ваш провайдер і скільки потрібно у вашу найзавантаженішу годину.

Ще три речі з того самого посібника варто зробити разом із цією зміною:

  • Налаштуйте DKIM, DMARC і SPF для свого домену розсилки у провайдера. Supabase каже, що це "will significantly increase the deliverability of your messages".
  • Увімкніть CAPTCHA для реєстрацій. Посібник називає ботів, які реєструють списки адрес, "a common source of abuse", і кожна така реєстрація забирає лист із вашої години. CAPTCHA він називає "the most effective way" їх зупинити.
  • Перевірте, чи ваших користувачів не викидає із системи. За посібником, короткі сесії змушують "active users to sign in frequently, increasing the number of messages", і якщо ваші користувачі входять за посиланням із листа, кожен несподіваний вихід коштує марку. Чому користувачів Supabase викидає із системи розповідає про причини.

Про інші межі, на які натрапляє безплатний проєкт, читайте в що входить у безплатний план Supabase.

Обробка помилки у формі реєстрації

Ловіть її за кодом і простими словами кажіть людині, що робити. JavaScript-клієнт Supabase додає код сервера до помилки, яку повертає, як error.code, тож перевірка займає один рядок:

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

if (error?.code === 'over_email_send_rate_limit') {
  // показати: "Не вдалося надіслати лист просто зараз. Спробуйте ще раз за хвилину."
}

Попросіть свій інструмент, чи то Lovable, Bolt, v0, Cursor, Claude Code чи Replit, про три речі:

  • ту саму перевірку в кожній формі, що надсилає лист: реєстрація, "забули пароль", вхід за посиланням із листа і "надіслати ще раз"
  • повідомлення, яке просить людину спробувати трохи згодом, замість сирої помилки або форми, що мовчки нічого не робить
  • кнопку повторного надсилання, вимкнену на 60 секунд після кожного надсилання, щоб ніхто не натискав її під час очікування для адреси

Обійдіться без автоматичних повторів. Поки аркуш порожній, кожен повтор відхиляється, а запити на реєстрацію ще й обмежені за IP-адресою, типово 30 за 5 хвилин. Цикл повторів може зачепити і цей ліміт, а він відповідає кодом over_request_rate_limit.

Чого не змінювати, поки реєстрації стоять

Підтвердження email і те, звідки йдуть листи. Два обхідні шляхи прибирають помилку і лишають вас у гіршому становищі.

Лишіть підтвердження email увімкненим. Якщо вимкнути "Confirm email", реєстрації взагалі перестануть надсилати листи, і помилка зникне. Посібник Supabase з SMTP вносить "Do not disable email confirmations under pressure" до своїх засобів захисту, бо без підтвердження хтось може створити акаунт на ім'я іншої людини.

Тримайте листи поза браузером. Попросіть асистента "просто надіслати підтвердження через Resend", і він може вставити API-ключ провайдера у фронтенд вашого застосунку, де кожен відвідувач може його прочитати й надсилати пошту від вашого імені. Надсилайте листи через налаштування SMTP у Supabase або через серверну функцію, ніколи з ключем на сторінці. Якщо не впевнені, що жоден не просочився, наш безплатний скан читає код, який ваш робочий застосунок надсилає кожному відвідувачу, і позначає секретні ключі, які там знаходить. Це займає близько 20 секунд і не потребує акаунта: проскануйте свій застосунок.

Стежити за застосунком, поки ви змінюєте надсилання листів

Дві речі можуть піти не так, поки ви переробляєте надсилання листів: ключ опиниться в коді застосунку, а повідомлення "ніхто не може зареєструватися" відправить вас шукати збій.

Reeve Monitor і далі перевіряє ззовні:

  • чи доступний ваш застосунок, з перевіркою щохвилини, щоб ви одразу знали, чи скарга на реєстрацію означає збій, чи щось вужче
  • повну перевірку безпеки щогодини, до трьох застосунків, разом із секретними ключами в коді, який ваш застосунок надсилає відвідувачам
  • повідомлення, коли результат змінюється, щоб ключ, який пішов із пізнішим деплоєм, дійшов до вас без того, щоб ви самі йшли дивитися
  • щомісячний звіт простою мовою про те, що він бачив

Reeve Care зберігає копію вашої бази даних Supabase:

  • зашифровану копію за розкладом, у власному сховищі Reeve в ЄС, поза вашим акаунтом Supabase
  • схему auth, де живе кожен акаунт, якому таки вдалося зареєструватися
  • кожну копію, перевірену, перш ніж вона зарахується, підрахунком рядків у кожній таблиці
  • також ваші завантажені файли, щойно ви підключите доступ до Storage
  • відновлення в один клік, перед яким робиться страхувальна копія поточного стану
  • усе, що робить Monitor

Що зробити зараз

Що робити

  • Читайте повідомлення, а не лише код: email rate limit exceeded означає годинну межу проєкту, а For security purposes… означає 60 секунд очікування для однієї адреси.
  • Якщо клієнти бачать Email address … cannot be used as it is not authorized, ваш проєкт досі на вбудованому відправнику Supabase, який пише лише вашій команді.
  • Підключіть власного SMTP-провайдера, а потім підніміть ліміт листів на сторінці Rate Limits, де він починається з 30 на годину.
  • Налаштуйте DKIM, DMARC і SPF у провайдера й увімкніть CAPTCHA для реєстрацій.
  • Нехай кожна форма, що надсилає лист, перевіряє over_email_send_rate_limit, показує зрозуміле повідомлення і блокує кнопку повторного надсилання на 60 секунд.
  • Лишіть підтвердження email увімкненим і ніколи не кладіть ключ поштового провайдера у фронтенд.

Почніть із повідомлення в невдалій відповіді, бо воно каже, який із двох лімітів ви вичерпали. А коли листи вже підуть через вашого провайдера, проскануйте свій застосунок, щоб перевірити, що разом із ними не прийшов жоден ключ.

Поширені запитання

Що означає "email rate limit exceeded" у Supabase?

Що ваш проєкт уже надіслав за цю годину стільки листів, скільки дозволяє Supabase Auth, тож наступний відхилено. Рахується кожен лист, який надсилає Auth, будь-кому: підтвердження реєстрації, magic links, скидання пароля і запрошення. З вбудованим відправником це 2 на годину. З власним SMTP-провайдером число встановлюєте ви.

Чому там написано, що повторити запит можна лише через 0 секунд?

Бо з 60 секунд очікування лишалося менше секунди. Supabase Auth рахує залишок цілими секундами й відкидає решту, тож остання секунда показується як 0. Спробуйте ще раз за мить, і лист піде, якщо в годинній межі ще є місце.

Скільки листів Supabase може надіслати за мене?

З вбудованим відправником 2 на годину на весь проєкт, і лише людям із вашої команди в Supabase. Supabase каже, що це число може змінитися без попередження. З власним SMTP-провайдером фіксованого числа немає: Supabase починає з 30 на годину, а ви піднімаєте його на сторінці Rate Limits.

Чи потрібен мені власний SMTP-провайдер?

Так, щойно хтось поза вашою командою реєструється через email. Вбудований відправник відхиляє адреси, яких немає у вашій команді, і Supabase описує його як призначений для знайомства, перевірки шаблонів і демо. Resend, AWS SES, Postmark, SendGrid, ZeptoMail і Brevo серед сервісів, які Supabase називає сумісними.

Як не дати цьому зламати форму реєстрації?

Перевіряйте код помилки, перш ніж щось потрапить на екран. Якщо це over_email_send_rate_limit, покажіть зрозуміле повідомлення з проханням спробувати за хвилину і тримайте кнопку повторного надсилання вимкненою 60 секунд після кожного надсилання, щоб ніхто не натискав її під час очікування.

Чому мої клієнти отримують "Email address not authorized"?

Бо ваш проєкт досі надсилає через вбудований відправник Supabase, який доставляє лише учасникам вашої організації в Supabase. Усіх інших він відхиляє з кодом email_address_not_authorized. Це виправляє підключення власного SMTP-провайдера, і та сама зміна знімає годинну межу.

Автор

Vlad Tkachenko

Засновник Reeve

Я щодня дивлюся на застосунки, зібрані в Lovable, Bolt, v0, Cursor і Replit, і на короткий список помилок, які трапляються в них знову і знову.

Більше про автора

Читати далі

Усі статті

Зробіть резервну копію бази Supabase перед наступною зміною

Reeve за розкладом зберігає зашифровану копію і відновить її за вас, якщо щось зламається.

Резервні копії Supabase

Автоматична зовнішня перевірка, а не повний аудит. Відсутність знахідок не є гарантією безпеки.