E 会計/ファイナンス・コスト効率 — Unit Economics × Cloud Run min-instances=0 × Pub/Sub ackDeadline × BigQuery パーティション剪定(メール配信基盤 Bad→Good)

2026-06-12 (Day 67) 金曜 E: 会計/ファイナンス・コスト効率 ★★★★☆ Unit Economics / Cloud Run v2 / Pub/Sub BigQuery パーティション剪定 / ROI 試算

概要

📊

Unit Economics でコスト構造を可視化する

「月額 $9,600 が高い」ではなく「1配信あたり $0.0004 のコストで $0.06 の GMV を生み出している」と Unit Economics に変換することで、削減余地とビジネスへの影響を定量的に判断できる。Unit Margin が 99.3%なら「コスト削減よりも配信数拡大の方が高インパクト」という議論も生まれる。

☁️

Cloud Run の min-instances=0 でアイドルコストを撲滅する

min_instance_count=4 + cpu_idle=false は常時4インスタンスが稼働し、バースト時間8.3%に対してアイドル時間91.7%にコストが発生する。min_instance_count=0 + cpu_idle=true でリクエスト処理時のみ課金され、アイドルコスト95%を削減できる。

🔁

Pub/Sub の再配信ループはコストを静かに膨張させる

デフォルトの ackDeadlineSeconds=10 で処理に20秒かかるメッセージは再配信ループに入り、実メッセージ数の 3.2倍が課金される。ackDeadlineSeconds=60 に延長するだけで月額 68.75%削減。0.5人日で $660/月の改善は ROI が最高の施策。

💰

ROI を CFO・CTO・エンジニアの言語に変換する

「8.5日でペイバック、年間 ROI 4,207%」という数字は CFO が拒否できない投資案件になる。施策を ROI 降順に並べ「どれから始めるか」を優先順位付きで提案することが、エンジニアリングリードとしての価値を示す最短ルート。

問題

ECサイト MOps チームの Cloud Run v2(配信 API)+ BigQuery(集計)+ Pub/Sub(トリガー) 基盤で、過去6ヶ月のインフラコストが 1.8倍に膨張(GMV 成長は 1.2倍)した。CFO から「コスト増加率がビジネス成長を上回っている」と指摘された。Unit Economics を軸にコスト構造を分解し、3ヶ月以内に Unit Cost を 40%削減する施策を立案・試算せよ。

現状コスト内訳(月額 $9,600)

リソース月額コスト月間配信量備考
Cloud Run v2(配信 API)$3,8402,400万通min-instances=4・CPU always-on
BigQuery(集計・分析クエリ)$2,880パーティション未設定・フルスキャン
Pub/Sub(メッセージング)$9602,400万メッセージackDeadline 10秒・再配信ループあり
Cloud Storage$720削除ポリシーなし
Artifact Registry$480世代管理なし・蓄積
Cloud Monitoring / Logging$720デフォルト設定・不要ログ多数
合計$9,6002,400万通/月

制約・前提条件

  • チーム: エンジニア2名(工数上限: 10人日)
  • 単価: エンジニア 6,000円/時間、1 USD = 150円
  • 配信品質(到達率・遅延)への影響ゼロが必須
  • 追加調査: Cloud Run は1日4バースト × 各30分のみ実行(残り22時間はアイドル)
  • BigQuery: 平均スキャン量 800GB/クエリ × 720回/月
  • Pub/Sub: 処理に平均20秒かかるため ackDeadline 10秒で再配信ループ発生(3.2倍課金)
期待する回答形式: Unit Economics 分解 + 施策別コスト試算(削減額)+ 優先順位付き実施計画 + ROI 試算 + リスクと対策

コスト構造 (Before) — 3つの設計上の問題

この GCP コスト構造には 3つの設計上の問題 が隠れています。
Bad コスト構造 — 91.7%がアイドル課金
# 問題①: Cloud Run min-instances=4 + CPU always-on
resource "google_cloud_run_v2_service" "delivery_api_bad" {
  template {
    scaling {
      min_instance_count = 4   # ← 常時4インスタンス稼働
      max_instance_count = 20
    }
    containers {
      resources {
        cpu_idle = false        # ← CPU always-on(アイドルでも課金)
      }
    }
  }
}
# 実行時間: 4回 × 30分 × 30日 = 60h/月(8.3%)
# アイドル時間: 720h - 60h = 660h/月(91.7%が無駄)
# コスト: $3,840/月 → 実質 $320/月分の稼働

