Debugging Production Issues at 2 AM: A Survival Guide

March 2026 · 20 min read · 4,730 wordsAdvanced

午前2時の生産問題のデバッグ: サバイバルガイド

午前2時17分。PagerDuty。 アラートは支払いサービスのエラーレートが95%であると告げている。847件の影響を受けた取引。あなたの心臓がドキリとする。 あなたは瞬時に目が覚める—生産インシデントからしか得られない特有のアドレナリンの種類が体内を巡る。あなたの電話はすでにロック解除され、ラップトップが起動し、コーヒーメーカーが筋肉の記憶だけで動き始める。これはあなたのキャリアの847ページ目だ。はい、あなたはそれを追跡している。200ページ目を越えたとき、これはあなたの職業生活の決定的な部分になることを認識し、非道な時間に起こされることがあるなら、そのデータを持っているほうがいいと数え始めた。 支払いサービス。もちろん、支払いサービスだ。常に支払いサービスか、認証レイヤーか、誰かが「ただのシンプルなラッパー」のように誓ったマイクロサービスが、ここ3年でインフラストラクチャの半分にとっての重要な依存関係に変わったのだ。 あなたには、マネージャーに2回目のページが送信されるまでにおそらく90秒しかない。サポートチャンネルに顧客が押し寄せるまでにおそらく3分。C-suiteの誰かが目を覚まし、Slackで質問をし始めるまでにおそらく5分。時間は刻々と迫り、あなたの手は動いていて、あなたの脳は数百回のこれらのインシデントで作成したメンタルチェックリストを既に走らせている。 これはあなたの初めてのロデオではない。しかし、午前2時の生産デバッグについて誰も教えてくれないことは、決して簡単にはならないということだ。ただ早くなるだけだ。より良いツールを構築する。愚かなミスを減らす。直感を信じるようになりつつも、すべてを疑問視する。実際に壊れているものと、見た目で壊れているものの違いを見抜く第六感を養う。そして最も重要なのは、10分のインシデントと4時間のインシデントの違いは、しばしばあなたの応答の最初の60秒にかかっているということを学ぶ。 このガイドは、ページ番号1の前に誰かが自分に教えてくれたらよかったことすべてだ。

最初の60秒:あなたの仕事がそれに依存しているかのようにトリアージを行う

どんな生産インシデントの最初の1分は、純粋な混乱管理だ。あなたの脳はまだ起動していなくて、おそらくズボンも履いていない状態で、これが数分で解決するか数時間かを決定する重要な決定をしなければならない。 私が毎回実行する手順は次の通りだ: すぐにページを確認する。 「最初に調査する」を待ってはいけない。確認してほしい。これがエスカレーションチェーンを停止させ、あなたのチームに誰かが対応していることを示す。調査をする前に「ちょっと確認するだけ」と言って、複数の人がページされてしまったインシデントを見てきた。30秒の調査があなたのシフトバックに眠っている可能性のある人を失わせる。 インシデント応答ダッシュボードを開く。 アプリケーションでもなく、ログでもなく。あなたのダッシュボード。システムの健康状態を一目で示すもの。私にとって、それはエラーレート、レイテンシパーセント、データベース接続プール、キューの深さ、そしてすべての重要なサービスにおけるCPU/メモリを示すカスタムGrafanaボードである。私は5秒以内に爆風半径を見ることができる。 まだ問題が続いているか確認。 これは明白に思えるが、アラートが発火する30秒前に解決された問題でページされたことがある。モニタリングシステムには遅延がある。アラートの閾値には評価ウィンドウがある。時には問題はすでに解決されていて、展開の元に戻す作業やサービスを再起動し始める前にそれを知っておかなければならない。 顧客への影響を評価。 理論的な影響ではなく、実際の影響だ。現在、何人のユーザーが影響を受けているか? トラフィックの100%か5%か? 一つの地域、一つの顧客セグメント、一つの機能に限定されているのか? これがあなたの応答の緊急性を決定し、さらに多くの人を起こす必要があるかどうかを決める。 この特定のインシデント—午前2時17分の支払いサービス—では、私のダッシュボードは8秒で私が知る必要のあるすべてを教えてくれた。エラーレート:94.7%。影響を受けたリクエスト:過去5分間で847件。地理的分布:グローバル。顧客セグメント:すべて。支払いプロバイダーAPIのレイテンシ:通常。データベース接続:正常。問題は上流でも下流でもなかった。私たちだった。 その時、私は長い夜になることを知った。

プレッシャーの下で実際に機能するデバッグ手法

