Skip to content

필사 모드: 耐久ワークフローエンジン 2026 完全ガイド — Temporal · Restate · Hatchet · Inngest · Trigger.dev · Cadence · DBOS · Dapr Workflows 徹底比較

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

プロローグ — 「バックグラウンドジョブか、ワークフローか?」

2026年のある企業の決済システム会議。

ジュニア:「決済後にメールを送るのは、キューに入れてワーカーが処理すれば OK ですよね?」

シニア:「そのワーカーが落ちたら?」

ジュニア:「リトライすれば。」

シニア:「でもメールはもう 2 通行ってる。返金はしたけど在庫はロックされたまま。決済は通ったのに注文は pending で止まっている。」

ジュニア:「...」

シニア:「それが、ワークフローエンジンが必要になる瞬間だ。」

この短い会話に、2026年の分散システムにおける核心的な悩みが詰まっている。Cron + Celery + Redis で始まったバックグラウンドジョブは、決済・注文・サブスクリプション・オンボーディング・AI エージェントといった**多段階の非同期ビジネスプロセス**へと進化し、単純なキューでは捌けない領域が広がった。

**耐久実行(durable execution)** — コードを書くようにワークフローを記述するが、そのコードのすべてのステップが永続化され、プロセスが死んで蘇っても同じ場所から続行できる。2026年、このパラダイムは Temporal が定義したカテゴリーから始まり、Restate・Hatchet・Inngest・Trigger.dev v3・DBOS が各々の答えを提示する豊かな市場へと成熟した。

本稿はその全地形を整理する。耐久実行とは何か、各エンジンの設計思想、コード例、Saga・Outbox といったパターン、AI エージェントのオーケストレーションにおける位置づけ、そして韓国・日本の大手 IT 企業が何をどう使っているか、までを一気に。

第 1 章 · 耐久実行とは何か — イベントソーシングとリプレイ

**Durable execution** の一行定義は「関数のすべての入出力と非決定的部分をイベントログに永続化し、障害後に再起動した際にログをリプレイして同じ状態に正確に復元する実行モデル」。

このアイデアの起源は 3 つ。

1. **イベントソーシング(event sourcing)** — 状態を直接保存せず、状態を生んだ事象を保存する。

2. **決定的リプレイ(deterministic replay)** — 同じイベントログ上で同じコードを走らせれば常に同じ結果になる。

3. **副作用の隔離** — 外部呼び出し(HTTP、DB、キュー)は一度だけ実行され、その結果がログに保存されるため、再実行しても重複しない。

従来のワークフローエンジン(BPMN、Airflow)は DAG 定義を外部ファイルに置き、エンジンがそれを解釈して実行する。耐久実行は違う — **ワークフロー自体がコード**だ。`if`、`for`、`try/catch`、関数呼び出しのすべてがワークフロー定義の一部であり、エンジンはそのコード実行を永続化する。

表で対比。

| 項目 | 従来(Airflow/Argo) | 耐久実行(Temporal/Restate) |

| --- | --- | --- |

| 定義形式 | YAML/Python DAG 宣言 | 任意のコード |

| 分岐 | DAG に明示 | コードの `if/else` |

| 長期待機 | sensor / poke | `sleep(30d)` のような関数呼び出し |

| 状態保存 | 外部 DB のタスク状態 | イベントログ |

| 失敗復旧 | 失敗タスクから再試行 | 同じ場所からリプレイ再開 |

| 開発体験 | DSL 学習 | 普通のコード |

このモデルの真の価値は「**`sleep(30d)` が実際に 30 日眠って起き、メモリに残っていたかのように動作する**」点にある。プロセスが落ちて別ノードで再開しても、イベントログのリプレイで同じ行へ復帰する。

第 2 章 · なぜ今ワークフローエンジンが重要か — 5 つの問題

2026年のマイクロサービス環境で、ワークフローエンジンが解決する問題群。

**問題 1 — 分散 Saga**。注文が決済・在庫・配送・通知の 4 サービスを跨ぎ、3 段階目で失敗した場合、1・2 段階目を補償しなければならない。DB トランザクションでは括れない。

**問題 2 — 長期実行**。会員登録後 7 日間トライアル、14 日後に課金、30 日後に失効 — このタイムラインはメモリで持てず、cron + state machine で書くとコードが爆発する。

**問題 3 — AI パイプライン**。RAG インデックス -> 埋め込み -> 生成 -> レビュー -> 公開のような多段階 LLM パイプラインは、ステップごとに失敗率が異なり、分単位で時間がかかる工程もあり、コストの大きな工程は決して重複呼び出ししてはならない。

**問題 4 — 冪等性とリトライ**。外部 API(決済、メール、SMS)はネットワーク断時に冪等性キーなしでは再試行が危険。ワークフローエンジンはその冪等処理をコード一行で抽象化する。

**問題 5 — Exactly-once**。メッセージキューで擬似的に実現する "at-least-once + 冪等性" の限界を超え、「各ビジネスアクションは厳密に一度だけ起きた」を強制するのがワークフローエンジンの中核的な約束。

要するに、2026年のバックエンドエンジニアが向き合う問題は、「1 回の HTTP レスポンス」型ではなく、「複数のシステムを横断し、時間を横断するプロセス」型へと比重が移っている。

第 3 章 · Temporal Cloud + Temporal Server 1.25 — カテゴリーの定義者

Temporal は 2019 年に Maxim Fateev と Samar Abbas(共に Uber Cadence のオリジナル作者)が設立した会社で、事実上「耐久実行」というカテゴリーを定義した。2025 年シリーズ D で評価額は 15 億ドルを超えた。