# 問題②: BigQuery パーティション未設定でフルスキャン
SELECT campaign_id, SUM(revenue) AS total
FROM `project.mops_dataset.email_events`  # ← 800GB フルスキャン
WHERE created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY 1
# コスト: $5/TB × 800GB × 720回/月 = $2,880/月
# 7日分しか使わないのに 180日分をスキャン

# 問題③: Pub/Sub ackDeadline 10秒(デフォルト)
# メッセージ処理に20秒かかる → 10秒でタイムアウト → 再配信ループ
# 実メッセージ: 2,400万通
# 課金対象: 2,400万 × 3.2倍 = 7,680万メッセージ = $960/月
問題点サマリー(3点)
1Cloud Run アイドルコスト($3,840/月 の 91.7%が無駄) — min-instances=4 + cpu_idle=false で常時4インスタンスが稼働。バースト時間は8.3%しかなく、残り91.7%(660h/月)のアイドルコストが $3,520/月を無駄に消費。min_instance_count=0 + cpu_idle=true に変更することでリクエスト処理時のみ課金され $192/月まで削減可能
2BigQuery フルスキャン(必要データの 26倍をスキャン)created_at にパーティション設定なし。直近7日分(24GB)を取得するために 180日分(800GB)をスキャン。partition_by(event_date, 'date') + cluster_by を設定することで月額 97%削減($2,880 → $86.4)
3Pub/Sub 再配信ループ(3.2倍の課金) — デフォルトの ackDeadlineSeconds=10 で処理が間に合わず再配信。実メッセージ 2,400万通が 7,680万メッセージ課金になっている。ackDeadlineSeconds=60 に延長(0.5人日)で $660/月削減・工数対効果 ROI 最高

ヒント(段階的開示)

ヒント1 — 方向性
Unit Economics の視点では「1通あたりのインフラコストがどのリソースで主に発生しているか」を分解することが出発点。今回は Cloud Run のアイドルコスト(40%)と BigQuery のフルスキャンコスト(30%) が主因。「大きい順に攻める」原則で施策の ROI を計算し、工数対削減額が最大の施策を Phase 1 に置く。
ヒント2 — アプローチ
  • Cloud Run削減: min-instances=4 → min-instances=0 + cpu_idle=true。アイドルコスト $3,520/月 → $0。実行コストのみ約 $192/月
  • BigQuery削減: partition_by(event_date) 設定後、7日分スキャンに絞ると 800GB → 24GB(97%削減)= $2,793.6/月削減
  • Pub/Sub削減: ackDeadlineSeconds=60 に延長で再配信ループ解消。3.2倍課金 → 1.0倍 = $660/月削減
  • Unit Economics 再計算: 施策後の月額 $2,138 ÷ 2,400万通 = $0.0000891/通(77.7%削減)
ヒント3 — 試算の骨格
【Cloud Run: min-instances=0 試算】
現状: $3,840/月(91.7%アイドル)
改善後リクエスト課金:
  2,400万リクエスト × 0.1vCPU-s/リクエスト = 240万 vCPU-s
  240万 vCPU-s × $0.0000240 ≈ $192/月
削減: $3,648/月(95%削減)

【BigQuery パーティション試算】
現状: $5/TB × 800GB/回 × 720回/月 = $2,880/月
改善後: $5/TB × 24GB/回 × 720回 = $86.4/月
削減: $2,793.6/月(97%削減)

【Pub/Sub ackDeadline 試算】
現状: $960/月(3.2倍ループ)
改善後: $960 / 3.2 = $300/月
削減: $660/月

ROI 試算:
  実施コスト: 6.5人日 × 8h × 6,000円 = 312,000円
  月次削減: $7,462 × 150円 = 1,119,300円/月
  ペイバック: 312,000 / 1,119,300 = 8.5日

問題点分析(3点)

