B2B SaaSのOn Callを「人を起こさない」方向に育てる話
はじめに
B2B SaaSでOn Callを始めると、かなりの確率でこうなります。
- 最初は「とりあえず全部Slack通知で様子見よう」から始まる
- そのうち夜間・休日にもスマホが鳴り始める
- 半年くらいすると「これは人間がやる仕事じゃないのでは?」という空気になる
On Callそのものよりも、「アラート疲れ」「バーンアウト」のほうが先に限界を迎えると思います。
この記事では、On Callを「維持する」ために、どうやって『人を起こさない方向』に運用を改善し、自動化投資の優先順位をつけていくかを整理します。
この記事で分かること
- B2B SaaSのOn Callでアラート疲れが起きやすい理由
- 「人を起こす条件」を継続的に引き上げるための基本設計
- Runbook・自動復旧・Feature Flagなどへの投資をどう並べるか
- 成長ステージ別(立ち上げ / 拡大期 / 安定運用期)のOn Call改善の方針
技術的なHow-toというより、現場でOn Callを運用し続けるための考え方と小技の話が中心です。
1. なぜOn Callはすぐに「つらい仕組み」になるのか
最初に、なぜ放っておくとOn Callが破綻するのかを整理しておきます。
B2B SaaS特有のプレッシャー
B2B SaaSのOn Callは、B2Cとは少し空気が違います。
- 少数の大口顧客の業務が止まると、売上インパクトが極端に大きい
- 契約でSLAや違約金が決まっていることが多い
- 営業・CSへの説明が必要(=技術対応と並行で説明責任が走る)
その結果、「ちょっと怪しい挙動」でも過剰に敏感になりがちです。SLO設計が甘いと、ほぼすべての異常値が「誰かを起こす理由」になってしまいます。
典型的な失敗パターン
On Call初期によくあるのが、この流れです。
- 「とりあえず障害は全部検知したい」
- 監視ツールのデフォルトテンプレでアラートを山ほど生やす
- 夜間にちょこちょこ鳴り始める
- そのうち誰もアラート内容をちゃんと読まなくなる
ここで厄介なのは、技術的には「誤検知」ではないアラートも多いことです。
- たしかにエラー率は上がっている
- レイテンシもSLOギリギリで推移している
- でも実際には顧客影響が限定的か、少し様子見してから対応しても間に合う
それでも「将来大きな障害になったら怖い」という理由だけで、人が起こされ続けます。
この状態から抜け出すには、最初から完璧なアラート設計を目指すのではなく、 「On Callを運用しながら徐々に人を起こさない方向に押し戻していく」 という前提で設計する必要があります。
2. 「人を起こす条件」を言語化する
アラート疲れを防ぐうえで、一番効くのはここです。
そもそも、どういう条件を満たしたら「人を起こす」のか?
これをチームで明文化しておかないと、判断が毎回場当たり的になります。
ざっくり3レベルで考える
細かい分類の前に、まずは次の3レベルだけ決めてしまいます。
- 起こさない(翌営業日でよい)
- 業務時間内なら対応するが、夜間・休日は起こさない
- いつでも起こす(夜間・休日含む)
それぞれの代表的な条件を、B2B SaaSを前提に少しだけ整理してみます。
1. 起こさない
- 自動でリトライされる一時的なエラー(しかもユーザー非同期処理)
- 値がしきい値を少し超えただけで、ビジネス指標にまだ跳ねていないもの
- 冗長構成の片系障害で、容量的にも余裕がある状態
条件:
- エラーバジェットの消費速度が許容範囲内
- 代替手段があり、業務停止にはつながらない
2. 業務時間内のみ対応
- 一部顧客のバッチ処理が遅延している
- 特定機能だけエラー率が高いが、クリティカルな業務ではない
条件:
- 翌営業開始までに解消されれば、SLA的にも実務的にも許容される
- CSが顧客に「今対応中です」と説明できれば致命傷にはならない
3. いつでも起こす
- 複数の大口顧客の主要業務が止まっている
- 契約上のSLAを明確に割り込みそう
- データ欠損や不整合が発生し、後からの修復コストが極端に高い
条件:
- 数時間放置すると、顧客の業務・会社の売上に直接の大きなインパクト
- CS/営業に説明しても許容されない不具合
ここまで決めたうえで、個々のアラートルールを「どのレベルに属するのか?」に紐づけていきます。
実際のアラートルールへの落とし込み
抽象的なポリシーだけだと運用に乗りません。
たとえばSLOベースのアラートを見るなら、ざっくりこんな考え方になります。(疑似コードレベルのイメージです)
alerts:
# レベル3: いつでも起こす
- name: critical_slo_burn
condition: >-
error_budget_burn_rate(1h) > 10 # 1時間で10時間分のエラーバジェットを消費
notify: pager_duty
# レベル2: 業務時間内のみ
- name: warn_slo_burn
condition: >-
error_budget_burn_rate(6h) > 4 # やや高めの消費ペース
notify: slack
# レベル1: 起こさない(可視化のみ)
- name: slow_slo_burn
condition: >-
error_budget_burn_rate(24h) > 1 # じわじわ悪化
notify: dashboard_only
ここで大事なのは、「pager_dutyを叩く前に、Slackだけで済ませられるか?」を常に検討することです。
3. アラートレビューの仕組みを作る
「人を起こさないOn Call」の鍵は、アラートルールを放置しないことです。
障害対応の後始末に「アラートの反省会」を必ず入れる
ポストモーテムのテンプレートのどこかに、次の2行を入れてしまうのがおすすめです。
- 今回のインシデントで鳴ったアラートは、事前に防ぎたかったか?
- もしもう一度同じことが起きるなら、どのタイミングで人を起こしたいか?
この2つに「はい」と答えたものだけ、アラートルールを強化します。
逆に、
- 「正直ここまで敏感でなくてもよかった」
- 「これは業務時間内で間に合う」
となったものは、
- しきい値を上げる
- 夜間通知だけオフにする
- アラートではなくダッシュボードの指標に格下げする
といった調整の候補にします。
定期レビューで「人を起こす閾値」を少しずつ引き上げる
もう少し仕組みとして回すなら、月1などでアラート疲れレビューを置いてしまうのが現実的です。
題材はシンプルでよくて、たとえば次のようなものです。
- 先月の夜間アラート件数の推移
- 夜間に起きたアラートのうち、翌営業日でも問題なかったもののリスト
この場でやりたいのは、完璧な分析ではなく、
- 「これはもう起こさなくてよくない?」
- 「この種の障害は、自動復旧に寄せられそう」
といったざっくりした判断を、ちゃんとチームの合意として残すことです。
ドキュメントは簡素でよくて、Google DocsでもNotionでも「アラート疲れボード」みたいな1枚を作っておくだけでもOKです。
4. 自動化投資の優先順位をどう決めるか
「人を起こさない」方向に倒していくには、どこかで自動化にコストをかける必要があります。
ただ、自動化候補はいくらでも出てくるので、優先順位をつけないと際限がありません。
投資判断の軸を3つに絞る
ざっくりですが、次の3軸で考えると整理しやすくなります。
- 夜間・休日に人を起こしている頻度
- 対応にかかる時間・ストレス
- 自動化したときの技術的な難易度
理想は、
- 頻度が高く
- 対応も面倒で
- でも自動化は比較的シンプル
というところから潰していくことです。
Runbook → 手動自動化 → 完全自動化
いきなりフル自動化は難しいことが多いので、段階を分けて考えます。
1. Runbookを書く
まずは 「起きた人が迷わず対応できる」状態 にします。
- チェックすべきダッシュボード
- よくある原因候補
- 一時的な回避策(例: 特定機能の一時停止、トラフィックシフトなど)
これを書くだけでも、「起きてから復旧までのストレス」はかなり減ります。
2. 手動自動化(ワンコマンド化)
次に、Runbookに書いてある手順のうち、「毎回ほぼ同じことをする」部分をスクリプト化します。
仮に、よくあるパターンが次のようなものだとします。
- 特定のジョブがハングする
- 再実行すると直ることが多い
最初の素朴なRunbookはこうです。
1. ジョブ管理画面で対象ジョブを特定
2. 状態を確認
3. 問題なさそうなら手動でリトライを実行
ここから、CLIやAPIがあればこういったスクリプトに寄せていけます。
# 仮の例: ジョブを特定してリトライするワンライナー
jobctl retry --name nightly-report --only-stuck
これをRunbookから呼び出して、
「アラートが鳴ったらまずこれを実行して、その結果を見てから次の判断をする」
という運用に寄せていきます。
3. 完全自動化
最後に、手動自動化で問題なく回っているパターンをアラートトリガーから直接呼ぶようにします。
- しきい値を少し保守的にする
- 自動復旧が一定回数失敗したら人を起こす
という形にしておくと、「自動復旧で直るうちは人を起こさない」状態に近づけられます。
Feature Flagへの投資はどこで効くか
B2B SaaSだと、個別顧客向けの機能が壊れて全体を巻き込む、という状況もあります。
ここで効いてくるのがFeature Flagです。
- 問題のある機能・顧客だけ一時的にオフにする
- コア機能は生かしたまま、影響範囲を絞る
Feature Flagは「オン/オフのフラグそのもの」よりも、
- 「このフラグを落としても業務に耐えられるか?」
- 「CS/営業がその状態をどう説明するか?」
まで含めて設計しないと、On Callの現場ではあまり使えません。
なので、自動化投資としての優先度をつけるなら、
- コア機能ではないが、障害頻度が高い機能
- 特定顧客だけに有効な実験的機能
あたりから、 「落としてもビジネス的にまだ安全」 なものに狙いを絞るのが現実的です。
5. 成長ステージ別のOn Call改善プラン
最後に、プロダクトの成長ステージごとに「どこまでやるか」をざっくり分けておきます。
1. 立ち上げ期: まずは「起こしてもよい」仕組みを作る
この段階では、正直アラート疲れよりも「障害に気づけない」ほうが怖いです。
やるべきことはシンプルで、
- コア機能のSLOを決める
- 致命的な障害を検知するアラートを少数に絞って作る
- PagerDuty等で最低限のOn Callローテーションを回す
- ポストモーテムと簡易Runbookを書く習慣をつける
この段階で、無理に全部自動化しようとはしないほうが現実的です。
2. 拡大期: 「人を起こす条件」を徐々に引き上げる
顧客数が増え、インシデントも増え始めたタイミングで、
- アラートレビューを定期イベントにする
- 夜間アラートの数をメトリクスとして追う
- 頻度の高い障害からRunbook → 自動化に乗せる
というサイクルを回し始めます。
このフェーズで 「On Callをやるのは一部の好き者だけ」になっていないか を確認しておくとよいです。属人化すると、その人が燃え尽きた時点で体制ごと崩れます。
3. 安定運用期: 「人を起こさないこと」自体をKPIにする
ある程度プロダクトが安定し、チーム規模も増えてきたら、
- 「夜間に人を起こした回数」をチームのKPIに含める
- 逆に「自動復旧で解決したインシデント数」も可視化する
といった形で、「人を起こさないほうが評価される」雰囲気を作っていきます。
そうすると、自然と次のような動きが生まれます。
- 新機能リリース時に、Feature FlagやRunbookまでセットで用意される
- 監視・アラートの変更PRに、SLOやエラーバジェットの観点からの議論が乗る
もちろん、ここまで行き着くのは簡単ではないのですが、「理想像」としてチームで共有しておくだけでも判断がぶれにくくなります。
6. うまくいかないときの違和感メモ
最後に、実際にやってみると引っかかりがちなポイントをいくつか挙げておきます。
-
「顧客影響があるかどうか」が判断しづらい
- B2Bだと、どの機能がどの業務に効いているかがブラックボックス化しがちです。
- CSや営業と一緒に「機能 x 業務」のマッピングをざっくり作るだけでも、優先度付けはかなり楽になります。
-
SLOが曖昧なままアラートだけ増えていく
- あるあるですが、「遅い/重い」の感覚値だけでアラートを作ると、誰も消せなくなります。
- 完璧でなくていいので、主要なAPIやユースケースだけでもSLOを定義しておくと、その後の議論の土台になります。
-
自動化した結果、かえって障害の全貌が見えづらくなる
- 自動復旧が走ると、「何が起きて、何をしたのか」がログに残っていないケースがあります。
- 自動復旧スクリプトには、できるだけ丁寧なログを吐かせておくと、あとからポストモーテムを書くときに助かります。
このあたりは、正直まだ「これが正解」というものはなく、各社・各プロダクトで試行錯誤している領域だと思います。
まとめ
この記事で伝えたかったのは、
On Callは一度作って終わりの仕組みではなく、アラートを減らしながら育てていくプロセスそのものが本体だ
ということです。
明日から一つだけやるとしたら、
- 直近1ヶ月の夜間アラートを洗い出して、
- 「本当に人を起こすべきだったか?」をチームで30分話してみる
ところから始めてみると良いのではと思います。
余力があれば、その中で一番頻度が高くて単純なものを選んで、簡単なRunbookかワンコマンドスクリプトを書く。そこまでできると、「人を起こさないOn Call」に一歩近づいているはずです。
Discussion