中核アーキテクチャ。

| コンポーネント | 役割 |

| --- | --- |

| Frontend | gRPC API ゲートウェイ |

| History | イベントログ永続化(Cassandra/PostgreSQL/MySQL) |

| Matching | タスクキュー |

| Worker (Internal) | システムワークフロー(例: アーカイブ) |

| **Worker (User)** | ユーザーが SDK で書いたワークフロー/アクティビティを実行 |

Temporal Server 1.25(2025 年後半)の大きな変化。

- **PostgreSQL 16 サポート + 新しい visibility バックエンド**(ElasticSearch 依存を削減)。

- **Update with start** — ワークフロー開始と同時に入力更新を渡す。

- **Nexus** — 異なる namespace 間で安全にシグナル/クエリ(マルチテナンシー対応)。

- **ワークフロー memoization キャッシュ改善** — メモリ使用量 50% 削減。

公式 SDK は Go・Java・Python・.NET・TypeScript・PHP・Ruby。2025 年に Rust SDK がベータ追加。最も愛されているのは TypeScript と Python。

**TypeScript ワークフロー例**。

// workflows/order.ts

const { chargeCard, reserveInventory, ship, sendEmail, refundCard } =

proxyActivities<typeof activities>({ startToCloseTimeout: '1 minute' })

export const cancelOrderSignal = defineSignal('cancelOrder')

export async function orderWorkflow(orderId: string, amount: number) {

let cancelled = false

setHandler(cancelOrderSignal, () => { cancelled = true })

await chargeCard(orderId, amount)

try {

await reserveInventory(orderId)

await ship(orderId)

await sleep('48 hours') // 配送後 48 時間後に満足度メール

if (!cancelled) await sendEmail(orderId, 'satisfaction-survey')

} catch (err) {

await refundCard(orderId, amount) // 補償アクション

throw err

}

}

このコードの魔法は `sleep('48 hours')`。ワーカーが死んで再起動しても、別ホストで再開しても、48 時間後の正確なその瞬間に次行へ続く。

ワーカー実行。

// worker.ts

const worker = await Worker.create({

workflowsPath: require.resolve('./workflows'),

activities,

taskQueue: 'orders',

})

await worker.run()

**Temporal Cloud** はマネージドの形態で、2026 年の価格はアクション(イベント)ベース + active execution。一般的な SaaS はクラスタ自前運用より Cloud の方が安い。

第 4 章 · Cadence (Uber) — Temporal の祖先

Cadence は 2017 年に Uber がオープンソース化したワークフローエンジンで、Temporal の直系の祖先。Temporal 共同創業者がもともと Uber Cadence チームを率い、2019 年に Temporal として fork・創業した。

2026 年時点での両者の関係。

- **API/SDK は類似**だが互換性なし。Cadence Go SDK コードを Temporal に移すにはパッケージ名・一部セマンティクスを修正する必要がある。

- **Cadence は Uber 内部で依然大規模運用中**(数十万ワークフローインスタンス/日)。

- **Temporal が OSS 側のイノベーションを牽引** — Nexus、Workflow Updates、Visibility v2 などの新機能は Temporal が先行。

新規プロジェクトなら Temporal を推奨。Cadence は Uber エコシステムまたは既存 Cadence 資産がある場合にのみ意味がある。

第 5 章 · Restate — Workflow + RPC、「よりシンプルな Temporal」

Restate は 2023 年に Stephan Ewen(Apache Flink 共同創業者)が設立した会社で、2025 年に 1.0 をリリース。

設計判断の比較。

| 項目 | Temporal | Restate |

| --- | --- | --- |

| 中核抽象 | Workflow + Activity | Virtual object + Workflow + Service |

| 永続化 | Cassandra/Postgres | 内蔵 RocksDB + 任意の外部ストレージ |

| 通信 | gRPC + 独自プロトコル | HTTP/2 + Connect/gRPC |

| デプロイ | クラスタ(History/Matching/...) | 単一バイナリ |

| 決定性 | SDK が保証 | ハンドラ単位の冪等性 |

Restate の核となるキーワードは **Virtual Object**。ステートレスハンドラ(HTTP エンドポイント)と永続状態を結合した単位で、「決済ドメインオブジェクト」のようなモデルを自然に表現する。

**TypeScript 例**。

const orderService = restate.service({

name: 'OrderService',

handlers: {

async place(ctx: restate.Context, input: { orderId: string; amount: number }) {

const paymentId = await ctx.run('charge', () =>

chargeAPI(input.orderId, input.amount)

)

try {

await ctx.run('reserve', () => reserveInventory(input.orderId))

} catch (err) {

await ctx.run('refund', () => refundAPI(paymentId))

throw err

}

await ctx.sleep(48 * 60 * 60 * 1000) // 48h

await ctx.run('survey', () => sendSurveyEmail(input.orderId))

},

},

})

restate.endpoint().bind(orderService).listen(9080)

`ctx.run(...)` が副作用の冪等単位。結果が Restate サーバに永続化され、再実行時には同じ結果がそのまま返される。

Restate の魅力は**運用シンプリシティ**。単一の Rust バイナリ、別の SQL や Cassandra クラスタなしでも小規模ならそのまま動く。AWS・GCP・Azure マネージドもベータで登場中。

2026 年の Restate のポジショニングは「**Temporal の強力さは必要だが、運用複雑性は嫌な小さなチーム**」。スタートアップや単一サービスへの迅速導入を狙う場面で採用が増えている。

第 6 章 · Hatchet — Postgres 上の分散キュー + ワークフロー