#問題点分類改善方法
1Cloud Run min-instances=4 + cpu_idle=false(アイドル91.7%)コストmin_instance_count=0 + cpu_idle=true + startup_cpu_boost=true
2BigQuery パーティション未設定(800GB フルスキャン)コスト/性能partition_by(event_date) + cluster_by([campaign_id, segment_id]) + 7日ルックバック
3Pub/Sub ackDeadlineSeconds=10(処理20秒で再配信ループ 3.2倍課金)コスト/信頼性ackDeadlineSeconds=60 + modifyAckDeadline で長時間処理に対応

コスト構造図 — Bad vs Good + Unit Economics 分解

Bad コスト構造($9,600/月) ① Cloud Run v2: $3,840/月(全体の40%) min-instances=4 + cpu_idle=false → 常時4インスタンス稼働 アイドル時間: 91.7%(660h/月)→ $3,520/月が無駄 バースト時間: 8.3%(60h/月)= 実質 $320/月分の稼働のみ タイムラインで表現: ████░░░░░░░░░░░░░░░░░░░░ ← 8%稼働・92%アイドル ② BigQuery: $2,880/月(全体の30%) パーティション未設定 → 毎回 800GB フルスキャン 必要データ: 7日分 = 約 24GB 実際にスキャン: 180日分 = 800GB(26倍の無駄スキャン) ③ Pub/Sub: $960/月(ackDeadline 10秒 → 再配信ループ) メッセージ処理に平均20秒かかる 10秒でタイムアウト → 再配信 → ループ = 3.2倍課金 実メッセージ 2,400万通 → 課金 7,680万メッセージ ④ Storage + Artifact + Monitoring: $1,920/月 ライフサイクルなし・世代管理なし・不要ログ全量収集 削除ポリシー設定だけで $360/月削減可能 Unit Cost: $0.0004/通(0.06円/通) コスト成長 1.8倍 vs GMV 成長 1.2倍 → Unit Cost 1.5倍悪化 CFO 警告: 「スケールするほど Unit Economics が悪化している」 Good コスト構造($2,138/月・77.7%削減) ① Cloud Run v2: $192/月($3,648/月削減・95%減) min_instance_count=0 + cpu_idle=true → リクエスト処理時のみ課金 startup_cpu_boost=true → コールドスタート高速化 コネクションプール再利用(グローバル変数でシングルトン初期化) タイムラインで表現: ████░░░░░░░░░░░░░░░░░░░░ ← アイドル $0・実行分のみ課金 ② BigQuery: $86.4/月($2,793.6/月削減・97%減) partition_by(event_date) + cluster_by([campaign_id, segment_id]) 7日ルックバック: 800GB → 24GB/クエリ(必要な 7日分のみスキャン) dbt incremental + insert_overwrite で差分パーティションのみ更新 ③ Pub/Sub: $300/月($660/月削減・68.75%減) ackDeadlineSeconds=60(処理時間 20秒の3倍の余裕) 再配信ループ解消: 3.2倍 → 1.0倍に正規化 modifyAckDeadline + 冪等性キーで長時間処理の重複配信を防止 ④ Storage + Artifact + Monitoring: $1,560/月($360削減) ライフサイクルポリシー + 最新5世代のみ保持 + DEBUGログ除外 Phase 2 で実施(ROI は低いが長期的な蓄積防止効果あり) Unit Cost: $0.0000891/通(77.7%削減) 年間削減額: $7,462 × 12 = $89,544(≈1,343万円) 年間 ROI: ($89,544 - $2,080) / $2,080 = 4,207% / ペイバック 8.5日 最適化

Unit Economics 分解 — 施策前後の比較

施策前 Unit Economics 月次コスト: $9,600/月 月間配信数: 2,400万通 Unit Cost: $0.0004/通 GMV/通: $0.06/通 Unit Margin: $0.0596/通(99.3%) コスト成長 1.8倍 vs GMV 成長 1.2倍 → Unit Cost 1.5倍悪化 77.7%削減 施策後 Unit Economics 月次コスト: $2,138/月($7,462削減) 月間配信数: 2,400万通(変化なし) Unit Cost: $0.0000891/通 GMV/通: $0.06/通(変化なし) Unit Margin: $0.0599/通(99.85%) 年間 ROI 4,207% / ペイバック 8.5日 / 工数 6.5人日

模範解答

【施策前の Unit Economics】

月次コスト:   $9,600
月間配信数:   2,400万通
Unit Cost:    $9,600 ÷ 24,000,000 = $0.0004/通(0.06円/通)

