TECH:

決定的ワークフロー実践ガイド:2025年の最新事例3選

CI/CDパイプライン、金融取引、自律飛行システム。現場で使われている決定的ワークフロー(Deterministic Workflow)の最新事例を、ワークフロー図と検証プロセスとともに解説。

決定的ワークフロー実践ガイド:2025年の最新事例3選

「同じコードなのに、本番では動かない」

開発者なら誰もが経験する悪夢。この問題を根本から解決するのが、決定的ワークフロー(Deterministic Workflow) です。

前回の記事「エージェンティック vs デターミニスティック」では、AIワークフローの2つのアプローチを解説しました。今回は、決定的ワークフローが現場でどう活用されているか、最新の事例を3つ紹介します。


決定的ワークフローとは?(復習)

3行でわかる決定的ワークフロー:
  • 再現性:同じ入力なら、必ず同じ出力が保証される
  • 監査可能性:全てのステップが記録され、追跡できる
  • 予測可能性:失敗しても「どこで」「なぜ」が明確

では、実際の現場ではどう使われているのでしょうか?


事例1:GitHub Actions による CI/CD パイプライン

概要

最も身近な決定的ワークフローの例が、CI/CD(継続的インテグレーション/継続的デリバリー) です。GitHub Actionsを例に、そのワークフロー構造を見てみましょう。

ワークフロー図