Hatchet は 2023 年に登場したオープンソースのワークフローエンジンで、**Postgres のみで動作する**ことが核心の差別点。

設計宣言。

- 外部依存は Postgres ひとつ。Cassandra・Redis・NATS・Kafka 不使用。

- gRPC + ワーカー SDK(Python・TypeScript・Go)。

- マルチテナンシー内蔵。

- AOR(Acyclic Orchestration Runtime) — DAG のようにステップを定義。

**Python 例**。

from hatchet_sdk import Hatchet, Context

hatchet = Hatchet()

@hatchet.workflow(on_events=["order:created"])

class OrderWorkflow:

@hatchet.step(retries=3, timeout="1m")

def charge(self, ctx: Context):

order = ctx.workflow_input()

return charge_card(order["id"], order["amount"])

@hatchet.step(parents=["charge"])

def reserve(self, ctx: Context):

return reserve_inventory(ctx.workflow_input()["id"])

@hatchet.step(parents=["reserve"])

def ship(self, ctx: Context):

return ship_order(ctx.workflow_input()["id"])

worker = hatchet.worker("orders-worker")

worker.register_workflow(OrderWorkflow())

worker.start()

Hatchet の強みは、**既に Postgres を運用しているチーム**に圧倒的に刺さること。新規インフラなしに非同期ジョブ + ワークフロー + キューを一つのシステムに統合。さらに Python が強い分野(データ・AI)で素早く地歩を築いた。

2026 年 Hatchet Cloud もリリースされ、マネージドオプションが追加された。

第 7 章 · Inngest — Step Functions、開発者ファースト

Inngest は 2021 年に登場し、「**Step Functions の正確性を開発者へ、AWS ロックインなしで**」を掲げて地位を築いた。TypeScript ファーストの SDK が最も完成度高いと評される。

中核抽象は `step`。関数内で `step.run`、`step.sleep`、`step.sendEvent`、`step.waitForEvent` で永続単位を定義すれば、Inngest エンジンが各 step の入出力を保存し、再実行時にキャッシュ値を再利用する。

**TypeScript 例**。

export const onboarding = inngest.createFunction(

{ id: 'user-onboarding' },

{ event: 'user.signed_up' },

async ({ event, step }) => {

await step.run('send-welcome-email', () => sendEmail(event.data.email, 'welcome'))

await step.sleep('wait-2-days', '2 days')

await step.run('send-tips', () => sendEmail(event.data.email, 'tips'))

const purchase = await step.waitForEvent('await-purchase', {

event: 'order.completed',

timeout: '7d',

match: 'data.userId',

})

if (!purchase) {

await step.run('reminder', () => sendEmail(event.data.email, 'reminder'))

}

}

)

このコードはユーザー登録後 7 日間のオンボーディングをそのまま表現する。`step.waitForEvent` で特定イベントの到着を待つのが自然に書ける。

Inngest の魅力は**5 つが一つに集約された**こと — イベントキュー、cron、ワークフロー、関数ホスティング、Observability。別の BullMQ/Sidekiq + Temporal の組み合わせを一つの SaaS で済ませる。

価格は関数呼び出し(steps)ベース。小さなスタートアップは無料枠で十分にスタート可能。

第 8 章 · Trigger.dev v3 — オープンソース版 Inngest 代替

Trigger.dev は 2022 年に始まり、v2 までは SaaS 中心だった。2024 年リリースの **v3 は大きな転換**。

- **オープンソース化**: AGPL ライセンスで自己ホスト可能。

- **コンテナベース実行**: ジョブを Firecracker または Docker で隔離実行。

- **チェックポイント**: ジョブ実行中にメモリスナップショットを取り、長時間ジョブを再開可能に。

- **TypeScript ファースト**。

**例**。

export const onboarding = task({

id: 'user-onboarding',

maxDuration: 60 * 60 * 24 * 7, // 7d

run: async (payload: { userId: string; email: string }) => {

await sendEmail(payload.email, 'welcome')

await wait.for({ days: 2 })

await sendEmail(payload.email, 'tips')

const purchase = await wait.forEvent('order.completed', {

timeout: '5d',

filter: (e: any) => e.userId === payload.userId,

})

if (!purchase) {

await sendEmail(payload.email, 'reminder')

}

},

})

Trigger.dev v3 の差別ポイントは**チェックポイント**。任意の npm ライブラリ(例: Puppeteer による PDF 生成)を呼んでも、途中でコンテナを停止・再開できる。AI 推論のような GPU リソースを使うジョブに特に合う。

Inngest と Trigger.dev の違い。

| 項目 | Inngest | Trigger.dev v3 |

| --- | --- | --- |

| ライセンス | プロプライエタリ(コア一部 OSS) | AGPL |

| 実行モデル | ユーザー関数が HTTP 経由で呼ばれる | Trigger コンテナがユーザーコードを実行 |

| 自己ホスト | 限定的 | 完全可能 |

| 価格 | step ベース | コンピュート時間ベース |

| AI/長時間ジョブ | 可能だが step 分割必要 | チェックポイントで自然 |

第 9 章 · DBOS — Postgres こそがランタイム

DBOS は 2023 年に MIT の Mike Stonebraker(PostgreSQL・Vertica・VoltDB)グループが起業。一行サマリ:「**プログラム状態を Postgres に永続化するランタイム**」。

DBOS の発想はこうだ — すべての関数呼び出し、トランザクション、ワークフローステップの入出力を Postgres に保存する。すると関数自体が**トランザクション的**になり、失敗後の再起動も Postgres トランザクションの整合性で保証される。

**Python 例**。

from dbos import DBOS, Queue, WorkflowHandle

