Как добавить rate limiting — предохранитель от счёта на 10 000 запросов

Реальная страшилка вайб-кодера: модель написала тебе цикл, где-то ошиблась в условии выхода — и он ушёл дёргать платный API по кругу. Тысяча запросов в минуту, счёт растёт на глазах. Или бота нашёл скрипт-бот и долбит твой эндпоинт без остановки.
Лекарство одно и старое как мир — rate limiting, ограничение частоты запросов. Это предохранитель: «не больше N обращений за промежуток времени». Ниже — как добавить его руками, по шагам, без магии.
Шаг 1. Реши, что именно ограничиваешь
Прежде чем писать код, ответь на один вопрос: считать запросы по кому?
- По IP — простейший вариант, защищает от «долбёжки» снаружи. Годится для публичной формы или открытого эндпоинта.
- По пользователю — если у тебя есть вход, честнее считать по id пользователя: один человек с двух устройств не должен получать двойной лимит.
- По API-ключу — если твой сервис дёргают другие программы.
Для первого приложения бери IP — это 90% пользы за 10% усилий.
Шаг 2. Выбери, где поставить турникет
Ограничитель ставят перед дорогой операцией. Два типичных места:
- Перед своим эндпоинтом целиком — чтобы никто не завалил сервер.
- Прямо вокруг вызова платной модели — чтобы даже свой же кривой код не сжёг бюджет. Это тот случай из вступления.
Часто нужно и то, и другое. Начни с эндпоинта.
Шаг 3. Самая простая версия — счётчик в памяти
Идея на пальцах: держим для каждого IP счётчик и время. Пришёл запрос — проверяем, не превышен ли лимит в окне.
const hits = new Map(); // ip -> { count, resetAt }
const LIMIT = 20; // 20 запросов
const WINDOW = 60_000; // за 60 секунд
function rateLimit(ip) {
const now = Date.now();
const rec = hits.get(ip);
if (!rec || now > rec.resetAt) {
hits.set(ip, { count: 1, resetAt: now + WINDOW });
return true; // пропускаем
}
if (rec.count >= LIMIT) return false; // блокируем
rec.count++;
return true;
}
В эндпоинте: if (!rateLimit(ip)) return res.status(429).send('Too many requests'). Двадцать строк — и грубый предохранитель готов.
Важно понимать его границу: счётчик живёт в памяти одного процесса. Перезапустил сервер — счётчики обнулились; серверов два — у каждого свой счёт. Для пет-проекта норм, для продакшена — шаг 5.
Шаг 4. Не изобретай — возьми библиотеку
Для реальных проектов есть готовые пакеты (что это такое — в статье про npm). На Node с Express — express-rate-limit, одна установка:
npm install express-rate-limit
import rateLimit from 'express-rate-limit';
app.use(rateLimit({ windowMs: 60_000, limit: 20 }));
Она сама считает по IP, сама шлёт правильный ответ и заголовки. Меньше кода — меньше багов.
Шаг 5. Для продакшена — общий счётчик
Как только серверов больше одного (а на бессерверном хостинге так почти всегда), счётчик нужно вынести наружу — в общее хранилище. Популярный простой вариант — Upstash (Redis по HTTP): все процессы смотрят в один счётчик, лимит становится честным. Настраивается это тоже пакетом, ключи держи в переменных окружения, а не в коде.
Шаг 6. Верни правильный ответ и проверь
Когда лимит превышен, отдавай код 429 Too Many Requests и, если можешь, заголовок Retry-After с числом секунд — по нему вежливый клиент поймёт, когда повторить. Не отдавай 200 с пустотой: клиент решит, что всё хорошо.
Проверить легко — быстро отправь много запросов подряд:
for i in $(seq 1 30); do curl -s -o /dev/null -w "%{http_code}\n" localhost:3000/api; done
Первые ответы — 200, после лимита пойдут 429. Значит, турникет работает.
Что получится
Публичный эндпоинт, который не завалить в лоб, и — главное — потолок на вызовы платной модели. Даже если завтра ИИ напишет тебе цикл с ошибкой, он упрётся в лимит, а не в твою карту. Дальше эту же привычку встраивай сразу, а не после первого страшного счёта — про экономию в целом есть отдельный разбор.
Rate limiting и защита от DDoS — это одно и то же?
Нет. Rate limiting режет частоту от одного источника и спасает от случайной «долбёжки» и мелких ботов. Настоящую распределённую атаку с тысяч адресов он не остановит — для этого есть уровень хостинга и CDN. Но 95% бытовых проблем закрывает именно он.
Где поставить лимит — на фронте или на бэкенде?
Только на бэкенде. Фронтенд легко обойти, отправив запрос напрямую. Ограничение должно жить там, где принимается решение выполнять операцию.
Rate limiting — из тех вещей, что кажутся «на потом», а спасают уже сегодня. Двадцать строк на старте дешевле одного счёта на пятизначную сумму. А собрать первое приложение с таким предохранителем проще в компании того, кто объясняет на «ты».
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





