Cloudflare Workflows では、一度デプロイしたステップ名を変えてはいけません。 ステップ名がキャッシュキーになっているため、名前を変えると、完了したはずの処理がもう一度実行されるおそれがあります。
この記事でわかること
- 時刻や乱数のように実行のたびに変わる値は、ステップ名に入れないでください
- 上限までリトライしても成功しなければ、ワークフロー全体がエラーで終わります
- 二重に実行されると困るステップは、べき等に書く必要があります
この記事の目次(7節)
途中から再開する仕組み
Durable Execution は、処理の途中でワーカー(処理を実行する環境)が停止しても、完了したステップをやり直さずに続きから再開できる実行方式です。Cloudflare Workflows はこの方式を採っています。
step.do() で囲んだ処理は、一度成功すると結果がキャッシュされます。ワークフローが再実行されても、キャッシュされた結果が使われ、処理そのものは呼ばれません。そのときのキャッシュキーが、ステップ名です。1
名前を変えると、別のステップになる
step.do("load-topic", ...) を step.do("fetch-topic", ...) に変えると、Workflows はこれを別の新しいステップとして扱います。中身が同じでも、キャッシュされた結果は使われません。1
ここから先は公式ドキュメントに記載がなく、この仕組みからの推測です。例えば、請求書を作ってメールで送り、入金の確認を待つワークフローがあるとします。入金確認を待っているインスタンスが、メールを送るステップの名前を変えたコードで再開すると、Workflows がそのステップを未実行と扱うおそれがあります。その場合、処理の中身を1行も変えていなくても、送信済みの請求書メールが再送されることがあります。
このサイトを動かしているシステム(記事公開のパイプライン)も、ステップ名を固定しています。ステップの並びは次のとおりです。
check-pausedload-topicwrite-draftqa-checksave-draftresolve-approval-policycreate-approvalpublishindex-kbmeasure
名前で見分けているのは step.do() だけではありません。人の承認を待つ step.waitForEvent("wait-approval", …) と、7日待つ step.sleep("settle", "7 days") も同じです。特に wait-approval は、承認を最大7日待っている最中に名前が変わると、待機がやり直しになると考えられます。
先頭の check-paused は、緊急停止のチェックです。停止の設計は、自律AIエージェントの実用アーキテクチャで取り上げています。
実行のたびに変わる名前も危ない
Date.now() や乱数を含むステップ名は、実行のたびに違う文字列になるので、結果がキャッシュされません。後続のステップが失敗したときに、不要な再実行を招きます。ステップ名は固定の文字列にします。1
リトライは各ステップの中で完結する
公式ドキュメントを確認する限り、「失敗したステップから自動で再開する」という仕様は明記されていません。 ドキュメントに書かれている挙動は次のとおりです。2
- リトライの回数・待ち時間・タイムアウトは、ステップごとに
StepConfigで設定します - 上限までリトライしても成功しなければ、そのステップは失敗し、ワークフロー全体が
Erroredの状態で終わります try...catchで例外を捕まえれば、後続のステップを続けられます
リトライ回数は既定で5回、最大で10,000回まで設定できます。バックオフ(リトライの間隔の広げ方)は、constant(一定)・linear(線形)・exponential(指数)の3種類です。2
自動で回復するのはステップの中のリトライまでで、上限に達した後の扱いは実装者が決めます。このシステムでリトライを個別に設定しているのは write-draft と index-kb の2つだけで、残りは既定のままです。
二重に実行されても困らない書き方
ステップはリトライで何度も実行されうるので、べき等にしておくのが理想です。 べき等とは、何度実行しても結果が同じになることです。呼び出し先のサービスが処理の途中で停止しても、処理自体は確定していることがあります。そのため公式ドキュメントでは、支払いを例に、実行の前に処理済みかどうかを確かめ、済んでいれば何もせずに戻る書き方が示されています。1
このチェックがないと、同じ支払いが二重に行われるような重複実行が起こりうると考えられます。コストを機能ごとに記録する設計は、LLMアプリのコストの記録で取り上げています。
このシステムの create-approval(承認の依頼を作るステップ)は、まだこの書き方になっていません。毎回新しい UUID を採番して INSERT するだけで、存在チェックも INSERT OR IGNORE もありません。approvals テーブルに UNIQUE 制約もなく、StepConfig を渡していないので、既定の5回のリトライがかかります。
INSERT が確定した後でステップが失敗と判定されると、同じ記事に承認待ちのレコードが2件できます。設計ではなく見落としで、直すべき不具合として記録してあります。べき等に書くべきだと知っていても、実際に書けているとは限らない例です。
ワークフロー設計の4つの原則
- ステップ名は固定の文字列にし、デプロイした後は変えない。 実行中のインスタンスがある限り、名前の変更は同じ処理の再実行につながりうる
- 外部への書き込み(副作用)があるステップは、べき等に書く。 支払い・通知・公開など、二重に実行されると困る処理は、先に処理済みかどうかを確かめる
- 外部の呼び出しを1つのステップに詰め込まない。 一部が失敗するとステップごとリトライされ、成功した呼び出しまで再実行される
- 失敗をどこで打ち切るかを決めておく。
try...catchで握りつぶすと後続のステップは実行されるが、それが意図した続行か失敗の隠蔽かは、書いた本人にしか分からない
よくある質問
Q. どうしてもステップ名を変えたいときは、どうすればよいですか。
旧バージョンの実行中のインスタンスが残っていないときに変えます。本番稼働中のシステムでは、変えない前提で設計するのが安全です。
Q. リトライ回数を増やせば、失敗はほぼ起きなくなりますか。
なりません。認証切れのように原因が続く失敗は、回数を増やしても失敗し続けます。原因への対処が先です。
出典
- Rules of Workflows · Cloudflare Workflows docs(参照 2026-08-12)
- Sleeping and retrying · Cloudflare Workflows docs(参照 2026-08-12)