from sqlalchemy import text

DBOS()

@DBOS.workflow()

def order_workflow(order_id: str, amount: int):

payment_id = charge_step(order_id, amount)

try:

reserve_step(order_id)

ship_step(order_id)

except Exception:

refund_step(payment_id)

raise

@DBOS.transaction()

def charge_step(order_id: str, amount: int):

DBOS.sql_session.execute(

text("INSERT INTO payments(order_id, amount) VALUES (:o, :a)"),

{"o": order_id, "a": amount},

)

return f"pay-{order_id}"

`@DBOS.workflow()` と `@DBOS.transaction()` デコレータで永続単位を明示する。トランザクションアクティビティは Postgres に直接書き、そのトランザクションがワークフロー状態の更新と同じトランザクションに束ねられる — **DB 整合性 + ワークフロー整合性の統一**。

2026 年の DBOS は **Postgres 上ですべてを完結させたいチーム**に人気。欠点は Postgres に依存すること、そして非常に大きなスループットのワークロードで Postgres がボトルネックになり得る点。

第 10 章 · Dapr Workflows — Kubernetes ネイティブサイドカー

Dapr は Microsoft が 2019 年にオープンソース化したマイクロサービスランタイムで、**サイドカーパターン**(アプリの隣に Dapr サイドカーが付き、state/queue/event を抽象化)が核心。2022 年に CNCF 卒業。

**Dapr Workflows** は Dapr 1.10 でアルファ登場し、1.13(2024)で安定化。内部的に **DurableTask** ライブラリ(Azure Durable Functions の中核)を採用。

特徴。

- **言語 SDK**: Go・.NET・Python・Java・JavaScript。

- **バックエンド抽象**: state store は Redis・Postgres・Cosmos DB など任意選択。

- **Kubernetes と自然に統合**: Dapr が K8s サイドカーとして動作。

**Python 例**。

from dapr.ext.workflow import WorkflowRuntime, DaprWorkflowContext, WorkflowActivityContext

wfr = WorkflowRuntime()

@wfr.workflow(name="order")

def order_workflow(ctx: DaprWorkflowContext, order: dict):

payment = yield ctx.call_activity(charge, input=order)

try:

yield ctx.call_activity(reserve, input=order)

yield ctx.create_timer(fire_at=ctx.current_utc_datetime + timedelta(hours=48))

yield ctx.call_activity(send_survey, input=order)

except Exception:

yield ctx.call_activity(refund, input=payment)

raise

@wfr.activity(name="charge")

def charge(ctx: WorkflowActivityContext, order: dict):

return charge_card_api(order["id"], order["amount"])

Dapr Workflows の強みは、**既に K8s で Dapr を使っている環境で追加インフラなしに導入できる**こと。state store を決めれば同じコードでバックエンドを差し替え可能。

弱点は他のランタイムと比べて SDK の完成度と Observability がまだ一段遅れていること。

第 11 章 · AWS Step Functions — マネージドの標準

AWS Step Functions(2016 年リリース)はワークフローマネージドサービスの事実上の標準。**JSON で定義された状態機械**が中核。

種類。

| 種類 | 価格 | 用途 |

| --- | --- | --- |

| Standard | 状態遷移あたり($0.025/1000) | 長期実行、最大 1 年、exactly-once 保証 |

| Express | 実行時間 + メモリ | 短時間、最大 5 分、at-least-once |

**ASL(Amazon States Language)例**。

{

"StartAt": "ChargeCard",

"States": {

"ChargeCard": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "charge-card", "Payload.$": "$" },

"Next": "Reserve"

},

"Reserve": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "reserve-inventory", "Payload.$": "$" },

"Catch": [{ "ErrorEquals": ["States.ALL"], "Next": "Refund" }],

"Next": "Wait48h"

},

"Wait48h": { "Type": "Wait", "Seconds": 172800, "Next": "Survey" },

"Survey": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "send-survey", "Payload.$": "$" },

"End": true

},

"Refund": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": { "FunctionName": "refund-card", "Payload.$": "$" },

"End": true

}

}

}

AWS ロックインは強いが**運用負担はほぼゼロ**。AWS エコシステムのすべて(Lambda・DynamoDB・SQS・Bedrock・Athena・Glue)と直接統合され、SDK 呼び出しが一行。

コストの罠。Standard は状態遷移が多いワークフローで急速に高額になる。数百万実行 + 数十 step だと月数千ドルを簡単に超える。Express + Map state でコスト最適化するのが標準。

第 12 章 · GCP Workflows + Azure Durable Functions

**Google Cloud Workflows**(2020)。

- YAML または JSON 定義。

- HTTP 呼び出し + 分岐 + 並列。

- Eventarc、Cloud Run、Cloud Functions と自然に統合。

- 価格: ステップ実行あたり。

- 弱点: 状態機械の表現力が Step Functions より単純。

**Azure Durable Functions**(2017)。

- Azure Functions の拡張。

- **C#/JavaScript/Python** でコードのようにワークフローを記述。

- 耐久実行陣営の元祖格 — Temporal の一部アイデアはここから影響を受けている。

- DurableTask(OSS)ライブラリが Dapr Workflows の中核。

**TypeScript Durable Function 例**。

df.app.orchestration('orderWorkflow', function* (ctx) {

const order = ctx.df.getInput()

const payment = yield ctx.df.callActivity('chargeCard', order)

try {

yield ctx.df.callActivity('reserveInventory', order)

yield ctx.df.createTimer(new Date(Date.now() + 48 * 3600 * 1000))

yield ctx.df.callActivity('sendSurvey', order)

} catch {

yield ctx.df.callActivity('refundCard', payment)

throw new Error('order failed')

}

})