月次 GMV:     $1,440,000(1,440万ドル)
GMV/通:       $1,440,000 ÷ 24,000,000 = $0.06/通(9円/通)

Unit Margin:  $0.06 - $0.0004 = $0.0596/通
Margin Rate:  $0.0596 / $0.06 = 99.3%

【コスト構造の問題点】
  GMV は 1.2倍成長、コストは 1.8倍成長
  → コスト増加率がビジネス成長を 1.5倍上回っている
  → Unit Cost が 1.8倍/1.2倍 = 1.5倍に悪化

コスト比率の分解:
  Cloud Run:   $3,840 / $9,600 = 40% ← 最大・アイドルコストが主因
  BigQuery:    $2,880 / $9,600 = 30% ← 2番目・フルスキャンが主因
  Pub/Sub:     $960  / $9,600 = 10% ← 再配信ループが主因
  Storage:     $720  / $9,600 = 7.5%
  Monitoring:  $720  / $9,600 = 7.5%
  Artifact:    $480  / $9,600 = 5%

【施策後の Unit Economics(目標: Unit Cost 40%削減)】

月次コスト:   $2,138/月(77.7%削減 → 目標 40%削減を大幅超過)
Unit Cost:    $2,138 ÷ 24,000,000 = $0.0000891/通(77.7%削減)
Unit Margin:  $0.06 - $0.0000891 = $0.0599/通
Margin Rate:  99.85%(施策前 99.3% → 0.55pt 改善)
# terraform/cloud_run_delivery.tf

# Bad: min-instances=4 で CPU always-on(91.7%がアイドル)
resource "google_cloud_run_v2_service" "delivery_api_bad" {
  template {
    scaling {
      min_instance_count = 4   # ← 常時4インスタンス稼働・アイドルでも課金
      max_instance_count = 20
    }
    containers {
      resources {
        cpu_idle = false        # ← CPU always-on(リクエストなしでも課金)
      }
    }
  }
}

# Good: min-instances=0 + cpu_idle=true でアイドルコストを撲滅
resource "google_cloud_run_v2_service" "delivery_api_good" {
  name     = "mops-delivery-api"
  location = "asia-northeast1"

  template {
    scaling {
      min_instance_count = 0   # アイドル時はインスタンスゼロ(コスト $0)
      max_instance_count = 50  # バースト時に自動スケール
    }

    containers {
      image = "asia-northeast1-docker.pkg.dev/${var.project_id}/mops-images/delivery-api:latest"

      resources {
        limits = {
          cpu    = "2"
          memory = "1Gi"
        }
        cpu_idle          = true   # リクエスト処理時のみ CPU 課金(← 重要)
        startup_cpu_boost = true   # コールドスタート高速化(初回レイテンシ短縮)
      }
    }
  }
}

コールドスタート対策: コネクションプール再利用

# application/main.py
# コールドスタート対策: グローバル変数で接続プールを使い回す
# Cloud Run では同一インスタンスが複数リクエストを処理するため、
# リクエストごとに接続を張り直すのは最も多いアンチパターン

from google.cloud import bigquery
from google.cloud import pubsub_v1

# モジュールレベルで初期化(コールドスタート時のみ実行)
_bq_client: bigquery.Client | None = None
_publisher: pubsub_v1.PublisherClient | None = None


def get_bq_client() -> bigquery.Client:
    """シングルトンパターン: コールドスタート後は既存接続を再利用"""
    global _bq_client
    if _bq_client is None:
        _bq_client = bigquery.Client()  # 接続初期化は1回のみ
    return _bq_client


def get_publisher() -> pubsub_v1.PublisherClient:
    global _publisher
    if _publisher is None:
        _publisher = pubsub_v1.PublisherClient()
    return _publisher

削減試算

現状: $3,840/月(min-instances=4 × CPU always-on)
  - アイドル時間: 91.7%(660h/月)= $3,520 が無駄
  - 実行時間: 8.3%(60h/月)= $320 が実質稼働分

改善後(リクエスト課金のみ):
  - アイドルコスト: $0(min-instances=0)
  - 実行コスト:
    2,400万リクエスト × 0.1vCPU-s/リクエスト = 240万 vCPU-s
    240万 vCPU-s × $0.0000240/vCPU-s ≈ $192/月

