Claude Codeでアプリの「なんか遅い」を根絶する——プロファイリングと計測の実践

はじめに

「なんか最近APIが遅い気がする」——チームで誰かがこう言い出すと、だいたい返ってくるのは「調べてみます」という言葉で、そこから数週間放置されるのが現実だ。

これはエンジニアが怠惰なわけではない。計測コードを書いて、ログを分析して、修正して、という一連のサイクルに時間がかかりすぎるのが問題だ。忙しいスプリントの中で、緊急性が低い「遅さ」はどうしても後回しになる。

最初に断っておくと、この記事はClaude Code自体のトークン消費やコストを最適化する話ではない。あなたのアプリケーションを速くするために、Claude Codeをどう使うかという話だ。


「推測するな、計測せよ」をClaude Codeで実現する

パフォーマンスエンジニアリングの世界には古くから言われる鉄則がある。「推測するな、計測せよ」。頭では分かっていても、実際には「あのコードが怪しい気がする」という直感で動いてしまうケースが多い。

Claude Codeはこのサイクルを変える。APMツール(DatadogやNew Relicなど)を導入しなくても、ターミナルから直接パフォーマンスデータを収集できる。

プロンプトの例はこうなる。

このAPIエンドポイントのどこが遅いか調べたい。

performance.now()を使って「DB時間、外部API時間、ビジネスロジック時間」を JSON形式で記録する軽量計測コードを追加してください。 PERF_TRACE=1の環境変数でオン/オフ切り替えできるようにして。

このプロンプト1つで、計測コードの実装・ログ出力の設計・環境変数での制御まで一気に完成する。出力されたJSONログをClaudeに貼り返せば、「DB時間が全体の83%を占めている」「外部APIへの逐次呼び出しがボトルネック」といった分析が即座に返ってくる。

翻訳APIで起きた88%改善の話

DEV Communityに報告されている事例が分かりやすい。あるチームが翻訳APIのエンドポイントで6300ms/リクエストという遅延を抱えていた。メンバーの直感では「パース処理が重いのでは」という仮説だった。

Claude Codeで計測コードを挿入して実際に測ると、パース処理にかかった時間はわずか20ms以下。真犯人は別にいた。アライメントサービスへの9回の逐次HTTPコールだった。これをバッチAPIへの1回呼び出しに変更したところ、6300msが720msに落ちた。88%の改善だ。

「直感で推測した場所は関係なかった」という典型例。計測なしに最適化を始めていたら、全く関係のないパース処理を改修していたかもしれない。


バックエンドの最大の敵:N+1クエリをClaude Codeで根絶する

N+1クエリはバックエンドパフォーマンス問題の大きな原因の一つだが、コードレビューで見つけにくい。ループ内でDBクエリが発行されているパターンは、実行してみるまで分からないことが多い。

Claude Codeへの診断プロンプトはこう書ける。

このコードベースでN+1クエリパターンを全て洗い出してください。

ORMのループ内呼び出し、eager loading未設定箇所、 SELECT *で必要以上のカラムを取得している箇所を特定し、 ユーザー影響の大きい順に優先度をつけてリスト化してください。

同じくDEV Communityで報告されている事例では、ユーザーリスト取得後に各ユーザーの投稿を個別クエリで取得していたコードに対し、Claudeが`users.map内のawait`パターンを自動検出。`findMany({ include: { posts: true } })`の1クエリに統合するよう提案した。

同じくDEV Communityの別の事例ではWordPressのアーカイブページで47クエリ/ページが発生していたものを5クエリまで削減できている。Claude Codeは「どのクエリが冗長か」を説明しながら修正コードを生成するため、修正の意図が分かる状態でコードをレビューできる点も大きい。


メモリリーク・非同期最適化・その他のボトルネック

N+1クエリ以外にも、バックエンドには見つけにくいボトルネックが潜んでいる。

メモリリークの診断では、次のようなプロンプトが使える。

このコードベースでメモリリークの原因になりそうな箇所を全て特定して。

- リクエストハンドラーで追加したイベントリスナーの未削除 - 大オブジェクトをキャプチャするクロージャー - 制限なく増加するキャッシュ(サイズ上限なしのMap/Object) リスクの高い順にリストアップして。

非同期処理では、逐次`await`をまとめて`Promise.all`に変換できる箇所の自動検出も得意だ。「シンプルなAPIエンドポイントはp95 200ms以下、複雑な処理は1000ms以下」という基準をプロンプトに渡すことで、Claudeがその基準から外れそうな箇所を優先的にフラグを立てるよう誘導できる。

なお、フロントエンドのバンドルサイズ最適化(moment.jsをdate-fnsへ置き換えるなど)も同様のアプローチで対応可能だが、本記事のメインはバックエンドの話だ。フロントエンドに課題を抱えている場合は別途取り組んでほしい。


CLAUDE.mdで「書きながら気づく」仕組みを作る

ここまで紹介したのは、問題が起きてから診断するアプローチだ。もう一つ、予防の仕組みとして機能するのがCLAUDE.mdへのパフォーマンス警告ルールの定義だ。

# CLAUDE.md(パフォーマンス警告ルール)

<h2>Performance Review Rules</h2> When writing or reviewing code, always flag: - DB queries inside loops (N+1 risk) - Missing index on new foreign key columns - Synchronous operations that could run in parallel - Large payload responses without pagination

これをCLAUDE.mdに書いておくと、コードを変更するたびにClaudeが自動的に「この変更はDBクエリをループ内に含んでいる」「このカラム追加にはインデックスが必要かもしれない」と警告を出すようになる。CIパイプラインに組み込むのとは違い、日常のコーディング中にリアルタイムで気づける。

「直した後で気づく」から「書きながら気づく」へのシフトだ。チームに「パフォーマンスへの感度」を埋め込む手段として、CLAUDE.mdは意外と効く。


EMが作るべき「計測文化」とClaude Codeの役割

EMとして現場を見ていると、Claude Codeが変えるのは個人の作業速度だけではないと実感する。

「あそこが遅い気がする」という属人的な直感ベースの判断が、計測データを根拠にした議論に変わる。翻訳APIの事例で見たように、推測した場所が外れることは珍しくない。計測コードをClaudeに生成させることで、誰でも数値を持って議論できるようになる。

計測コードの実装・ログ解析にかかっていた時間が削減されると、エンジニアが向き合うべき判断——「このAPIは多少遅くても許容範囲か」「今スプリントでやるべき改善はどれか」——に集中できる。Claude Codeにできるのはボトルネックの特定と修正案の提示まで。ビジネス優先度を踏まえた判断は、人間のマネージャーやエンジニアが担う部分だ。

N+1クエリ診断のプロンプトで「ユーザー影響の大きい順にリスト化して」と指定したのと同じように、「ユーザー影響度 × 実装コスト」の観点でClaudeに優先順位を出力させることもできる。何から直すかを議論する材料を短時間で用意できる。


まとめ

パフォーマンス問題が後回しになるのは、計測のコストが高すぎるからだ。Claude Codeはそのコストを下げる。

時間があれば、直近で「なんか遅い」と感じているエンドポイントに`performance.now()`の計測コードをClaudeに生成させてみてほしい。5分で終わる。N+1診断プロンプトも主要なORMコードに投げてみると、10分で候補が出る。CLAUDE.mdへの警告ルール追加は5分もかからない。

推測ベースでは永遠に終わらない最適化も、計測ベースに切り替えた瞬間から打ち手が見えてくる。

コメント

タイトルとURLをコピーしました