`yield` のたびにチェックポイントが生成される。クラウドロックインだが定型化されており、Azure ユーザーなら標準選択。

第 13 章 · Airflow + Dagster + Prefect — データエンジニアリング DAG

データパイプライン領域には別の DAG エンジン群が定着している。本稿の範囲外だが比較として整理。

| エンジン | 開始 | 強み | 弱み |

| --- | --- | --- | --- |

| Apache Airflow | 2014(Airbnb) | 最も普及、豊富なコネクタ | Python DAG 定義、動的ワークフロー弱い |

| Dagster | 2018 | 資産中心(asset graph)、型システム | 学習曲線 |

| Prefect | 2018 | Pythonic API、動的ワークフロー | コミュニティが小さい |

| Argo Workflows | 2018 | K8s ネイティブ、CI/CD に強い | Pod オーバーヘッド |

データエンジニアリング DAG と耐久実行の決定的な違い。

- **DAG エンジン**: データ資産の変換グラフ、時間トリガーが中心。

- **耐久実行**: ビジネスプロセス、イベント・時間・シグナルが混在するコード制御フロー。

2026 年のパターンは「**DAG はデータパイプライン用、耐久実行はビジネスロジック用**」という分業に落ち着いた。

第 14 章 · Argo Workflows — Kubernetes CI/CD

Argo Workflows は 2017 年に Applatix(Intuit が買収)がオープンソース化した CNCF 卒業プロジェクトで、**すべてのステップが K8s Pod**。

apiVersion: argoproj.io/v1alpha1

kind: Workflow

metadata: { generateName: build-and-deploy- }

spec:

entrypoint: pipeline

templates:

- name: pipeline

steps:

- - name: build

template: build

- - name: test

template: test

- - name: deploy

template: deploy

- name: build

container: { image: golang:1.23, command: ["go", "build", "./..."] }

- name: test

container: { image: golang:1.23, command: ["go", "test", "./..."] }

- name: deploy

container: { image: argoproj/argocd:v2.12, command: ["argocd", "app", "sync", "main"] }

Argo Workflows は **K8s ネイティブ CI/CD** の標準。ML パイプライン(Kubeflow Pipelines が Argo ベース)、ビルド/デプロイ(Argo CD と組合せ)、データパイプラインに幅広く使われる。

耐久実行との位置の違い: Argo は**コンテナオーケストレーションワークフロー**、Temporal/Restate は**言語内永続実行**。同じ場所で両方使うケースも多い。

第 15 章 · Cloudflare Workflows — Workers + Durable Objects

Cloudflare Workflows は 2024 年 9 月にベータでリリース。核心は **Cloudflare Workers 上で動作する耐久ワークフロー**。

export class OrderWorkflow extends WorkflowEntrypoint<Env, { orderId: string; amount: number }> {

async run(event: WorkflowEvent<{ orderId: string; amount: number }>, step: WorkflowStep) {

const payment = await step.do('charge', async () =>

chargeCard(event.payload.orderId, event.payload.amount)

)

try {

await step.do('reserve', async () => reserveInventory(event.payload.orderId))

await step.sleep('wait 48h', '48 hours')

await step.do('survey', async () => sendSurvey(event.payload.orderId))

} catch (err) {

await step.do('refund', async () => refundCard(payment))

throw err

}

}

}

エッジコンピューティング + 耐久実行の組合せ。グローバルエッジで実行されるため遅延が極めて低く、Durable Objects が永続状態を担う。2026 年 GA に向けて進行中。

第 16 章 · Conductor (Netflix → Orkes 2022) — JSON DSL

Conductor は 2016 年に Netflix がオープンソース化したワークフローエンジンで、**JSON DSL** ベース。2022 年にコアチームが Orkes として独立、マネージドサービスを運用中。

{

"name": "order_workflow",

"version": 1,

"tasks": [

{ "name": "charge_card", "type": "SIMPLE", "taskReferenceName": "charge" },

{ "name": "reserve_inventory", "type": "SIMPLE", "taskReferenceName": "reserve" },

{

"name": "wait_48h", "type": "WAIT", "taskReferenceName": "wait48",

"inputParameters": { "duration": "48h" }

},

{ "name": "send_survey", "type": "SIMPLE", "taskReferenceName": "survey" }

]

}

Conductor の強みは**言語中立**。JSON DSL + ワーカーが任意の言語で書ける。Netflix 社内の数千のワークフローを運用した実戦的検証がある。

弱点は DSL の学習が別に必要なこと。2026 年の Conductor は大企業(Netflix のほか Walmart・Tesla 引用)で使われるが、スタートアップの採用は Temporal/Inngest に押されている。

第 17 章 · Zeebe + Camunda 8 — BPMN ベース

Camunda は 2008 年スタートのワークフロー会社で、2022 年の Camunda 8 とともに **Zeebe** エンジン(クラウドネイティブ、gRPC)をメインに採用。

主な特徴。

- **BPMN 2.0**: ビジネスが理解できる視覚的表記。

- **DMN**: 意思決定テーブル。

- **クラスタリング**: Zeebe broker + Elasticsearch でクラスタ構成。

BPMN はビジネス/マーケティング/オペレーションチームとワークフローを協業するのに適する。保険・銀行・通信での採用率が高い。エンジニアがコードで書きたいなら Temporal/Restate が自然、**ビジネスが図表で見る**ことが重要なら Camunda が合う。

第 18 章 · Saga パターン — 分散補償トランザクション

耐久ワークフローの定番パターンは **Saga**。

