Script
Cold Open
シーン1 二十三時のSlack
十月十三日。二十三時。
秋雨の合間の、湿った夜だった。窓を、ほんの少しだけ開けると、外の空気が、夏のころより、ずっと、密度を持って、入ってくる。桜子は、入浴を終えて、パジャマの上に薄手のカーディガンを羽織り、ベッドの脇でスマホの充電ケーブルを差そうとしていた。
画面の上部に、通知が、立て続けに鳴った。
[ALERT] sakura-support api: 5xx surge (12 errors / 60s)
[ALERT] sakura-support api: 5xx surge continues (47 errors / 5min)
[ALERT] severity: P2胃のあたりが、ぎゅっと冷たくなった。
数秒後、鈴木からのDM。
@suzuki-kenichi: 桜子さん、もし起きてたら、参加してみない?
今夜は P2 だから、現場に立ち会うだけでいい。
オンコールは僕と山下さん。中村くんも入る予定
無理しないで、断ってくれていい桜子は、しばらく画面を見つめてから、返信を打った。
@mochizuki-sakurako: 起きてます。
いまから入ります。
よろしくお願いします送信ボタンを押すと、心臓が、自分が思っていたより速く打っていることに気づいた。
Part A
シーン2 ビデオ通話の中の三人

Google Meet のリンクを開く。
画面の左上に、鈴木。背景は、彼の自宅のリビングだろう、薄暗く、本棚の影が見える。中央に、遥。落ち着いた色のTシャツ姿で、すでにエディタとログ画面を並べている。右上に、翔太。Tシャツ姿、すでに目が冴えている。
桜子のカメラが映ると、鈴木が、いつもの穏やかな声色のまま、言った。
「桜子さん、夜分にありがとう。よろしくね」
「お、おはようございます。じゃない、ええと、こんばんは」
Meet の画面で、遥が、ほんの少しだけ笑った。
「いまから、状況、整理する。桜子さんは、記録役、お願いできる?」
「記録、ですか」
「うん。社内wikiの障害対応ページに、新しいタイムラインを切ってほしい。あとは、ここで誰が何を提案して、何を試して、何が分かったかを、五分おきくらいに事実だけ書いていく。それが、桜子さんの今夜の仕事」
「……はい、やります」
桜子は、wiki の incidents/ の下に、新しいページを作った。
# Incident: 2022-10-13 23:10 sakura-support api 5xx surge
- severity: P2
- status: investigating
- on-call: 鈴木健一 (lead) / 山下遥 / 中村翔太
- recorder: 望月桜子
## Timeline (JST)手が、少し震えた。
シーン3 5xxの正体を追う
遥が、Meet の画面共有で、ログ集約ツールを開いた。
「いま見てるのは、サクラサポートの api ロール、過去30分。/api/v1/inquiries/{id} で 500、平均で毎秒0.8件。10分前から、徐々に増えて、いまピーク」
翔太が、すかさず仮説を並べる。
「直近のデプロイは、僕の #118 と、桜子さんの #103。#118 は、JOINに変えただけだから、5xxを引く理由は、たぶん、ない。#103 は、Redisキャッシュ。Redisが落ちてたら、説明はつく」
鈴木が、
「Redis、生きてる?」
「生きてます。レイテンシも普通」
「桜子さんのフラグは、いま、どう?」
桜子は、自分のwiki画面と、featureflags.yaml の現在状態を、別タブで開いた。
「unreadcacheenabled: true、有効です」
「OK。すぐに切れる選択肢がある、ってことだけ、頭に置いとこう」
遥が、ログをさらに絞った。
「5xxの中身、トレースバックを見ると、外部に投げてる『顧客企業マスタ取得API』からのレスポンスがタイムアウトしてる」
「それ、うちのじゃない外部API?」
「うん。外部の、子会社が運用してる方。先月から契約変えたところ」
Meet の画面で、四人とも、一瞬、口を閉じた。
四人分の、息遣いだけが、マイク越しに、低く、つながっていた。鈴木のキーボードを叩く音。遥のマウスのスクロール音。翔太の、小さく舌打ちしたあとの、慌てた咳払い。それぞれの自宅の、それぞれの夜の音が、薄く、Meetの画面の中で、混ざっていた。
沈黙は、たぶん、十秒もなかった。けれど、その十秒は、桜子の身体の中では、もっと、ずっと長かった。
(誰も、何も、言わない時間って、こんなに、こわいんだ)
桜子は、手のひらが、また、わずかに、湿ったのを、感じた。沈黙の中で、桜子の指は、知らず知らず、wikiの編集画面のテキストエリアの上で、待機の姿勢を、続けていた。書くことが、思いつかない時間でも、書く準備の手だけは、机の上に、置いておく。それだけが、いま、桜子に出来ることだった。
桜子は、聞こえてくる事実だけを、wiki に書き続けた。
- 23:10 5xx surge detected, severity P2 raised
- 23:14 on-call assembled (鈴木/山下/中村/望月)
- 23:18 5xx の主体は /api/v1/inquiries/{id}
- 23:22 直近デプロイ: #118 (JOIN), #103 (Redis cache)
- 23:24 Redis health OK, latency normal
- 23:25 unread_cache_enabled: true (有効、切替可能)
- 23:27 5xx のトレース: 外部「顧客企業マスタ取得API」のタイムアウトPart B
シーン4 タイムラインを書く
「先月、契約変えてから、向こうの安定度の話、ちゃんと出てなかったよね」
遥が、画面を見たまま、言った。
「うん。SLA、確認しよう」
鈴木が、別のタブで、契約資料のページを開く。SLAは99.5%の表記。月単位で換算すると、月に何時間かは落ちうる、という前提だ。
翔太が、
「いま、向こうの公開ステータスページ、見てます。あ、十五分前に、向こう側で、incident を立ててます。タイムアウト多発、調査中、って」
桜子は、書く。
- 23:32 契約資料: 外部APIのSLAは99.5% (月単位換算で残時間あり)
- 23:34 外部側ステータスページに incident あり
(23:17 開始, "increased latency, investigating")Meet の中で、鈴木が、しばらく考えてから、言った。
「ここで、二つ、選択肢がある」
「一つ。直近デプロイの何かが、結果として、外部APIのタイムアウトを誘発してる、と仮定して、#118 か #103 を戻す」
「もう一つ。原因は外部側、と仮定して、向こうの復旧を待つ。我々側は、5xxを返さないように、フォールバック処理(顧客企業情報なしで詳細表示)を一時的に出す」
遥が、
「#118 は、JOIN追加だけ。外部APIを叩く頻度は、変えてない。だから、戻しても、たぶん、5xxは止まらない」
「#103 は、Redisキャッシュ。これを切ると、countunread が全件ロードに戻って、別の負荷が出るだけ。5xxの直接の原因とは、つながらない」
「結論として、戻すべき直近デプロイは、ないと思う」
鈴木が、
「同意。じゃあ、フォールバックの一時挿入と、向こうの復旧を待つ、で行こう。フォールバックの実装、翔太くん、できる?」
「やります。フィーチャーフラグで、/api/v1/inquiries/{id} で外部API失敗時に、顧客企業欄をnullで返すモード。十分でPR出します」
シーン5 戻すべきか、踏み込むべきか
その間、桜子は、ログ件数を時系列でグラフにして、Meet にペタッと貼り付けた。
時間帯 5xx 件数
23:10-23:15 12
23:15-23:20 28
23:20-23:25 47
23:25-23:30 52
23:30-23:35 55 (ほぼ横ばい)「五分前から、ほぼ、横ばいです」
遥が、
「そう。たぶん、外部API側がもう悪化してない。いま、こっちが踏み込んで戻すより、待つほうが、合ってる」
鈴木が、
「桜子さん、その横ばいの数字、すごく助かる」
「あ、はい」
桜子は、自分の頬が、急に熱くなったのを、画面の暗さの中で、どうにか、隠した。
ほんの、ひと拍だけ、桜子は、自分の手元の wiki ページを、見下ろした。
切り抜き、コピー、貼り付け。たったそれだけの動作で、五分おきに増えていった、二十数行の事実の連なり。判断はしていない。仮説も立てていない。コードも書いていない。書いたのは、ただの、時刻と、誰の発言と、何が分かったか、の、ログ。
(書いた、だけだ)
でも、その「ただの、ログ」が、いま、いま、こっちが踏み込まないほうが、合ってる という、四人の判断の、台座になっていた。
桜子は、四月の初出社の朝、駅までの坂道で、みんな、もう仕事してる と思って、自分は何もしていない、と感じたあの感覚を、ふっと、思い出した。
(記録は、何もしていない、ことじゃ、なかった)
その小さな書き換えが、桜子の中で、起きた。
翔太のフォールバックPR #125 が、その十分後に届いた。レビューは遥が即時、Approved。鈴木が Merged。デプロイは、十一分で完了。新しいリクエストから、5xxは止まり、フォールバックの200が返る。
二十三時五十分過ぎ。Meetの画面の中で、四人がほぼ同時に、息を吐いた。
- 23:48 フォールバックPR #125 デプロイ完了
- 23:49 5xx 停止、フォールバック200のみ
- 23:54 外部APIのステータスページ: latency restored
- 23:58 フォールバックOFFのPR #126 マージ予定 (明朝)
- 00:02 状況: stable桜子は、wiki のステータスを、investigating から mitigated に書き換えた。
Part C
シーン6 復旧と、フラグの記憶
深夜零時を回ったところで、鈴木が、
「お疲れさま。今夜は、ここで一旦、解散しよう。明日の朝、postmortem ミーティング、十時から。桜子さん、タイムライン、そのままドラフトに使います」
「はい、ありがとうございます」
「無理しないで。明日の朝は、ミーティングに間に合えば、それでいいから」
全員が「お疲れさまです」と返して、Meet が静かに切れた。
画面の中で、桜子だけが、まだ少し、ぼーっとしていた。
ふと、Slackで、遥からDMが来ていた。
@yamashita-haruka: 今日、桜子さんのフラグは、結局、触らなかったね。
でも、「すぐ切れる選択肢がある」って状態は、判断を軽くした。
使わなかったけど、あって、よかった桜子は、しばらくその文字を眺めてから、
@mochizuki-sakurako: ありがとうございます。
記録、ぜんぶ、ちゃんと、残せてたか、不安ですと返した。
遥の返事は、すぐ来た。
@yamashita-haruka: 大丈夫。読みやすかったよ。
横ばいの数字、あれ、PMが翌朝、お客さんに説明するとき、
ほぼそのまま使えるかたちになってる桜子は、メモ帳を開きかけて、いま、深夜だと気づいた。
明日、書こう。
ベッドの上で、ノートPCを閉じた。エアコンのかすかな音と、外を走るタクシーの音が、秋の夜の中で、混ざっていた。
Ending
シーン7 翌朝のpostmortem下書き
翌朝。
桜子は、起きるのに、いつもの倍くらい、時間がかかった。アラームを止めてから、ベッドの上で、しばらく、天井を、見ていた。身体の重さは、寝不足というより、昨夜の三時間で、自分の中の何かを、ひと回り、使い切ったあとの、独特の、重さだった。
駅までの道は、いつもと同じ景色のはずだった。けれど、街路樹の下を歩く自分の足音が、いつもより、ほんの少しだけ、遅く、聞こえた。改札を抜けるときの、Suicaのピッ、という音さえ、頭の奥のほうで、半拍、遅れて、響いた。
オフィスに着いた桜子は、自分の机に、鈴木が置いてくれたペットボトルのお茶を、見つけた。冷蔵庫から出して時間が経っているらしく、ボトルの肩のあたりに、結露の粒が、ゆっくり、流れた跡を残している。封のされていない、ただの「ありがとう」のしるしだった。
桜子は、お茶のキャップを開けて、ひとくち、飲んだ。お茶の温度は、もう、室温に近かった。けれど、その薄い温度が、いまの桜子の喉には、ちょうど、合っていた。
会議室「桜」のドアを開けると、鈴木と遥と翔太が、もう、いた。三人とも、顔色が、桜子と同じくらい、薄かった。翔太は、コーヒーを、両手で、抱えるように持っていた。遥のキーボードの横には、紙コップが、二杯、並んでいた。
「お疲れさま」
鈴木が、いつもより、半トーンだけ、低い声で、言った。
「お疲れさまです」
桜子も、半トーンだけ、低く、返した。
誰も、まだ、本題には、入らなかった。三人とも、ほんの少しだけ、椅子に深く腰を下ろし直して、自分の身体の、置きどころを、整えていた。桜子は、自分の身体の重さが、自分だけのものではないことを、その三人の身体の重さの中に、置きどころを、見つけた。
十時から始まったpostmortem ミーティングは、淡々と進んだ。鈴木が「桜子さんの夜のタイムライン、そのままベースで書いていきます」と言って、見慣れた障害報告テンプレに、夜の事実が流し込まれていく。
## 障害報告: 2022-10-13 sakura-support api 5xx surge (P2)
- 発生日時: 2022-10-13 23:10 JST 検知
- 検知日時: 2022-10-13 23:10 JST (アラート自動発火)
- 影響範囲: お問い合わせ詳細API /api/v1/inquiries/{id} の一部に 5xx
実利用への影響: お問い合わせ詳細を開けないユーザー、約120件 (推定)
業務影響: サポート担当の対応が、約45分間、ブロック
- 事象: 詳細API の 5xx が、最大で毎秒0.8件、約45分継続
- 一次原因: 外部「顧客企業マスタ取得API」のタイムアウト多発 (外部側 incident)
- 暫定対応: 外部API失敗時のフォールバック (#125) を導入し 200 で返す
- 恒久対応:
- 外部APIの呼び出しに、明示的なタイムアウトとリトライ上限を入れる (#127 起票)
- 外部API失敗時のフォールバックを、フラグでデフォルトON運用に変更検討 (#128 起票)
- 再発防止:
- 外部依存の状態確認手順を Runbook に追加
(公開ステータスページのURL、SLA、過去のincident頻度)
- 月次で、外部依存の incident 履歴をレビューする会を設定 (鈴木)
- 学び:
- 直近デプロイがあったとき、つい戻したくなるが、
原因が外部側にあるかどうかを先に切り分けると、判断が速くなる
- 「使わなかった停止手段」も、判断の幅として価値がある桜子は、再発防止の欄に、自分の名前で、一行だけ、提案を書いた。
- (望月) 外部依存ごとに、Runbook に
"公開ステータスページURL / SLA / 過去incident頻度" の欄を必ず置く鈴木が、それを読んで、軽くうなずいた。
「これ、いいね。やろう」
ミーティング後、桜子は、自分のメモ帳を開いた。
2022/10/14 新人日記
- 初・本番障害(P2)
- 自分の役割は「記録」
- 五分おきに事実を書く。仮説と判断は、書く人ではなく、
チームで分担する
- 「すぐ切れる選択肢がある」だけで、判断は軽くなる
- 直近デプロイより、外部依存の状態を、まず見ること
- 戻すか、待つか、踏み込むか。三択を並べてから決めるペンを置いて、桜子は、窓の外を見た。
秋分を過ぎた空に、雲の切れ間から、細い光が差し込んでいた。
たぶん、何ヶ月かしたら、また、夜のアラートが鳴る。次は、自分が、もう少しだけ、踏み込んだ役割で出るかもしれない。記録から、調査へ。調査から、判断へ。
(運用は、夜にも、ある)
その当たり前を、桜子は、初めて、自分の身体の側から、知った。
お問い合わせ詳細を開けなかった、推定百二十人の顔は、桜子には見えなかった。けれど、その百二十回分の「あれ、開かない」を、深夜の四人が、引き受けた。
明日からの仕事は、その百二十人のうちの誰かが、また、安心してお問い合わせを開けるための続きだ。
ミーティングのあと、桜子は、トイレで、洗面台の鏡の前に、しばらく、立っていた。
目の下に、薄い、青い影が、ふたつ、ある。普段の自分の顔とは、別の人の顔のようで、桜子は、しばらく、その顔と、自分との距離を、測れずにいた。蛇口をひねって、冷たい水を、両手のひらに、ためた。それを、目元の下に、軽く、当てる。
冷たかった。
いつもの「冷たい」とは、また、別の冷たさだった。睡眠不足の皮膚に、秋の水道水の温度は、いっそう、深く、染みてくる。
顔を上げて、もう一度、鏡を、見る。
目の下の影は、消えなかった。けれど、目そのものは、たぶん、昨日の朝よりも、ほんの少しだけ、奥の方が、しっかりしているように、見えた。
桜子は、ハンドペーパーで、顔を、軽く、押さえた。
席に戻る通路で、翔太と、すれ違った。翔太も、目の下に、桜子と同じくらい、青い影を、ふたつ、持っていた。お互い、目だけで、軽く、うなずきあった。言葉は、いらなかった。同じ夜を、同じMeetの画面の中で、起きていた人どうしの、無言の挨拶だった。
席に戻ると、桜子は、ペットボトルのお茶の、残りを、もうひと口、飲んだ。室温の、薄い温度。今度は、喉の奥のほうまで、ゆっくり、降りていった。
