Патчи в CI у Anthropic жили 70 дней, 29 дней и меньше суток

За полгода число задач CI в Anthropic выросло в 25 раз. Внутренний сервис отбора тестов трижды латали, прежде чем переписать с нуля, и каждая заплатка жила короче предыдущей: 70 дней, 29 дней, меньше суток.
Как это было, инженер Anthropic рассказал 14 сентября в блоге Claude. Сами приёмы, по его словам, обычные: машина побольше, параллельная обработка, перезапуск сервиса («да, этот до сих пор работает на удивление хорошо»). Важнее другое: каждый из них выигрывал лишь долю того времени, что год назад. Зато полная переделка стала в разы дешевле, раз написание кода перестало быть узким местом. Главный урок автор формулирует так: «всегда закладывайтесь на экспоненту».
Откуда 25x
Инженеры Anthropic за квартал отгружают в 8 раз больше кода, чем в 2021-2025 годах, и 80% этого кода пишет Claude. Обе цифры взяты из отчёта Anthropic Institute о рекурсивном самоулучшении, опубликованного 4 июня на внутренних инженерных метриках. Claude к тому же всё активнее ревьюит и одобряет PR, так что ускорилось и ревью. Нагрузка дошла до CI.
Тестов в кодовой базе за тот же период стало в 10 раз больше, инженеров добавилось немного. Задачи CI выросли сильнее тестов, хотя на каждом PR запускается далеко не каждый тест. Именно этим отбором и занимается сервис, который пришлось перестраивать.
Слушатель и селектор
Многие коллеги автора работают там, где на каждое изменение по-прежнему гоняют все тесты. До какого-то масштаба это работает, но потом проверки в CI становятся долгими, дорогими и ненадёжными. С агентами есть ещё одна причина: человек сам поймёт, какие упавшие тесты к его правке не относятся, а агенту нужны контекст и направление. Получив конкретный набор валидных тестов, агент эффективнее проверяет себя и итерирует.
В Anthropic построили детерминированный сервис test impact analysis. Он решает, какие тесты запускать на каждое изменение, по истории их прошлых результатов и по связи с затронутыми пакетами. Практика не редкая, и на рынке есть целая категория вендоров с такими продуктами. Сервис держится на двух компонентах, которые должны оставаться синхронными. Listener записывает результаты тестов из каждого прогона CI. Selector читает накопленную историю и решает, какие тесты запускать на открытых PR.
Когда каждую секунду идёт по несколько задач CI, listener начинает отставать от очереди PR. Двадцать минут такого отставания превращаются в десятки тысяч обновлений по тестам, которые не дошли до selector. Если в основную ветку влили плохое изменение, тест начинает падать у всех остальных, и несколько человек разбираются в одном и том же. Если начинает «флакать» зависимость (тесты на ней то проходят, то падают), ложные красные прогоны блокируют слияния. Починенный или новый тест не запустится, пока listener не догонит очередь, и вместе с этим растёт риск регрессии.
Весь сервис работал одним процессом. Чтобы вести историю по каждому тесту, результаты должен был применять единственный писатель, и такая архитектура v0 не давала шардировать сервис горизонтально.
Три заплатки
В октябре 2025 года сервис уже трещал, и команду два дня подряд будили пейджером. Первое решение было простым: удвоили число ядер, заранее понимая, что надолго не хватит. Хватило на 70 дней. Тренд был очевиден, а вот с ответственностью было мутно: «Никто не хотел брать на себя ещё один кусок инфраструктуры», а у команды CI были задачи поважнее.
Пейджер срабатывал всё чаще, и автор завёл долгую сессию во внутренней версии Claude Tag, того самого, который в Anthropic ведёт первую линию дежурства CI. Сессия следила только за этим сервисом: стоило отставанию listener превысить 50 000 задач, Claude писал автору и продолжал прежний разговор о следующих шагах. Так продолжалось месяцами, и контекст прошлых попыток напоминать не приходилось. «Claude часто настаивал на полной переделке, но обычно мы останавливались на очередной заплатке», признаётся автор.
В феврале экспоненциальный рост задач снова упёрся в сервис, и его распараллелили. Оказалось, что listener нужен не один писатель на всё, а один писатель на пакет: этого достаточно, чтобы результаты по каждому участку кодовой базы шли в правильном порядке. Claude сгенерировал код, который разложил состояние каждого пакета по отдельному шарду со своим воркером. Что решение временное, тоже понимали, но не ждали, что оно продержится всего 29 дней.
В марте процесс в большинство будних дней упирался в лимит памяти к середине дня. Быстрых решений не нашлось: багов обнаружили всего четыре, замена аллокатора памяти ничего не дала, а профилировать память у единственного экземпляра под тяжёлой нагрузкой не рискнули. Оставались ежедневные перезапуски, и они купили уже меньше суток.
К тому же после каждого перезапуска сервис отставал всё сильнее. Несколько раз отставание превышало час, и тогда listener терял заметную часть результатов. Автор уточняет, что CI на этих PR всё равно отрабатывал и непротестированный код в продакшен не уходил. Но selector решал, какие тесты запускать, по устаревшим данным, и на деле это чаще всего означало прогон тестов, которые и так сильно флакали или падали повсюду.
Что поменяли при пересборке
В итоге команда последовала совету Claude и дала сервису отдельное хранилище, а именно in-memory хранилище данных. Основную работу, которую раньше держал в памяти единственный процесс, вынесли туда.
- Состояние: в памяти одного процесса → в журнале во внешнем in-memory хранилище.
- Обработка результатов: один писатель, после февральской заплатки по одному на пакет → любой воркер listener берёт любой результат, дописывает его в журнал и идёт дальше, ничего не держа в памяти.
- Очередь необработанных событий: копилась почти каждый день и росла от недели к неделе → после переключения и настройки держится ровной.
Раз воркеры не хранят состояние, их можно добавлять горизонтально. Отдельный небольшой процесс-потребитель раз в несколько секунд сворачивает журнал в историю по каждому тесту, и selector быстро находит нужные результаты. Распределённая схема дороже в эксплуатации, но её гораздо проще масштабировать и профилировать по памяти, чем, по выражению автора, «шаткий синглтон».
Работа заняла три недели у одного инженера. Год назад, по оценке автора, на неё ушло бы ближе к кварталу, около тринадцати недель. Подбор размера журнала и числа воркеров Claude провёл по большей части сам, и с тех пор сервис стабилен.
Что автор сделал бы иначе
Число задач CI растёт экспоненциально по двум причинам: у каждого инженера становится больше агентов, а автоматическое одобрение PR становится изощрённее. Меняется и форма PR: Claude предпочитает делать их мельче и дробнее, и это ещё один аргумент против прогона всех тестов на каждом PR. Агенты пушат ночью и в выходные, поэтому нижний уровень активности вырос. Но нагрузка по-прежнему идёт всплесками, ведь значительную часть PR всё ещё ведут и одобряют люди.
Автор ожидает, что горизонтально масштабируемый отбор тестов станет отраслевым стандартом: команды с агентами производят и больше PR, и больше тестов. Его советы короткие. Инструментировать сервисы так, чтобы они служили Claude глазами и ушами: так он находит и чинит проблемы шаг за шагом намного быстрее, чем люди вручную. В первую очередь проверять, что задач CI на выходе столько же, сколько на входе. С самого начала держать состояние вне процесса. Не запускать критичный сервис единственным экземпляром, если нельзя измерить его самого и любые canary-изменения.
Понятие «переусложнения», считает он, понемногу уходит, по крайней мере планка сильно поднялась: если позволяет бюджет, уже в v0 можно закладывать масштаб в 10-20 раз больше ожидаемого. Строите вы сами или покупаете, совет один: «исходите из того, что в пределах двух кварталов ваша архитектура окажется под 25-кратной нагрузкой».
Дальше
Сооснователь Anthropic хочет рубильник с проверкой
«Мы бросаем кости с огромными рисками». Джек Кларк, один из семи основателей Anthropic, зовёт законодателей обязать лаборатории иметь рубильник, который сможет проверить третья сторона.
Читайте также
- Anthropic за пять месяцев съехала с git на свою Scion
- Claude разбирал ошибки 500 и вышел на злоупотребление
- Bun на Rust собрали агентами Claude, GitHub пошёл иначе
- Две сессии Claude Code съели 32% месячного счёта команды
- Claude переписал Messages API с Python на Rust
- Шесть правок от Claude Opus 4.6 попали в ядро Linux 7.3
Комментарии
Пока никто не написал. Будьте первым.
Присоединяйтесь к разговору
Войдите, чтобы оставить комментарий. Он появится после модерации.