| ステップ | アクション | 補償 |

| --- | --- | --- |

| 1 | 決済 | 返金 |

| 2 | 在庫引当 | 在庫戻し |

| 3 | 配送 | 配送キャンセル |

| 4 | 通知 | (なし) |

3 段階目で失敗したら 2 -> 1 の順で補償アクションを逆順実行。ワークフローエンジンはこの流れを `try/catch + 補償呼び出し` で明瞭に表現できる。

**Temporal における Saga**。

const { charge, refund, reserve, restore, ship, cancel, notify } =

proxyActivities<typeof activities>({ startToCloseTimeout: '1 minute' })

export async function saga(orderId: string, amount: number) {

const compensations: Array<() => Promise<void>> = []

try {

await charge(orderId, amount)

compensations.push(() => refund(orderId, amount))

await reserve(orderId)

compensations.push(() => restore(orderId))

await ship(orderId)

compensations.push(() => cancel(orderId))

await notify(orderId)

} catch (err) {

for (const compensate of compensations.reverse()) await compensate()

throw err

}

}

**補償の冪等性**が肝。`refund(orderId)` が二度呼ばれても二重返金してはいけない。

第 19 章 · Outbox パターンと冪等性キー

ワークフローエンジンが解いてくれない(あるいは解いてくれる)2 つの整合性ツール。

**Outbox パターン** — DB トランザクションとメッセージ送信を結合するために、ビジネス変更と同じトランザクションで「送るイベント」レコードを outbox テーブルに書く。別のディスパッチャが outbox テーブルを読み、メッセージキューへ送る。DBOS はこのパターンが自然で、Temporal ではアクティビティから直接 outbox テーブルに INSERT する形で組み合わせる。

BEGIN;

UPDATE orders SET status='paid' WHERE id='o1';

INSERT INTO outbox(topic, payload) VALUES ('order.paid', '{"id":"o1"}');

COMMIT;

**冪等性キー(idempotency key)** — 外部 API(特に決済)呼び出し時に同一リクエストを 2 回送っても 1 回だけ処理されるよう、キーを一緒に渡す。Stripe・Adyen・PayPal の API はすべてこのパターンをサポート。

curl -X POST https://api.stripe.com/v1/charges \

-H "Idempotency-Key: order-o1-charge" \

-d amount=10000 -d currency=usd -d source=tok_visa

Temporal/Restate/Inngest はワークフロー ID または step ID を自然に冪等性キーとして活用。`Idempotency-Key: workflowId-stepName` のような形が標準。

第 20 章 · 指数バックオフ リトライとデッドレター

すべてのワークフローエンジンの標準機能は**指数バックオフ リトライ**。Temporal RetryPolicy 例。

const { charge } = proxyActivities<typeof activities>({

startToCloseTimeout: '30 seconds',

retry: {

initialInterval: '1 second',

backoffCoefficient: 2,

maximumInterval: '1 minute',

maximumAttempts: 5,

nonRetryableErrorTypes: ['ValidationError'],

},

})

5 回失敗するとワークフローは失敗状態になり、運用者が手動で再起動するかデッドレターキューに移す。Inngest はこの自動デッドレターをデフォルト提供。

非決定的エラー(タイムアウト、ネットワーク)はリトライしてよいが、**決定的エラー**(検証失敗、不正入力)はリトライしても同じく失敗する。`nonRetryableErrorTypes` で分けるのが標準。

第 21 章 · AI エージェント オーケストレーション — LangGraph · Claude · OpenAI Agents

2025〜2026 年に最も急速に伸びるワークフロー活用領域が **AI エージェント**。多段階 LLM パイプラインは耐久実行のすべての魅力 — 段階別コスト、段階別失敗、冪等性 — がそのまま当てはまる。

**LangGraph**(LangChain の姉妹プロジェクト、2024 年〜)。グラフベースのエージェントワークフロー。ノードとエッジで状態機械を構成。

from langgraph.graph import StateGraph, END

from typing import TypedDict

class State(TypedDict):

question: str

answer: str

graph = StateGraph(State)

graph.add_node("retrieve", lambda s: {"answer": rag(s["question"])})

graph.add_node("review", lambda s: {"answer": review(s["answer"])})

graph.add_edge("retrieve", "review")

graph.add_edge("review", END)

graph.set_entry_point("retrieve")

app = graph.compile()

LangGraph 自体は「グラフ定義 + インメモリ ランタイム」だが、**LangGraph Cloud** がチェックポイント保存と再開を提供し、耐久実行に近づく。

**Anthropic Claude Agent SDK**(2025)。ツール使用 + ハンドオフベース。Temporal/Restate と組み合わせてツール呼び出しをアクティビティでラップすれば、自然な耐久エージェントになる。

**OpenAI Agents SDK**(2025)。類似のハンドオフモデル。単一エージェントが別エージェントへ作業を引き継ぐ。

3 SDK の共通点は **エージェント自体は耐久性保証が弱い**こと。そして Temporal/Restate/Inngest をバックエンドとして敷き、永続性を担う構成が標準になりつつある。

第 22 章 · 比較マトリクス — いつ何を選ぶか

| エンジン | OSS | 運用複雑度 | SDK | 強み | 弱み |

| --- | --- | --- | --- | --- | --- |

| Temporal | Yes(MIT) | 中〜高 | Go・Java・Py・.NET・TS・PHP・Rust | 最強、大規模検証 | Cassandra/PG・運用負担、Cloud は割高にも |

| Restate | Yes(BSL) | 低 | Go・Java・TS・Py・Rust・Kotlin | 運用シンプル、Virtual Object | 新規、エコシステム小 |