削減額: $3,840 - $192 = $3,648/月(95%削減)
工数: 2人日
削減額/工数: $1,824/人日
-- Bad: パーティション未設定でフルスキャン(800GB/クエリ)
SELECT
  campaign_id,
  DATE(created_at)          AS event_date,
  COUNT(*)                  AS send_count,
  COUNTIF(opened)           AS open_count
FROM `project.mops_dataset.email_events`  -- フルスキャン確定!
WHERE created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY 1, 2


-- Good: パーティション + クラスタリング設定済みモデル(24GB/クエリ)
-- models/mart/mart_email_delivery_kpi.sql
{{
  config(
    materialized='incremental',
    incremental_strategy='insert_overwrite',
    partition_by={
      'field': 'event_date',
      'data_type': 'date',
      'granularity': 'day'
    },
    cluster_by=['campaign_id', 'segment_id'],  -- よく使うフィルタカラム
    on_schema_change='fail'
  )
}}

WITH events AS (
  SELECT
    DATE(created_at)                        AS event_date,  -- パーティションキー
    campaign_id,
    COALESCE(segment_id, 'unknown')         AS segment_id,  -- NULL 保護
    email_id,
    opened,
    clicked,
    converted,
    revenue_amount
  FROM {{ ref('stg_email_events') }}

  {% if is_incremental() %}
  -- パーティション剪定: 直近7日のみスキャン(800GB → 24GB)
  WHERE DATE(created_at) >= DATE_SUB(
    (SELECT MAX(event_date) FROM {{ this }}),
    INTERVAL 7 DAY
  )
  {% endif %}
)

SELECT
  event_date,
  campaign_id,
  segment_id,
  COUNT(DISTINCT email_id)                              AS send_count,
  COUNTIF(opened)                                       AS open_count,
  COUNTIF(clicked)                                      AS click_count,
  COUNTIF(converted)                                    AS conversion_count,
  COALESCE(SUM(revenue_amount), 0)                      AS total_revenue,

  -- KPI 指標(SAFE_DIVIDE でゼロ除算防止)
  SAFE_DIVIDE(COUNTIF(opened),    COUNT(DISTINCT email_id)) AS open_rate,
  SAFE_DIVIDE(COUNTIF(clicked),   COUNTIF(opened))          AS ctr,
  SAFE_DIVIDE(COUNTIF(converted), COUNTIF(clicked))         AS cvr,

  CURRENT_TIMESTAMP() AS _loaded_at
FROM events
GROUP BY event_date, campaign_id, segment_id

削減試算

現状: $5/TB × 800GB/クエリ × 720回/月 = $2,880/月

改善後(パーティション剪定: 7日分のみスキャン):
  7日分スキャン: 800GB × (7/180) ≈ 31GB → 実績値 24GB/クエリ(97%削減)
  改善後コスト: $5/TB × 24GB/クエリ × 720回/月 = $86.4/月

削減額: $2,880 - $86.4 = $2,793.6/月(97%削減)
工数: 3人日
削減額/工数: $931/人日
"""Pub/Sub ackDeadline 延長 + modifyAckDeadline リース管理パターン"""
import threading
from google.cloud import pubsub_v1

# Terraform で subscription を管理する場合:
# resource "google_pubsub_subscription" "delivery_sub" {
#   ack_deadline_seconds       = 60   # 20秒処理 → 60秒(3倍の余裕)
#   message_retention_duration = "86400s"
#   retry_policy {
#     minimum_backoff = "10s"
#     maximum_backoff = "600s"
#   }
# }

ACK_DEADLINE_SECONDS: int = 60   # 名前付き定数(マジックナンバー禁止)
EXTEND_INTERVAL_SECONDS: int = 30  # 期限の半分で延長


