Cloudflare D1 на бесплатном плане отключается при превышении лимитов
Бесплатная база на Workers перестала быть «мягкой»: после лимита запросы падают до полуночи UTC. Как считаются строки, почему батчи не спасают от лимита записей и что менять в запросах.

Cloudflare с 1 сентября начала жёстко применять дневные лимиты D1, встроенной SQLite-базы для Workers, на бесплатном плане Workers Free. Об этом компания сообщила в записи changelog. Раньше превышение суточной квоты на строки проходило почти незаметно, теперь запросы через Workers Binding API и REST API возвращают ошибки и не работают до полуночи по UTC. Данные при этом не удаляются.
Если у вас на Workers Free крутится пет-проект, бот или небольшой сервис с базой в D1, это касается напрямую: в один день трафик чуть выше обычного, и после обеда по Москве запросы к базе начинают завершаться ошибкой до трёх часов ночи, а приложение без обработки этой ошибки показывает её пользователям. Cloudflare обещает письмо при достижении лимита, но письмо не починит прод.
Ключевые выводы
- Лимиты Workers Free для D1: 5 млн прочитанных строк и 100 тысяч записанных строк в сутки, 5 ГБ хранилища на аккаунт.
- С 1 сентября при превышении запросы к D1 завершаются ошибкой до сброса счётчика в 00:00 UTC (03:00 мск); сохранённые данные не затрагиваются.
- На Workers Paid за $5 в месяц включено 25 млрд чтений и 50 млн записей в месяц, дальше $0,001 за миллион прочитанных строк и $1 за миллион записанных; 5 ГБ хранилища включено, дальше $0,75 за ГБ в месяц.
- Строки считаются по факту прочитанного движком, а не по числу строк в ответе: SELECT без индекса по таблице в 100 тысяч строк — это 100 тысяч чтений.
- Cloudflare советует посмотреть статистику запросов за прошлые дни и добавить индексы: полное сканирование таблицы съедает лимит чтений быстрее всего.
Что изменилось на самом деле
Сами лимиты не новые, они давно указаны на странице тарифов. Изменился режим их применения: до 1 сентября Cloudflare не блокировала запросы при превышении, теперь блокирует. Ограничение действует и на вызовы из кода Worker через биндинг, и на REST API, которым пользуются внешние интеграции и админки. В тексте ошибки предлагается два выхода: перейти на платный план или подождать до завтра.
Upgrade to a paid plan or wait until tomorrow.
Компания подчёркивает, что хранилище остаётся нетронутым: речь только о временной недоступности запросов, а не о потере или заморозке данных. Счётчик сбрасывается в полночь по UTC, в три часа ночи по Москве. Уведомление по электронной почте приходит при достижении дневного лимита, и Cloudflare отдельно рекомендует посмотреть активность запросов за прошлые дни, чтобы понять, насколько проект близок к границе.
Почему один запрос может стоить 100 тысяч чтений
Главная ловушка D1 — учёт по прочитанным строкам, а не по запросам. Запрос SELECT * FROM events WHERE user_id = ? без индекса по user_id заставляет движок пройти всю таблицу, и каждая пройденная строка засчитывается в лимит, даже если в ответе одна запись. Поэтому небольшой сервис с парой тысяч посетителей в день может упереться в 5 млн чтений на одном неудачном запросе в цикле. Cloudflare в changelog прямо называет виновника: запросы с полным сканированием таблиц, и советует индексы как первое средство.
Сколько строк реально прочитал запрос, D1 возвращает в объекте meta ответа: поля rows_read и rows_written. Именно по ним, а не по числу вызовов, стоит оценивать, насколько вы близки к лимиту. Суммарную картину за день показывают GraphQL Analytics API и дашборд Cloudflare; страница тарифов перечисляет все три способа отслеживать расход.
С записями та же логика: учитываются записанные строки, а не вызовы. Объединение вставок в один батч сокращает число запросов и задержку, но не уменьшает rows_written, так что от лимита в 100 тысяч записей в сутки оно не спасает. Единственный способ уложиться — писать меньше строк: агрегировать события, не хранить в D1 логи на каждый запрос, выносить телеметрию в Analytics Engine или KV.
Сколько стоит платный план
Workers Paid стоит $5 в месяц и снимает дневные лимиты. По странице тарифов в него включены 25 млрд прочитанных строк и 50 млн записанных строк в месяц, сверх этого чтение стоит $0,001 за миллион строк, запись — $1 за миллион строк. Хранилище: 5 ГБ включено, дальше $0,75 за гигабайт в месяц. Бесплатный план даёт те же 5 ГБ, но при их превышении не тарифицирует, а блокирует новые записи и изменение схемы; но 5 млн чтений и 100 тысяч записей в сутки, то есть примерно 150 млн чтений и 3 млн записей в месяц.
Что сделать до вечера
- Откройте статистику D1 в дашборде за последние две недели: если пиковые дни выше 3–4 млн чтений, по нашей оценке вы в зоне риска; порог редакционный, Cloudflare его не задаёт.
- Пройдитесь
EXPLAIN QUERY PLANпо самым частым запросам и добавьте индексы там, где видитеSCAN. - Кэшируйте горячие ответы в KV или Cache API: одно чтение из кэша вместо тысячи строк из базы.
- Записи ограничены сильнее чтений: считаются записанные строки, а не вызовы, батчи не помогут; пишите меньше строк, агрегируйте события и не кладите логи в D1 на каждый запрос.
- Обрабатывайте ошибку D1 в коде: показывайте пользователю понятное сообщение и отдавайте кэшированные данные, а не пятисотую страницу.
Контекст
D1 вышла из беты в 2024 году как «SQLite на краю сети» для Workers: база живёт рядом с кодом и тарифицируется по строкам, а глобальная репликация чтения доступна как отдельная бета-функция, а не по процессорному времени. Учёт по строкам — осознанный выбор Cloudflare, и до сих пор он был безболезненным для бесплатных проектов. Для D1 «бесплатно» теперь читается буквально: в пределах квоты сервис работает, за пределами останавливается, а не копит счёт. Распространится ли такой режим на другие бесплатные лимиты Workers, changelog не говорит.
Источники: D1 free tier limit enforcement (Cloudflare Changelog), D1 pricing
Изображение на обложке: Cloudflare