| Hatchet | Yes(MIT) | 低 | Py・TS・Go | Postgres ベースのシンプルさ | 新規、大規模検証不足 |

| Inngest | 部分 | マネージド | TS・Py・Go | 開発体験最高 | 自己ホスト限定 |

| Trigger.dev v3 | Yes(AGPL) | 中 | TS | OSS + チェックポイント | コンテナオーバーヘッド |

| DBOS | Yes(MIT) | 低 | Py・TS | Postgres トランザクション統合 | PG 依存、スループット上限 |

| Dapr Workflows | Yes(Apache 2.0) | 中 | Go・.NET・Py・Java・JS | K8s + Dapr エコシステム | SDK 成熟度遅れ |

| AWS Step Functions | No | マネージド | JSON DSL | AWS 統合、運用ゼロ | AWS ロックイン、コスト |

| Azure Durable | No | マネージド | C#・JS・Py・Java | Azure 統合 | Azure ロックイン |

| GCP Workflows | No | マネージド | YAML | GCP 統合 | 表現力低い |

| Cadence | Yes(MIT) | 中〜高 | Go・Java | Uber 検証 | Temporal に押される |

| Conductor | Yes(Apache 2.0) | 中 | 言語中立ワーカー | JSON DSL、言語中立 | DSL 学習 |

| Camunda 8 / Zeebe | 部分 | 中〜高 | BPMN + クライアント | BPMN、ビジネス協業 | 重量級 |

| Cloudflare Workflows | No | マネージド | TS | エッジ + Workers | ベータ、短時間ジョブ寄り |

**一行ガイド**。

- 「現実的に検証され、最強」 -> Temporal。

- 「運用シンプル、同等の表現力」 -> Restate。

- 「Postgres だけ使いたい」 -> Hatchet または DBOS。

- 「TS コードで素早く、マネージド」 -> Inngest。

- 「OSS マネージド代替、長時間/AI」 -> Trigger.dev v3。

- 「AWS のみで運用ゼロ」 -> Step Functions。

- 「K8s + Dapr 環境」 -> Dapr Workflows。

- 「ビジネス BPMN 協業」 -> Camunda 8。

第 23 章 · 韓国大手 IT の採用事例

**Toss(トス)** — 金融取引の耐久トランザクションに自社ワークフローエンジンを構築、2024 年のカンファレンスで Temporal 導入経験を発表(2023 年〜)。決済・精算・送金ドメインで Saga パターン活用。

**Coupang(クーパン)** — 注文パイプラインの多段階処理に自社ワークフローエンジンと AWS Step Functions を併用。新規マイクロサービスでは Temporal 導入を評価中。

**Naver(ネイバー)** — Naver Cloud 内部自動化に Argo Workflows + 自社エンジン。検索・ショッピングのバッチ処理は自社分散ジョブシステム。

**NCsoft(エヌシーソフト)** — ゲーム状態マシン、ギルドイベントなど長期非同期処理に Cadence/Temporal 系の検討事例を共有。

**LINE Plus / LY** — メッセージ・決済・広告の非同期処理に Kafka + 自社ワークフローエンジン。一部ドメインで Temporal POC が進行中。

**Kakao(カカオ)** — KakaoTalk の通知・決済パイプライン。社内の非同期処理基盤が強く、新規ドメインでは Temporal・Inngest を評価。

共通点は**決済と注文の領域**で最初に耐久実行の導入を検討すること。トランザクション整合性 + 補償 + 運用可視性を同時に解決する必要があるため。

第 24 章 · 日本の大手 IT の採用事例

**Mercari(メルカリ)** — 決済・送金ドメインで自社ワークフローエンジンと一部 Temporal POC。マイクロサービス化が最も進んだ事例として知られる。

**LINE Yahoo(LY Corporation)** — 統合後の注文/決済パイプライン構築で Kafka + ワークフローエンジンを併用。自社エンジン + 部分的に Temporal。

**Rakuten(楽天)** — サプライチェーン・サブスクリプション・ポイントシステム。AWS Step Functions と Apache Airflow が二本柱、新規ドメインは Temporal Cloud を評価。

**Recruit(リクルート)** — Indeed/SUUMO など子会社が多様。一部チームは Inngest、一部は Airflow + 自社 DAG。

**SmartHR / freee** — SaaS HR/会計。非同期ジョブ + ワークフロー統合に Temporal・Inngest を活発に検討中。

**NTT データ** — エンタープライズ統合に Camunda BPMN の採用率が高い。

日本市場の特徴: エンタープライズでは BPMN(Camunda)の採用率が韓国・米国より相対的に高い。スタートアップ/モダン SaaS では Temporal・Inngest が急速に地歩を築きつつある。

第 25 章 · 始める — 30 分以内に最初の耐久ワークフロー

最速の出発点は Temporal CLI + TypeScript 例。

1. Temporal Server を起動

brew install temporal

temporal server start-dev

2. 新規プロジェクト

npx @temporalio/create@latest hello-temporal

cd hello-temporal

3. ワーカー + クライアント

npm install

npm run start.watch # ワーカー

npm run workflow # ワークフロー実行

Inngest はさらに速い。

npx inngest-cli@latest dev

別ターミナル

mkdir hello-inngest && cd $_

npm init -y

npm install inngest

Restate。

docker run -d --name restate -p 8080:8080 -p 9070:9070 docker.restate.dev/restatedev/restate:latest

npm install @restatedev/restate-sdk