def process_message_with_lease_management(
    message: pubsub_v1.types.ReceivedMessage,
    subscriber: pubsub_v1.SubscriberClient,
    subscription_path: str,
) -> None:
    """
    長時間処理でも確実に ack するリース管理パターン。

    処理時間が ackDeadline を超える可能性がある場合は
    modifyAckDeadline で延長する。
    """
    stop_event = threading.Event()

    def extend_ack_deadline() -> None:
        """バックグラウンドスレッドで定期的に ackDeadline を延長する"""
        while not stop_event.wait(timeout=EXTEND_INTERVAL_SECONDS):
            subscriber.modify_ack_deadline(
                request={
                    "subscription": subscription_path,
                    "ack_ids": [message.ack_id],
                    "ack_deadline_seconds": ACK_DEADLINE_SECONDS,
                }
            )

    extender = threading.Thread(target=extend_ack_deadline, daemon=True)
    extender.start()

    try:
        # メイン処理(平均20秒かかる配信処理)
        _deliver_emails(message.data)  # type: ignore[name-defined]
        subscriber.acknowledge(
            request={
                "subscription": subscription_path,
                "ack_ids": [message.ack_id],
            }
        )
    finally:
        stop_event.set()  # 延長スレッドを停止

削減試算

現状: 3.2倍再配信ループ
  実メッセージ: 2,400万通
  課金対象: 2,400万 × 3.2 = 7,680万メッセージ
  月額: $960/月

改善後(ackDeadline=60秒で再配信なし):
  課金対象: 2,400万メッセージ(1.0倍)
  月額: $960 / 3.2 = $300/月

削減額: $660/月(68.75%削減)
工数: 0.5人日
削減額/工数: $1,320/人日 ← ROI 最高(Phase 1 に先着手)

施策別 ROI サマリー(優先順位順)

施策削減額/月工数削減額/人日優先度Phase
Pub/Sub ackDeadline 延長$6600.5人日$1,320★★★★★Phase 1
Cloud Run min-instances=0$3,6482人日$1,824★★★★★Phase 1
BigQuery パーティション設定$2,7943人日$931★★★★☆Phase 2
Monitoring ログフィルタ$3601人日$360★★★☆☆Phase 2
合計$7,4626.5人日$1,148(平均)

ROI 試算(全ステークホルダー向け)

【実施コスト】
6.5人日 × 8時間 × 6,000円/時間 = 312,000円(≈ $2,080)

【月次削減額】
$7,462/月 × 150円/$  = 1,119,300円/月

【ペイバック期間】
312,000円 ÷ 1,119,300円/月 = 0.279ヶ月 ≈ 8.5日

【年間 ROI】
年間削減額: $7,462 × 12 = $89,544(≈ 1,343万円)
年間 ROI:   ($89,544 - $2,080) / $2,080 = 4,207%

【ステークホルダー別の伝え方】
  CFO 向け:  「実施コスト $2,080 で年間 $89,544 の削減。ROI 4,207%。
              リスクフリーレートの 400倍以上の投資効果。」

  CTO 向け:  「6.5人日(約1.5スプリント)で月額 77.7%削減。
              ペイバック 8.5日。エンジニア2名で完遂可能。」

  エンジニア向け: 「ackDeadline を 10秒→60秒に変えるだけ(0.5人日)で
                  月 $660 削減。Terraform 1行変更で完了。」

【目標達成確認】
目標: Unit Cost 40%削減
実績: Unit Cost 77.7%削減 → 目標を 37.7pt 超過達成

リスクと対策

リスク影響対策
Cloud Run コールドスタート増加最初のリクエストの配信遅延startup_cpu_boost=true + Cloud Monitoring Uptime Check(30秒間隔)でウォームアップ維持
BigQuery dbt モデル移行時のデータ欠損KPI 数値の不整合--full-refresh 実行前に dbt test でデータ品質確認 + 移行後24時間は旧テーブルと並行監視
Pub/Sub ackDeadline 延長で重複配信増加メール重複送信(スパム判定リスク)冪等性キー(email_id + campaign_id)を BigQuery に保存し、配信前に重複チェック

ポイント解説