┌──────────────┐    ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│   Push       │───▶│    Build     │───▶│    Test      │───▶│   Deploy     │
│   (Trigger)  │    │  (npm build) │    │  (npm test)  │    │ (Cloudflare) │
└──────────────┘    └──────────────┘    └──────────────┘    └──────────────┘
       ▲                   │                   │                   │
       │                   ▼                   ▼                   ▼
       │            ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
       │            │   Cache      │    │   Report     │    │   Notify     │
       │            │ (node_modules│    │  (Coverage)  │    │  (Slack)     │
       │            └──────────────┘    └──────────────┘    └──────────────┘

    Rollback(失敗時は自動ロールバック)

決定的にするためのベストプラクティス

  1. アクションのバージョン固定: actions/checkout@v4 ではなく actions/checkout@v4.1.1 のようにパッチバージョンまで指定
  2. 依存関係のキャッシュ: node_modules をキャッシュし、毎回同じ依存関係を使用
  3. イミュータブル・インフラストラクチャ: Dockerイメージは一度ビルドしたら変更しない

検証プロセス

# .github/workflows/ci.yml(抜粋)
jobs:
  build:
    runs-on: ubuntu-22.04 # OSバージョンを固定
    steps:
      - uses: actions/checkout@v4.1.1 # バージョン固定
      - uses: actions/setup-node@v4
        with:
          node-version: '20.10.0' # Node.jsバージョンを固定
          cache: 'npm'
      - run: npm ci # npm install ではなく ci で再現性を保証
      - run: npm test
      - run: npm run build

ポイント: npm install ではなく npm ci を使うことで、package-lock.json に記載された完全に同じバージョンの依存関係がインストールされます。


事例2:Temporal による金融取引ワークフロー

概要

金融業界では「1円でも間違えてはいけない」ため、決定的ワークフローが必須です。Temporal は、Uber、Netflix、Stripe などが採用するワークフローエンジンで、障害が起きても確実に処理を完了させることを保証します。

ワークフロー図

┌─────────────────────────────────────────────────────────────────┐
│                    送金ワークフロー                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐ │
│   │ 送金依頼 │───▶│ 残高確認 │───▶│ 引落し   │───▶│ 入金     │ │
│   │ (Start)  │    │ (Check)  │    │ (Debit)  │    │ (Credit) │ │
│   └──────────┘    └──────────┘    └──────────┘    └──────────┘ │
│        │               │               │               │       │
│        ▼               ▼               ▼               ▼       │
│   ┌──────────────────────────────────────────────────────────┐ │
│   │              Event History(不変の履歴)                  │ │
│   │  [WorkflowStarted] → [ActivityCompleted] → [ActivityCompleted] → ... │
│   └──────────────────────────────────────────────────────────┘ │
│                                                                 │
│   💡 障害発生時:履歴を再生(Replay)して、同じ状態に復元      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

なぜ決定的なのか?

Temporalの核心は 「履歴の再生(Replay)」 です。

  • ワークフローの各ステップは イベント履歴 として永続化される
  • 障害が発生しても、履歴を最初から再生することで 全く同じ状態 に復元できる
  • 「Exactly-once(厳密に1回だけ実行)」を保証

検証プロセス

// Temporal ワークフロー例(Go言語)
func TransferWorkflow(ctx workflow.Context, fromAccount, toAccount string, amount int) error {
    // ❌ 非決定的(NG): time.Now() は再生時に値が変わる
    // timestamp := time.Now()

    // ✅ 決定的(OK): Temporal の時刻関数を使う
    timestamp := workflow.Now(ctx)

    // Activity(外部処理)を呼び出し
    err := workflow.ExecuteActivity(ctx, DebitActivity, fromAccount, amount).Get(ctx, nil)
    if err != nil {
        return err // 失敗したらここで停止(自動リトライ設定可能)
    }

    err = workflow.ExecuteActivity(ctx, CreditActivity, toAccount, amount).Get(ctx, nil)
    return err
}

注意: ワークフロー内で time.Now()rand.Int() を直接使うと、再生時に値が変わり非決定的になります。Temporalでは専用の関数(workflow.Now() など)を使う必要があります。


事例3:自律飛行システムの決定的コンパイル

概要

ドローンや航空機の自律飛行システムでは、ソフトウェアのバグ=人命に関わるため、最高レベルの決定的ワークフローが求められます。Embention社(自律飛行システム開発)の事例を見てみましょう。

ワークフロー図

┌───────────────────────────────────────────────────────────────────────┐
│                  決定的コンパイル・パイプライン                        │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  [開発者のコード]                                                     │
│        │                                                              │
│        ▼                                                              │
│  ┌──────────────┐                                                    │
│  │ 隔離された   │  ← 外部ネットワークから完全に遮断                    │
│  │ CIサーバー   │  ← 同一のOSイメージ、ツールチェーンを使用            │
│  └──────────────┘                                                    │
│        │                                                              │
│        ▼                                                              │
│  ┌──────────────────────────────────────────────────────────────────┐│
│  │ コンパイル → バイナリ生成 → ハッシュ検証 → 署名                   ││
│  └──────────────────────────────────────────────────────────────────┘│
│        │                                                              │
│        ▼                                                              │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐            │
│  │ バイナリA    │ == │ バイナリB    │ == │ バイナリC    │  ← 3回ビルド│
│  │ (Hash: abc)  │    │ (Hash: abc)  │    │ (Hash: abc)  │  して比較   │
│  └──────────────┘    └──────────────┘    └──────────────┘            │
│        │                                                              │
│        ▼                                                              │
│  【一致しなければデプロイ禁止】                                        │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘

決定的にするための技術

  1. 隔離されたCI環境: ビルドサーバーは外部ネットワークから遮断され、同一環境で繰り返しビルド
  2. タイムスタンプの排除: SOURCE_DATE_EPOCH 環境変数を設定し、ビルド時刻をバイナリに埋め込まない
  3. 複数回ビルドしてハッシュ比較: 同じソースから複数回ビルドし、生成されるバイナリのハッシュが一致することを検証

検証プロセス

# 決定的ビルドの検証スクリプト例
export SOURCE_DATE_EPOCH=0  # タイムスタンプを固定

# 3回ビルドしてハッシュを比較
for i in 1 2 3; do
  make clean && make
  sha256sum build/firmware.bin >> hashes.txt
done

# 全てのハッシュが一致するか確認
if [ $(sort -u hashes.txt | wc -l) -eq 1 ]; then
  echo "✅ 決定的ビルド成功:全ハッシュ一致"
else
  echo "❌ 非決定的ビルド検出:デプロイ禁止"
  exit 1
fi

なぜここまでやるのか?: 自律飛行システムでは、テスト環境で動いたバイナリと本番環境のバイナリが 1ビットでも違う と、予測不能な動作を起こす可能性があります。決定的ビルドは「テストしたものと全く同じもの」が本番で動くことを保証します。


まとめ:決定的ワークフローを選ぶべきケース

ケースなぜ決定的が必要か代表的ツール
CI/CD「動いていたコードが動かない」を防ぐGitHub Actions, GitLab CI
金融取引1円も間違えられない、監査対応Temporal, Cadence
航空・医療人命に関わる、規制遵守隔離CIサーバー、決定的コンパイラ
Next Action: あなたのプロジェクトで「再現性がない」問題に悩んでいるなら、まずは 依存関係のバージョン固定ビルド環境の統一 から始めてみてください。それだけで、多くの「謎のバグ」が消えるはずです。

出典・参考資料

公式ドキュメント

技術記事・事例

企業導入事例

  • Netflix: Temporalを使ったメディアエンコーディング・パイプライン
  • Stripe: 決済処理における決定的ワークフロー
  • Coinbase: 全トランザクションをTemporalで管理