SLO / Error Budget — Parky
Parky の API / Mobile / Web に対する Service Level Objective (SLO) と error budget の定義・運用ルール。 2026-04-28 初版。観測性配線 (Sentry/OTel/CAE) の本格運用と同時に開始する。 2026-04-30 改訂 (監査 M-3): 立ち上げ期と本格運用期で 段階的目標 を導入。
設計方針
- 目的: ユーザー影響の継続観測と「いつリリースを止めるべきか」を客観的に決める基準。
- 対象:
api.parky.co.jp(Workers BFF) を一次対象。Mobile / Web ポータルは Phase 2 で追加。 - 計測ソース: Cloudflare Analytics Engine (CAE) + Sentry + Workers Observability。Logpush → R2 を 30 日 retention で raw データ保管。
- 窓: 28 日ローリング (4 週)。週次レビューで burn rate を確認する。
- error budget:
(1 - SLO%) × 28 日のリクエスト総数の許容失敗数。 - alert 方針: burn rate × 14.4 (1h で 24h 分消費) と × 6 (6h で 1日分消費) の二段アラート。
段階的目標の考え方 (Phase 1 / Phase 2)
監査 (2026-04-29) は本来「5xx error rate < 0.1% / P99 < 500ms」(= 99.9% / P99) を要求。 ただし Parky は 2026-03 末開始・1 人開発・Phase 1 (MAU 1万 + IMP 100万) の立ち上げ段階で、 インフラと観測性が安定する前から 99.9% を契約してしまうと、健全な実験速度が損なわれる (error budget が常時枯渇 → freeze 連発 → 出荷不能)。
そのため SLO は 段階的に引き上げる。
| Phase | 期間目安 | 可用性 | レイテンシ | 採用根拠 |
|---|---|---|---|---|
| Phase 1 (立ち上げ) | 〜MAU 1万到達 (2026-06〜2026-12 想定) | 99.5% (5xx < 0.5%) | p95 < 500ms | 1 人開発 / Cloudflare Free〜Pro / 観測整備中。実験速度を確保しつつユーザー影響を一定以下に保つ。 |
| Phase 2 (本格運用) | MAU 1万到達後、または Phase 2 (ARR 1億) 入り | 99.9% (5xx < 0.1%) | p99 < 500ms | 監査要求準拠。Cloudflare Pro+ Health Checks、Sentry quota 拡張、オンコール rota 整備が前提。 |
Phase 移行の判定: 直近 4 週連続で Phase 2 値 (99.9% / p99 < 500ms) を達成し、 かつ次の運用要件が満たされた時点で Phase 2 SLO を契約として宣言する。
- Cloudflare Health Checks (Pro 以上, 1 分粒度) 稼働
- Sentry burn rate 二段アラート (14.4× / 6×) 稼働
- 週次 SLO レビューが 4 週以上継続
- オンコール rota またはそれに類する 1 次受け体制が文書化済
Phase 1 中は監査要求 (99.9%) を 観測目標 (informational) として CAE で並走計測し、 Phase 2 移行の判断材料に使う (= 実力が先、契約が後)。
API SLO (Tier 0 — Workers BFF)
Phase 1 (現行・契約値)
| 指標 | 目標値 | 計測 | error budget (28 日) |
|---|---|---|---|
| 可用性 (success rate) | 99.5% | CAE: 5xx を除く 2xx/3xx/4xx の割合 | 0.5% (例: 100 万 req/月 なら 5,000 req まで) |
| レイテンシ p95 | < 500ms | CAE: status < 500 のみで集計 | p95 が 500ms を超えた時間の割合 ≤ 5% |
| レイテンシ p99 | < 1500ms | CAE: 同上 | 同上 ≤ 5% |
| エラー率 | < 0.5% | Sentry + CAE 5xx | 0.5% を 28 日連続で超過したら freeze |
Phase 2 (将来契約値・現在は観測目標)
| 指標 | 目標値 | 計測 | error budget (28 日) |
|---|---|---|---|
| 可用性 (success rate) | 99.9% | CAE: 5xx を除く 2xx/3xx/4xx の割合 | 0.1% (例: 100 万 req/月 なら 1,000 req まで) |
| レイテンシ p95 | < 300ms | CAE: status < 500 のみで集計 | p95 が 300ms を超えた時間の割合 ≤ 5% |
| レイテンシ p99 | < 500ms | CAE: 同上 | 同上 ≤ 5% |
| エラー率 | < 0.1% | Sentry + CAE 5xx | 0.1% を 28 日連続で超過したら freeze |
除外 (SLI から除く)
- 4xx クライアントエラー全般 (
401/403/404/409/422/429) — クライアント由来 - 計画メンテナンス時間中の 5xx (事前 announce + Discord 通知必須)
- 上流 (Supabase / Cloudflare 自身) の同時刻インシデント中 (Cloudflare Status / Supabase Status で確認)
Mobile SLO (Phase 2)
| 指標 | 目標値 | 計測 |
|---|---|---|
| crash-free sessions | ≥ 99.5% | Sentry Flutter |
| cold start p95 | < 2.5s | Firebase Performance Monitoring (要設定) |
| 検索 RPC p95 | < 300ms | CAE で endpoint 別 |
| OTA バージョン採用率 7 日 | ≥ 80% | App Store / Play Store consoles |
Web Portal SLO (Phase 2)
| 指標 | 目標値 |
|---|---|
| LCP p75 | < 2.5s (CrUX 月次) |
| CLS p75 | < 0.1 |
| JS error rate | < 1% of pageviews (Sentry browser SDK) |
Error Budget 運用ルール
状態判定
budget_total = (1 - SLO_target) × total_requests_28d
budget_remaining = budget_total - errors_consumed_28d
burn_rate_1h = errors_last_1h / (budget_total / (28 × 24)) # 1h 想定消費
burn_rate_6h = errors_last_6h / (budget_total / (28 × 4)) # 6h 想定消費
| 状態 | 条件 | アクション |
|---|---|---|
| 健康 (green) | budget_remaining > 50% | 通常開発 |
| 注意 (yellow) | budget_remaining 25-50% | 高リスク変更を要レビュー |
| 危険 (orange) | budget_remaining 10-25% | new feature freeze、信頼性改善のみ |
| 枯渇 (red) | budget_remaining < 10% | deploy freeze、postmortem 必須 |
Burn rate アラート (Phase 1 — 99.5% 想定)
SLO target = 0.995 → 許容エラー率 = 0.005。
| 条件 | 意味 | error rate しきい値 | 通知先 |
|---|---|---|---|
| burn_rate_1h × 14.4 | 1 時間で 1 日分消費 (fast burn) | 5xx rate > 7.2% (= 0.005 × 14.4) | Discord #p0-alerts (P1) |
| burn_rate_6h × 6 | 6 時間で 1 日分消費 (slow burn) | 5xx rate > 3.0% (= 0.005 × 6) | Discord #p0-alerts (P2) |
| budget < 25% | budget 危険 | — | Discord #p1-ops (Daily summary) |
Burn rate アラート (Phase 2 — 99.9% 想定)
SLO target = 0.999 → 許容エラー率 = 0.001。
| 条件 | 意味 | error rate しきい値 | 通知先 |
|---|---|---|---|
| burn_rate_1h × 14.4 | 1 時間で 1 日分消費 (fast burn) | 5xx rate > 1.44% (= 0.001 × 14.4) | Discord #p0-alerts (P0/P1) |
| burn_rate_6h × 6 | 6 時間で 1 日分消費 (slow burn) | 5xx rate > 0.6% (= 0.001 × 6) | Discord #p0-alerts (P2) |
| budget < 25% | budget 危険 | — | Discord #p1-ops (Daily summary) |
Phase 2 のしきい値は sentry-alert-rules.md R-02 の
failure_rate() > 0.0144と一致 (= 99.9% target × 14.4×)。 Phase 1 中は同 rule を dev/prod の自然 5xx 率では発火しない 安全網として併用し、 Phase 1 専用の> 0.072rule を別途登録する (M-04 manual checklist)。
週次レビュー (毎週月曜)
- 28 日 budget 残量
- 当週の SEV1/2 件数 + RCA 進捗
- 翌週の planned change リスク評価
- 直近 4 週の SLO trend (改善 / 悪化)
- Phase 2 観測目標 (99.9% / p99 < 500ms) の達成状況 ← Phase 1 中の追加項目
アクションランブック (5xx 急増時)
burn rate alert (Discord #p0-alerts) が発火したら、以下を順に実行する。
詳細トリアージは incident-response.md §トリアージ を参照。
Step 1 — 5 分以内: 一次トリアージ
- Discord alert の embed から 影響範囲 (api/admin/owner/marketing/home) と 5xx 率 を確認
- Cloudflare Workers Observability で
parky-api-prodの Logs/Metrics タブを開く wrangler tail --config wrangler.<worker>.toml --env prodで直近のエラーパターンを確認 (4 split worker のうち該当を選ぶ — 例: 5xx burst の channel が判別済ならwrangler.public.toml等)cd parky/api && npx wrangler tail --config wrangler.public.toml --env prod --format pretty | head -100- synthetic-healthcheck.md の
/healthz失敗有無を確認 (= 全停止か部分障害か切り分け)
Step 2 — 15 分以内: 上流確認 + 初動
- 上流ステータス確認:
- Cloudflare Status
- Supabase Status
- 上流障害なら SLI から除外して観測継続のみ (deploy freeze は不要)
- 直前 deploy の特定:
直近 1 時間以内に deploy があれば rollback を最優先 (deployment-rollback.md)gh run list --workflow deploy-api-prod.yml --limit 5 - error の主因特定 (Sentry):
- Sentry
parky-apiプロジェクトの Issues タブで直近 1h を確認 - 同一 error が 80% 以上を占めるなら原因コード特定 → hotfix
- 散発なら infra 起因の可能性 (Supabase connection pool / R2 / KV)
- Sentry
Step 3 — 1 時間以内: 緩和か rollback 判断
| 状況 | アクション |
|---|---|
| 直前 deploy が原因 | rollback (deployment-rollback.md) — 議論せず即実行 |
| 上流 (Supabase/CF) 障害 | 上流復旧待ち + status page 監視 + ユーザー告知判断 |
| 既知 bug の負荷増幅 | rate limit / circuit breaker を一時的に強める (api/src/middleware/rate-limit.ts) |
| 原因不明 + budget red | deploy freeze 宣言 (#p1-ops) + tech-lead 召集 |
Step 4 — 24 時間以内: 事後
- SEV1/2 ならポストモーテム作成 (postmortem-template.md)
- 本 doc の SLO 値 / burn rate しきい値が現実に合っているか週次レビューで再評価
- 関連 alert rule (sentry-alert-rules.md) の感度調整
- error budget が枯渇 (red) した場合は postmortem の AI として 信頼性改善タスクを次週以降に必ず計上する
実装 TODO
Phase 0 (即日)
- Sentry org 作成 + Workers/Flutter project 作成
- Sentry DSN を
wrangler secret put SENTRY_DSNで dev/prod 投入 - Honeycomb 無料アカウント + OTLP endpoint 投入
- Cloudflare Health Checks for
/healthz(60s 間隔, Discord alert) — synthetic-healthcheck.md 本格化
Phase 1 (1 週間)
- CAE で SLO 集計 SQL を確立 (analytics-engine.md に追記)
- 週次 cron で error budget 残量を Discord に投稿
- burn rate alert (Phase 1: 7.2% / 3.0%) を Sentry rule で配線 — sentry-alert-rules.md
- Phase 2 観測目標 (99.9% / p99) の並走計測を CAE で開始
- 本 doc の SLO 値を 1 ヶ月運用後に再校正
Phase 2 (MAU 1万到達後)
- Phase 2 SLO (99.9% / p99 < 500ms) を契約値として正式採用
- burn rate alert を Phase 2 値 (1.44% / 0.6%) に切り替え
- Mobile crash-free + cold start を Sentry/Firebase で計測開始
- Web Portal LCP/CLS を Sentry browser SDK で計測開始
- Status page 公開 (オプション、
parky.statuspage.io等) - オンコール rota 文書化 (incident-response.md TODO 反映)
参照
- docs/ops/incident-response.md — インシデント対応 (5xx 急増時のトリアージ詳細)
- docs/ops/sentry-alert-rules.md — burn rate alert (R-02) など Sentry 側の rule 定義
- docs/ops/synthetic-healthcheck.md —
/healthz外部監視 (worker 全停止検知) - docs/ops/sentry-setup.md — Sentry 設定状況
- docs/ops/opentelemetry-setup.md — OTel 配線
- docs/ops/analytics-engine.md — CAE 集計 (SLO SQL の置き場)
- docs/ops/notification-strategy.md — severity / channel SSoT
- docs/ops/postmortem-template.md — ポストモーテム標準
- docs/ops/deployment-rollback.md — rollback 手順
- Google SRE Workbook ch.5: Alerting on SLOs — burn rate 設計の元ネタ