1 Unit Economics を軸にコスト分析する
「月額 $9,600 が高い」という絶対額でなく「1配信あたり $0.0004 のコストで $0.06 の GMV を生み出している」と Unit Economics に変換することで、削減余地(Unit Cost を下げる)とスケール戦略(配信数を増やして規模の経済を活かす)の2軸で議論できる。CFO が指摘した「GMV 1.2倍成長・コスト 1.8倍成長」は Unit Cost が 1.5倍悪化していることを意味し、放置するとスケールするほど Margin が圧迫される構造問題になる。
2 ROI 降順で施策を並べる
「Pub/Sub ackDeadline 0.5人日で $660削減(ROI $1,320/人日)」は Cloud Run の2人日・BigQuery の3人日より ROI が高い。先に着手することでチームの信頼を得られ、大型施策(BigQuery 3人日)への承認を取りやすくなる。コスト削減提案では「どの施策が ROI 最大か」を定量的に示すことが経営判断を加速させる核心スキル。
3 Cloud Run の課金モデルを理解する
cpu_idle=true(CPU throttling)は「リクエスト処理中のみ CPU が課金対象」になる。min_instance_count=0 との組み合わせでアイドルコストをゼロにできる。常時稼働サービス(WebSocket、ストリーミング)には向かないが、バースト型の配信 API には最適。startup_cpu_boost=true を設定することでコールドスタート時の CPU を一時的にブーストし、初回レイテンシの影響を最小化できる。
4 Pub/Sub の再配信ループはコストを静かに膨張させる
デフォルトの ackDeadlineSeconds=10 は多くの実務シナリオで短すぎる。処理時間の3倍程度(余裕係数)を設定し、長時間処理は modifyAckDeadline でリース延長する。再配信ループは Cloud Monitoring → Pub/Sub → subscription/num_undelivered_messages メトリクスの異常な増加で検知できる。冪等性キーによる重複配信チェックは ackDeadline 延長と必ずセットで実装する。
5 CFO・CTO・エンジニアそれぞれの言語に変換する
「年間 ROI 4,207%(CFO 向け)」「8.5日でペイバック(CTO 向け)」「Terraform 1行変更(エンジニア向け)」と変換することで意思決定のスピードが上がる。証券マンの視点では「ペイバック 8.5日」は投資として圧倒的な指標であり、CFO が承認しない理由がない。コスト削減提案では必ず ROI とペイバック期間をセットで提示する習慣が、エンジニアリングリードとしての信頼を高める。

実務への応用

  • Cloud Run v2 の min-instances と CPU throttling: 現職の配信 API に今すぐ適用可能。terraform plan で変更内容を確認してから apply し、Cloud Monitoring でリクエスト数・レイテンシを1時間監視してからアイドルコストの削減を確認する。コールドスタートが問題になった場合は min_instance_count=1 に戻すことも検討する。
  • Pub/Sub の ackDeadline 問題の発見方法: gcloud pubsub subscriptions describe <name> で現在の設定を確認。Cloud Monitoring → Pub/Sub → subscription/num_undelivered_messages が急増していたら再配信ループのサイン。DataDog でも gcp.pubsub.subscription.num_undelivered_messages メトリクスを監視できる。
  • 証券マン視点での意思決定: 「8.5日ペイバック」は株式投資で言えば年率 4,207% の IRR。リスクフリーレートの 400倍以上。CFO が承認しない理由がない数字。コスト削減提案は必ず ROI とペイバック期間をセットで出す。「エンジニアがコストを下げた」ではなく「$2,080 の投資で年間 $89,544 のリターンを生み出した」という言語に変換する。
  • BigQuery コスト監視の自動化: INFORMATION_SCHEMA.JOBS から「スキャン量 TOP 10 クエリ」を日次集計して Slack に投稿する Argo ジョブを追加すると、コスト膨張の早期警戒システムになる。total_bytes_processed カラムを集計し、前日比 20%以上増加した場合にアラートを出す設計が実用的。

今日のまとめ

Unit Economics(1通あたりのコスト)を分解することで「GMV 成長 1.2倍に対してコスト 1.8倍」という構造問題を可視化し、Cloud Run の min-instances=0(アイドルコスト95%削減)と Pub/Sub の ackDeadline=60秒(再配信ループ解消)という「工数対削減額 ROI 最大」の施策を Phase 1 に置くことで、6.5人日で月額 77.7%削減・年間 ROI 4,207%・ペイバック 8.5日という CFO が拒否できない経営インパクトを出せる。

エンジニアリングリードの核心スキルは「技術的に正しいこと」だけでなく「ROI を CFO・CTO・エンジニアそれぞれの言語に変換して意思決定を加速させること」であり、Unit Economics × ROI 降順での施策優先順位付けがその実践的なアプローチ。

自己評価

自分の回答

気づき・メモ