テスト影響分析がCI負荷25倍で限界に — Anthropicの作り直し
半年でCIジョブが25倍になったAnthropicが、テスト選択サービスを3回の応急処置のあと水平分割に作り替えた経緯と、設計の要点をまとめます。
AnthropicはCIのテスト選択サービスを、6か月でCIジョブが25倍に増えたことを受けて作り直しました。2026年9月14日に公開された同社のエンジニアリング記事によると、応急処置を3回重ねて持った期間は70日、29日、1日未満でした。最後は単一プロセスをやめ、結果の取り込みを水平に増やせる構成へ移っています。
エージェントがコードを書き、レビューまで進める開発では、CIが次の詰まり所になります。教訓は、いつか来る負荷を前提に最初から設計することです。数字と失敗の順序が、その重さを具体的に見せています。
CIジョブ25倍の内訳 — コードを書くことがボトルネックでなくなった
前提は3つあります。Anthropicのエンジニアが1四半期に出荷するコード量は、2021〜2025年の平均の8倍。そのコードの80%をClaudeが書き、PRのレビューと承認にもClaudeが大きく関わっています。さらにコードベース全体のテスト数が10倍になる一方、エンジニアの増員はわずかでした。
この結果、6か月でCIジョブは25倍になりました。全テストが全PRで走るわけではないので、テスト数10倍との単純な掛け算にはなりません。
人が増えていないのに負荷だけが跳ねました。負荷の源は人数ではなく、1人あたりが回すエージェントの数です。
記事が示す規模感
コード出荷量
8倍
2021〜2025年の平均と比べた1四半期あたり
Claudeが書く割合
80%
出荷コードのうち
テスト数
10倍
コードベース全体
CIジョブ
25倍
6か月間
テスト影響分析は何を決めるサービスか
テスト影響分析(test impact analysis)は、変更ごとに「どのテストを走らせるか」を選ぶ仕組みです。全テストを全変更で回す運用は一定規模までは通りますが、CIの待ち時間・費用・信頼性が悪化していきます。Anthropicは、過去の成績とパッケージの関連度から実行テストを決める決定論的な(同じ入力なら同じテストを選ぶ)サービスを自前で持っています。
構成は2つの部品です。
- listener: すべてのCI実行のテスト結果を記録する
- selector: 結果の履歴を読み、開いているPRでどのテストを走らせるか決める
エージェントの側にも利点があります。人は無関係な失敗を見分けて読み飛ばせますが、エージェントは文脈と指示がないと迷います。選ばれた妥当なテストだけを渡せば、自分で検証して直す反復が回りやすくなります。
listenerが遅れると何が壊れるか
CIジョブが毎秒のように流れる環境では、listenerがPRキューに遅れ始めます。例えば、20分のlistener遅延で数万件のテスト更新がselectorに反映されません。起きることは次の3つです。
- 壊れた変更がマージされても、その失敗が履歴に入らず、他の人のテストが落ちて不要な調査が増える
- 依存先が不安定になると、不安定な失敗がマージを止める
- 直ったテストや新規のテストが、listenerが追いつくまで走らず、回帰を見逃すおそれがある
初期設計(v0)は単一プロセスでした。テストごとの履歴を持ち続けるため、結果を適用する書き手が1つ必要だったからです。この前提が水平分割を妨げていました。
3回の応急処置はなぜ短命だったか
2025年10月には負荷の兆候が出て、2日続けて障害の呼び出しを受けています。
応急処置3回と作り直し
- 2025年10月パッチ1 コア数を2倍に
マシンを大きくする最も簡単な対処です。持ったのは70日。担当が曖昧で、誰もインフラをもう1つ抱えたがらなかったためです。
- 2026年2月パッチ2 パッケージ単位で分割
結果の順序を保つ書き手は全体で1つではなく、パッケージごとに1つで足りると気づきました。各パッケージの状態をそれぞれのワーカーに分け、コードはClaudeが生成しています。持ったのは29日。
- 2026年3月パッチ3 毎日再起動
平日の午後にメモリ上限へ達するため再起動で凌ぎました。1日ももちません。再起動のたびに遅れが積み上がり、1時間以上遅れた日が何度もありました。
- 3回目のあとデータストアを挟んだ構成へ
Claudeの助言に沿い、単一プロセスの内部処理をインメモリのデータストアへ逃がしました。
パッチ3の時点で、バグは4件見つかっただけでした。メモリアロケーターの差し替えは効かず、負荷の高い単一プロセスにメモリプロファイリングをかけるリスクも取れませんでした。再起動は症状への対処で、原因には触れていません。
持ちこたえた期間が70日、29日、1日未満と縮んだのは、負荷が指数的に伸びるのに対し、3回の対処がどれも定数倍の余裕しか買えなかったからです。コア数の2倍化も、パッケージ分割も、再起動も、上限を一度押し上げるだけで、単一の書き手とメモリ常駐という構造は残ります。定数倍の余裕は、倍々に増える負荷の前では毎回短くなります。直すべきは余裕の大きさではなく、負荷に比例して増やせない構造のほうでした。
遅れの影響には限りがあります。listenerが拾えなかった結果があっても、CIが走らなかった、あるいは未検証のコードが本番に出た、という意味ではありません。selectorが古い履歴を使い、すでに不安定なテストや広範囲で落ちるテストを選びがちになった、という影響です。
作り直した構成 — 状態をプロセスの外に出す
新しい設計は、listenerのワーカーを状態なしにしたのが核です。
新しいデータの流れ
- 1
どのワーカーでも結果を受け取る
listenerのワーカーは、どのCI結果でも処理できます。メモリに何も持ち続けません。
- 2
ジャーナルへ追記する
結果はインメモリのデータストア上のジャーナルに追記され、ワーカーは次の結果へ進みます。
- 3
小さな消費プロセスが履歴にまとめる
別の小さなプロセスが数秒ごとにジャーナルをテスト単位の履歴へ集約します。
- 4
selectorが履歴を引く
selectorは集約された履歴から、対象のテストの結果をすばやく引けます。
運用費は上がりますが、不安定な単一プロセスよりずっとスケールとメモリ調査がしやすい構成です。作業は1人のエンジニアで3週間。1年前なら四半期近くかかった規模だったそうです。ジャーナルの大きさとワーカー数の調整はClaudeがほぼ自律的に行い、切り替え後は安定が続いています。切り替え前は毎日のようにバックログが積み上がっていましたが、調整後は平らになりました。
長期セッションで遅延を見張った使い方
パッチ2の時期に、元記事の筆者はClaude Tagの社内版で、このサービスの監視専用の長期セッションを立てています。listenerの遅れが5万ジョブを超えるとClaudeが通知し、前回の続きから次の手を相談する運用です。これが数か月続き、過去の経緯や文脈を毎回説明し直す必要がなかったと、筆者は評価しています。
Claudeは作り直しを何度も主張したものの、そのたびに別の応急処置に落ち着いた経緯も、筆者は隠していません。人の側が先送りを選んだ記録でもあります。
公開されているClaude Tagで近いことをするには
上の運用で使われたのは社内版で、5万ジョブという閾値で通知する仕組みも社内の構成です。公開ベータのClaude Tagには、定期チェックやアラート調査を頼む使い方が文書化されています。たとえば、アラートの流れ込むチャンネルで次のように頼む形です(ドキュメントの例に沿った形)。
@Claude every two hours, check the alerting dashboard against its last state. For anything new, post when it started, what changed around then, and what to look at first.この例は変化があったときだけ投稿するルーティンです。スレッドは固有のセッションに結び付き、サンドボックスは待機中に解放されても、スレッド自体は残り、返信で再開できます。監視系の接続先(Datadog、Sentry、PagerDutyなど)をチャンネルに追加しておくことが前提です。既知の誤報はチャンネルの指示欄に書いておくと、Claudeの確認から外せます。
導入の違いや費用管理は、Claude TagとClaude CodeのSlack連携の比較とClaude Tagの管理者設定で整理しています。登場時の位置づけはClaude Tagが登場にあります。
元記事の筆者が2025年10月に戻ってやり直すなら
元記事の最後は、そのときの振り返りです。
- 指数的な増加を見込む: エンジニア1人あたりのエージェント数と、PR承認の高度化で、CIジョブは指数的に増える。Claudeは小さく細かいPRを好むため、1日のジョブ数がさらに増える
- 負荷の床が上がる: エージェントは夜間や週末にもpushするが、人が主導して承認するPRも多いため、波は残る
- v0から10〜20倍を見込む: 作るか買うかによらず、2四半期以内に25倍の負荷が来る前提で設計する。予算が許す限り、過剰設計の許容範囲は広がっている
- サービスを計測可能にする: Claudeの目と耳として計装すると、Claudeが少しずつ直していける。特に、入ってくるCIジョブ数と出ていく数が一致するかを確認できるようにする
- 状態をプロセスの外へ: 重要なサービスを単一インスタンスで動かさない。計測とカナリア変更ができない限り避ける
増員は小さくても、レビューとCIの負荷は別の曲線で伸びます。応急処置の効き目は毎回短くなります。他のチームにとっても、早めに設計を変える判断材料になる経過です。
手元のCIに当てはめるときの見方
この記事はAnthropic社内の構成の話で、同じ数字が他の組織にそのまま当てはまるわけではありません。ただ、次の3点は規模を問わず点検できます。
| 点検項目 | 見るもの | 兆候 |
|---|---|---|
| 結果の取り込み遅延 | 見るもの入ってくるジョブ数と記録済みジョブ数の差 | 兆候差が日ごとに積み上がる |
| 単一の書き手 | 見るもの履歴更新を1プロセスが担っていないか | 兆候再起動で一時的に回復する |
| 古い履歴での選択 | 見るものテスト選択が参照する履歴の鮮度 | 兆候不安定なテストばかり選ばれる |
GitHub Actionsでエージェントを動かすワークフローの組み方はClaude CodeでGitHub Actionsのワークフローを作る手順に、サブエージェントの並列実行はClaude Code Sub-agents完全ガイドにまとめています。並列エージェントを増やす前に、テスト選択とCIの受け皿が追いつくかを見ておくと、負荷の跳ね方を読みやすくなります。