誰もが落ち着いてカフェインを摂取し、午後2時に開発環境で作業しているときにはデバッグの手法を持っている。しかし、半分寝ていて、CEOがインシデントチャネルにいて、ダウンタイムの一秒一秒が実際の金銭を失うときには、それを持っている人は非常に少ない。 私が使うのは「爆風半径から根本原因へ」というアプローチだ。これは特別ではないが、脳が60%のキャパシティで動いているときに機能する。 根本原因ではなく、爆風半径から始める。 これは直感に反する。すべての本能はすぐに根本原因を見つけようとする。しかし、その本能に抵抗する。最初に、何が壊れていて、何が壊れていないのかを正確に理解する。失敗の境界をマッピングする。これには二つの目的がある:健全なシステム内で誤った方向に進まないようにすること、そしてしばしば排除のプロセスによって根本原因に直接指定することだ。 支払いサービスのインシデントについて、私は90秒を使って爆風半径をマッピングした: - 支払い開始:失敗 - 支払いステータスチェック:失敗 - 支払いウェブフック:失敗 - 返金処理:正常動作 - 管理者支払いクエリ:正常動作 そのパターンは重要なことを示していた:読取操作は正常だが、書込操作が失敗している。それはデータベースの問題、キューの問題、または権限の問題である。30の可能性の中で3つ。 コードの流れではなく、データの流れに従う。 午前2時にデバッグをしているとき、コードを追跡する時間はない。データに従え。支払いリクエストはどこからシステムに入るのか? 次はどこへ行くのか? どこで失敗するのか? 私は私たちの分散トレーシングを引き上げ(持っていて良かった)、単一のリクエストがシステムを通じて流れるのを見た。それは認証を経て、レート制限を経て、バリデーションを経て、データベースに書き込もうとした瞬間に死んだ。 データベース。そこにあった。 まず退屈なことをチェックする。 ディスクスペース。メモリ。接続プール。ファイル記述子。証明書の有効期限。DNS。退屈なことのほうが、巧妙なバグが生産システムをパンクさせるよりも多い。午前2時に、誰かのcronジョブがディスクを満たしているためにページされたことがある。証明書が切れたためにページされたこともある。誰かがDNS TTLを変更し、伝播を待たなかったためにページされたこともある。 この場合、データベース接続プールは100%だった。すべての接続が使用中だった。しかし、なぜ? トラフィックは急増していなかった。クエリのパターンは変わっていなかった。何かが接続を開いたままにしていた。 監視を信頼するが、すべてを検証する。 モニタリングシステムは嘘をつく。悪意はない—それらはただのソフトウェアで、ソフトウェアにはバグがある。健康なサービスが完全にダウンしているという報告を受けたことがある。存在しないエラーを報告されたこともある。いつも重要なパスを手動で確認する。支払いシステムでは、テスト用クレジットカードとcurlコマンドを準備している。10秒で全ての支払いフローを検証できる。 テスト支払いを実行した。30秒間ハングしてタイムアウトした。モニタリングは嘘をついていなかった。我々は本当にダウンしていた。

データベース接続についてすべてを教えてくれたインシデント

ページ番号312についてお話ししましょう。3月の火曜日の午前3時47分で、データベース接続管理についての考え方を永遠に変えました。 私たちはフラッシュセールを実施中だった。トラフィックは高かったが前例のないものではなく—より大きなスパイクの処理をしていた。しかし突然、データベースに触れるすべてのサービスがタイムアウトを起こし始めた。接続プールが枯渇した。典型的な症状。明白な答え:接続プールサイズを拡大すること。 そこで私たちはそれを実行した。2倍にした。それから3倍にした。問題は悪化した。 その時、解決策が問題を悪化させることがあることを学んだ。我々がプールに追加した接続は、既に過負荷のデータベースでクエリを実行しようとする他の接続だった。我々は自分たちをDDoSしていた。 実際の問題は? 開発者が5000万行のテーブルで完全なテーブルスキャンを実行する新機能を追加したことだ。インデックスなし。クエリは完了するのに45秒かかった。そのコードパスに到達した各リクエストは45秒間データベース接続を保持した。十分なトラフィックがあれば、接続プールは接続数が足りないのではなく、すべての接続がその恐ろしいクエリが完了するのを待っている間に枯渇した。 解決策は、より多くの接続ではなく、そのクエリを終了し、インデックスを追加し、アプリケーションレベルでクエリタイムアウトを実装することだった。 そのインシデントは私に3つのことを教えてくれた: 接続プールの枯渇は症状であって病気ではない。 それを見たとき、すぐにプールを拡大しないでください。接続が解放されていない理由を尋ねてください。クエリが遅いのか? デッドロックがあるのか? 何かがトランザクションをオープンしたままにしているのか? 接続プールは、他のどこかに問題があることを伝えている。 クエリタイムアウトはすべての場所に存在すべきだ。 すべてのデータベースクエリにはタイムアウトが必要です。すべてのHTTPリクエストにはタイムアウトが必要です。すべてのキュー操作にはタイムアウトが必要です。タイムアウトはオプションではない。それらは劣化したサービスと完全にダウンしたサービスとの違いです。何かがうまくいかないとき、タイムアウトはブロックされた接続を溜め込むのではなく、すぐに失敗することを可能にします。 接続プールの利用状況を監視するだけでは不十分だ。 接続のライフタイムを監視する必要があります。平均接続保持時間はどのくらいか? P99は? 平均接続ライフタイムが突然50msから5秒に跳ね上がった場合、たとえプールがまだ枯渇していなくても、あなたに問題があるのです。それがあなたの早期警告システムです。 午前2時17分の支払いサービスのインシデントに戻ります。接続ライフタイムを確認しました。平均:8秒。P99:
C

Written by the Cod-AI Team

Our editorial team specializes in software development and programming. We research, test, and write in-depth guides to help you work smarter with the right tools.

Share This Article

Twitter LinkedIn Reddit HN

Related Tools

Base64 Encode & Decode — Free Online Tool COD-AI vs Cursor vs GitHub Copilot — AI Code Tool Comparison SQL Formatter & Beautifier — Free Online Tool

Related Articles

10 Online Developer Tools That Save Hours Every Week — cod-ai.com CSS Beautifier vs Minifier: When to Use Which Code Review Checklist: What I Look for After 10 Years of PRs \u2014 COD-AI.com

Put this into practice

Try Our Free Tools →