3 エンジンとも最初のワークフローは 30 分以内。その次は、自分のドメインで一番厄介な非同期フローを 1 つ選んで移してみることだ — 「決済 -> 返金」、「会員登録 -> トライアル満了」、「AI インデックス -> レビュー」のような。

第 26 章 · アンチパターンとよくある間違い

耐久ワークフローを誤って使うよくあるケース。

**1. すべてをワークフロー化**。単純なバックグラウンドジョブ(メール 1 通送信)は BullMQ/Sidekiq/Celery で十分。ワークフローエンジンは「多段階 + 時間横断 + 補償が必要」に向く。

**2. 決定性を壊す**。ワークフローコード内で直接 `Date.now()`、`Math.random()`、`fetch(...)` を呼ぶとリプレイが壊れる。常に `proxyActivities` / `ctx.run` / `step.run` を通して。

**3. 大きなペイロードを渡す**。ワークフローの入出力はイベントログに保存される。MB 単位のペイロードはログが爆発。S3 キーだけ渡してアクティビティ内で読むのが標準。

**4. ワークフロー内の無限ループ**。`while(true)` でポーリングしてはいけない。Temporal は `continueAsNew`、Restate は新セッション、Inngest は新イベントでワークフローを更新する。

**5. 補償の漏れ**。Saga の本質は補償。「補償アクション自体が失敗したら?」という問いに常に答えを用意する。

**6. シグナル氾濫**。シグナルはワークフロー状態を非決定的にし得る。シグナル処理順と冪等性を慎重に。

**7. マネージドコストの軽視**。Temporal Cloud / Step Functions はアクション単位課金。1 秒ごとにポーリングするワークフローは月に数千ドルを簡単に超える。

第 27 章 · おわりに — 「ワークフローをコードのように」

2026 年のワークフローエンジンの大きな流れ。

1. **コード中心への収束**。JSON/YAML/BPMN DSL は地位を縮め、「普通のコードで書き、エンジンが永続化」というパラダイムが主流になった。

2. **開発者ファースト**。Inngest・Trigger.dev・Hatchet の台頭は、DX(developer experience)が決定的な差別点であることを示す。

3. **AI エージェントとの結合**。LangGraph・Claude・OpenAI Agents SDK のすべてが耐久実行バックエンドの必要性に行き着く。

4. **運用シンプリシティ競争**。Restate・DBOS・Hatchet は揃って「Temporal より運用が楽」を中心アピールに据える。

5. **クラウドマネージドの成熟**。Temporal Cloud、Inngest Cloud、Restate Cloud、Trigger.dev Cloud — 自前運用を避けられる選択肢が増えた。

初めて導入するチームに勧める流れはこうだ。

1. 一番厄介な非同期ビジネスプロセスを 1 つ選ぶ(普通は決済またはオンボーディング)。

2. Temporal Cloud または Inngest のマネージドから始める。

3. ワークフロー定義をコードで書き、アクティビティは小さく冪等に保つ。

4. Saga + 冪等性キー + 補償を明示的に設計する。

5. 運用可視性(ワークフロー状態、リトライ、デッドレター)を確認する。

ワークフローエンジンは「もっとインフラを増やす」ものではなく、「**ビジネスロジックをよりよく表現できる新しい抽象**」だ。うまく使えば、分散システムで最も厄介な部分が「ただのコード」になる。

参考資料

1. [Temporal — Open Source Durable Execution Platform](https://temporal.io/)

2. [Temporal Cloud Documentation](https://docs.temporal.io/cloud)

3. [Temporal Server 1.25 Release Notes](https://github.com/temporalio/temporal/releases)

4. [Cadence Workflow — Uber Open Source](https://cadenceworkflow.io/)

5. [Restate — Distributed Application Toolkit](https://restate.dev/)

6. [Hatchet — Postgres-backed Workflow Engine](https://hatchet.run/)

7. [Inngest — Reliable Background Jobs and Workflows](https://www.inngest.com/)

8. [Trigger.dev v3 — Open Source Background Jobs](https://trigger.dev/)

9. [DBOS — Database-Backed Durable Programs](https://www.dbos.dev/)

10. [Dapr Workflows Documentation](https://docs.dapr.io/developing-applications/building-blocks/workflow/)

11. [AWS Step Functions Documentation](https://docs.aws.amazon.com/step-functions/)

12. [Azure Durable Functions Overview](https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview)

13. [Google Cloud Workflows](https://cloud.google.com/workflows)

14. [Cloudflare Workflows Documentation](https://developers.cloudflare.com/workflows/)

15. [Conductor / Orkes](https://orkes.io/)

16. [Camunda 8 Documentation](https://docs.camunda.io/)

17. [Apache Airflow](https://airflow.apache.org/)

18. [Dagster](https://dagster.io/)

19. [Prefect](https://www.prefect.io/)

20. [Argo Workflows](https://argoproj.github.io/workflows/)

21. [Saga Pattern — microservices.io](https://microservices.io/patterns/data/saga.html)

22. [Outbox Pattern — microservices.io](https://microservices.io/patterns/data/transactional-outbox.html)

23. [Stripe API — Idempotency](https://docs.stripe.com/api/idempotent_requests)

24. [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)

25. [Anthropic Claude Agent SDK](https://docs.anthropic.com/en/docs/agents)

26. [OpenAI Agents SDK](https://github.com/openai/openai-agents-python)

27. [Maxim Fateev — Designing Temporal (QCon)](https://www.infoq.com/presentations/temporal-design/)

28. [Mercari Engineering Blog — Microservices](https://engineering.mercari.com/en/)

현재 단락 (1/556)

2026年のある企業の決済システム会議。

작성 글자: 0원문 글자: 24,982작성 단락: 0/556