Бот Briefka, собирающий дайджесты телеграм-каналов, изначально использовал каскад из пяти LLM-провайдеров: два аккаунта Groq, затем Mistral, Cerebras и в конце платный DeepSeek. Идея была в том, чтобы все запросы обрабатывались бесплатно, и только при исчерпании всех лимитов подключался платный якорь. За четыре месяца число пользователей выросло с 59 до 84, и именно на этом масштабе схема начала давать сбои.

Проблема оказалась в thundering herd — одновременные запросы от рассылки дайджеста исчерпывали лимиты бесплатных провайдеров за секунды, и каскад массово падал на DeepSeek. В мае было 915 вызовов DeepSeek — по деньгам всего ~$0,10, но проблема была в линейном росте расходов при увеличении числа пользователей. Фактически разработчик сам себя DDOS-ил против собственных лимитов.

ПериодВызовов DeepSeekСтоимость
Февраль–март0$0
Апрель88~$0.02
Май (до фикса)915~$0.10
Май, 26+ (после фикса)0$0

Решение состояло из двух частей. Во-первых, разнос пользователей по времени с паузой 10 секунд между отправками дайджестов — общее время рассылки выросло с минуты до 13 минут, но лимиты успевали восстанавливаться. Во-вторых, сериализация LLM-вызовов внутри дайджеста с помощью asyncio.Semaphore(1): теперь запросы обрабатываются последовательно, без конкуренции за лимиты. Дополнительно ввели circuit breaker: если провайдер возвращает 429, он уходит на cooldown на 10 минут. Также реализован кросс-юзерный кэш — один и тот же пост обрабатывается через LLM только один раз для всех подписчиков.

При 84 пользователях параллельные запросы создавали thundering herd — бесплатные лимиты исчерпывались, и каскад падал на платный DeepSeek.

Отдельная грабля — российский IP первого VPS: запросы к зарубежным LLM с него блокировались. После переезда на зарубежный сервер проблема исчезла. Разработчик отмечает, что для безопасности в коде реализованы fallback ошибки и cooldown, а бесплатные провайдеры могут менять условия — поэтому нужен постоянно работающий мониторинг.