AWSコンソールだけでStep Functions + Lambdaワークフローを構築する手順【SAM版との比較付き / 新UI対応】

AWS Basic
スポンサーリンク
スポンサーリンク

はじめに

「複数のLambda関数を順番に呼び出したい」「エラーが起きたとき自動でリトライして、それでも失敗したら別の処理に切り替えたい」という要件を、AWS Step Functions は視覚的なフロー定義で実現します。

この記事では、AWSコンソールのみを使って、受注処理ワークフロー(注文検証 → 在庫確認・支払い並列処理 → 注文確定)をゼロから構築するハンズオンを紹介します。

入力: 注文データ(order_id / item_id / quantity)
  ↓
[ValidateOrder] 注文検証 ... Task + Retry + Catch
  ↓ 成功
[ProcessInParallel] 並列処理 ... Parallel + Catch
  ├─ [CheckInventory] 在庫確認
  └─ [ProcessPayment] 支払い処理
  ↓ 成功
[ConfirmOrder] 注文確定
  ↓
終了(成功)

[HandleError] エラー処理(Catch 先)
  ↓
終了(エラー通知済み)

このハンズオンで体験できること:

  • Step Functions の Task / Parallel / Retry / Catch という基本パターン
  • 並列ブランチの結果をリストとして次のステートに渡す仕組み
  • Workflow Studio(新UI) の操作方法 — ビジュアルエディタと ASL コードエディタの関係
  • ResultPath: "$.error" でエラー情報を元の入力にマージして後続ステートに渡すテクニック

この記事は SAM版ハンズオン の比較記事です。
コンソール操作でStep Functionsの概念を視覚的に学び、SAMと何が違うのかを比較したい方向けです。


Amazon検索[本 AWS 開発]

スポンサーリンク

Step Functions 新UIで戸惑いやすいポイント(先読み)

操作を始める前に、2026年時点の新UIと旧UIの違いを把握しておきましょう。

変更点旧UI新UI(現在)
作成モーダル「空白のステートマシン」テンプレートを選択3択モーダル が表示される
作成選択肢テンプレートギャラリーのみ「自分で作成する」「Hello World を実行」「テンプレートを選択」の3択
ASL入力の場所作成フォームに「コード」タブWorkflow Studio 内の「{ } コード」タブ
ロール設定タイミングASL入力と同じ画面「設定」タブで別途確認

最大のハマりポイント:
「テンプレートを選択」を押してしまうと36個のテンプレートギャラリーが開きます。今回の目的には 「自分で作成する」 を選ぶ必要があります。これを知らずに迷う人が多いポイントです。


スポンサーリンク

キーワード解説

用語意味
ステートマシンワークフローの全体定義。状態(State)の集合と遷移ルールをもつ
Task ステートLambda などの外部リソースを呼び出す状態
Parallel ステート複数のブランチを同時に実行する状態。両ブランチの結果がリストで次のステートに渡る
Retryエラー発生時に同じステートを自動で再実行するルール
Catchリトライ後もエラーが続く場合に別のステートへ遷移するルール
ResultPathCatch 時にエラー情報をどのフィールドに格納するかの指定("$.error" → 元の入力の error キーにマージ)
ASLAmazon States Language。ステートマシン定義の JSON 形式
Workflow StudioStep Functions のビジュアルエディタ。フロー図と ASL コードを双方向に編集できる

前提条件

ツール確認コマンド備考
AWSアカウントIAMユーザーまたはルートユーザー
AWS CLI v2(任意)aws --versionテスト実行を CLI で行う場合のみ必要

今回はほぼコンソール操作のみで完結します。


使用するAWSサービス

サービス役割料金
Step Functionsワークフロー(ステートマシン)の管理・実行月4,000回の状態遷移まで無料(標準タイプ)
Lambda各ステートで実行されるビジネスロジック月100万リクエスト・400,000 GB-秒まで無料
IAMLambda・Step Functionsの実行権限管理無料
CloudWatch LogsLambdaの実行ログ月5GBまで無料

全体の作業順序

① Lambda 関数を5つ作成する
      ↓(各関数の ARN が必要)
② Step Functions ステートマシンを作成する(新UI対応)
      ↓
③ 動作テスト(正常処理 / エラー処理)
      ↓
④ リソースの削除

① Lambda 関数を5つ作成する

共通手順

AWSコンソール → Lambda → 「関数の作成」

設定項目
作成方法一から作成
ランタイムPython 3.12
アーキテクチャx86_64
実行ロール「基本的な Lambda アクセス権限で新しいロールを作成」(デフォルトのまま)

各関数でコードを貼り付けたあと、必ず 「Deploy」 ボタンを押してコードを保存します。


1-1. ValidateFunction(注文検証)

関数名: ValidateFunction

コードエディタで lambda_function.py を開き、既存の内容を全て置き換えて以下を貼り付ける。

import json


def lambda_handler(event, context):
    order_id = event.get("order_id")
    item_id = event.get("item_id")
    quantity = event.get("quantity", 0)

    if not order_id:
        raise ValueError("order_id が指定されていません")
    if not item_id:
        raise ValueError("item_id が指定されていません")
    if not isinstance(quantity, int) or quantity <= 0:
        raise ValueError(f"quantity は正の整数である必要があります: {quantity}")

    result = {
        **event,          # 元の入力フィールドをすべて引き継ぐ(テスト用フラグを後続ステートに渡すため)
        "validated": True,
    }
    print(json.dumps({"step": "validate", **result}, ensure_ascii=False))
    return result

ARN を控えておく: 関数ページ右上の「関数の ARN」をコピー(例: arn:aws:lambda:ap-northeast-1:123456789012:function:ValidateFunction


1-2. InventoryFunction(在庫確認)

関数名: InventoryFunction

import json


def lambda_handler(event, context):
    order_id = event.get("order_id")
    item_id = event.get("item_id")
    quantity = event.get("quantity", 1)

    if item_id == "item-999":
        raise ValueError(f"在庫不足: item_id={item_id}")

    result = {
        "order_id": order_id,
        "item_id": item_id,
        "quantity": quantity,
        "stock_available": True,
    }
    print(json.dumps({"step": "inventory", **result}, ensure_ascii=False))
    return result

ARN を控えておく


1-3. PaymentFunction(支払い処理)

関数名: PaymentFunction

import json


def lambda_handler(event, context):
    order_id = event.get("order_id")
    quantity = event.get("quantity", 1)

    # エラーテスト用: fail_payment=True の場合は例外発生
    if event.get("fail_payment"):
        raise RuntimeError(f"支払い処理に失敗: order_id={order_id}")

    amount = quantity * 1000  # 1個 1,000円

    result = {
        "order_id": order_id,
        "amount": amount,
        "payment_status": "completed",
    }
    print(json.dumps({"step": "payment", **result}, ensure_ascii=False))
    return result

ARN を控えておく


1-4. ConfirmFunction(注文確定)

関数名: ConfirmFunction

import json
import datetime


def lambda_handler(event, context):
    # Parallel ステートの後に呼ばれるため、event はリスト形式
    #   event[0]: CheckInventory(在庫確認)の結果
    #   event[1]: ProcessPayment(支払い処理)の結果
    inventory_result = event[0]
    payment_result = event[1]

    order_id = inventory_result.get("order_id")
    now = datetime.datetime.now(datetime.timezone.utc)

    result = {
        "order_id": order_id,
        "item_id": inventory_result.get("item_id"),
        "quantity": inventory_result.get("quantity"),
        "amount": payment_result.get("amount"),
        "confirmed_at": now.isoformat(),
        "status": "confirmed",
    }
    print(json.dumps({"step": "confirm", **result}, ensure_ascii=False))
    return result

ARN を控えておく

Parallel ステート後の event がリストになる理由:
ProcessInParallel の各ブランチの出力が配列でまとめられて次のステートに渡されます。event[0] が在庫確認の結果、event[1] が支払い処理の結果です。この仕様を知らないと list indices must be integers エラーで詰まります。


1-5. ErrorHandlerFunction(エラー処理)

関数名: ErrorHandlerFunction

import json


def lambda_handler(event, context):
    # ResultPath: "$.error" により、エラー情報が元の入力に付加されて渡される
    error_info = event.get("error", {})
    original_input = {k: v for k, v in event.items() if k != "error"}

    result = {
        "status": "error",
        "error_type": error_info.get("Error", "Unknown"),
        "error_cause": error_info.get("Cause", ""),
        "original_input": original_input,
    }
    print(json.dumps({"step": "error_handler", **result}, ensure_ascii=False))
    return result

ARN を控えておく


② Step Functions ステートマシンを作成する

AWSコンソール → Step Functions → 「ステートマシンを作成」

2-1. 作成方法の選択(新UI:3択モーダル)

「ステートマシンを作成」ボタンを押すと 3択のモーダル が表示されます。

Step Functions 作成モーダル(新UI)

選択肢説明
Hello World を実行ガイド付きチュートリアル(今回は使わない)
テンプレートを選択36個のテンプレートギャラリーが開く(今回は使わない)
自分で作成するゼロからワークフローを作成する ← これを選ぶ

「自分で作成する」 をクリックします。

「テンプレートを選択」を押してしまった場合:
テンプレートギャラリーが開きます。左上の「✕」で閉じて、改めてモーダルから「自分で作成する」を選んでください。


2-2. 名前とタイプの設定(モーダル)

「自分で作成する」をクリックすると Workflow Studio が開き、同時に設定モーダルが表示されます。

設定項目
ステートマシン名OrderWorkflow
ステートマシンのタイプ標準

「続行」をクリックするとモーダルが閉じ、Workflow Studio の編集画面に切り替わります。

標準(Standard)と Express の違い:
標準タイプは「正確に1回実行」「最大1年の実行時間」「実行履歴をコンソールで確認可能」が特徴です。受注処理のような確実な実行が必要なユースケースに適しています。


2-3. ASL の入力(「{ } コード」タブ)

Workflow Studio の画面上部にある 「{ } コード」 タブをクリックしてコードエディタを表示します。

既存の内容を全て削除し、以下の JSON を貼り付けます。

【重要】 REPLACE_WITH_ARN_ValidateFunction などのプレースホルダーを、① で控えた実際の Lambda ARN に置き換えること。

{
  "Comment": "受注処理ワークフロー(検証 → 並列処理 → 確定)",
  "StartAt": "ValidateOrder",
  "States": {
    "ValidateOrder": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_ARN_ValidateFunction",
      "Next": "ProcessInParallel",
      "Retry": [
        {
          "ErrorEquals": ["States.ALL"],
          "IntervalSeconds": 2,
          "MaxAttempts": 1,
          "BackoffRate": 2.0
        }
      ],
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "Next": "HandleError",
          "ResultPath": "$.error"
        }
      ]
    },
    "ProcessInParallel": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "CheckInventory",
          "States": {
            "CheckInventory": {
              "Type": "Task",
              "Resource": "REPLACE_WITH_ARN_InventoryFunction",
              "End": true
            }
          }
        },
        {
          "StartAt": "ProcessPayment",
          "States": {
            "ProcessPayment": {
              "Type": "Task",
              "Resource": "REPLACE_WITH_ARN_PaymentFunction",
              "End": true
            }
          }
        }
      ],
      "Next": "ConfirmOrder",
      "Catch": [
        {
          "ErrorEquals": ["States.ALL"],
          "Next": "HandleError",
          "ResultPath": "$.error"
        }
      ]
    },
    "ConfirmOrder": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_ARN_ConfirmFunction",
      "End": true
    },
    "HandleError": {
      "Type": "Task",
      "Resource": "REPLACE_WITH_ARN_ErrorHandlerFunction",
      "End": true
    }
  }
}

貼り付けると 「フロー」タブ に切り替えると、フロー図が自動生成されます。ASL を正しく記述できているかを視覚的に確認できます。


2-4. 実行ロールの確認と作成(「設定」タブ)

画面上部の 「設定」 タブをクリックして実行ロールを確認します。

設定項目
実行ロール「新しいロールを作成」(デフォルトのまま)
ログ記録OFF(デフォルトのまま)

「新しいロールを作成」を選ぶと、以下のような青いボックスが表示されます。

実行ロールは、完全な許可で作成されます。StepFunctions-OrderWorkflow-role-XXXX という名前の新しい実行ロールが作成されます。ステートマシンで指定されたアクションに必要なすべての許可が自動生成されます。

「自動生成された許可を確認」を展開すると lambda:Invoke が含まれていることを確認できます。

右上の 「作成」 ボタンをクリックします。

IAMロールの自動作成について:
ASL 定義に記述した Lambda ARN に対して lambda:Invoke 権限を持つロールが自動的に作成されます。SAM版では LambdaInvokePolicy ポリシーでこれを明示的に定義しています。


③ 動作テスト

Step Functions → OrderWorkflow → 「実行を開始」

テスト1: 正常処理

入力データ:

{
  "order_id": "ORD-001",
  "item_id": "item-001",
  "quantity": 2
}

「実行を開始」をクリックします。

実行グラフで確認:

  • 全ステートが緑色になることを確認する
  • ProcessInParallel の2つのブランチが同時に緑になることを確認する(並列処理の視覚化)

出力を確認:

実行完了後、「出力」タブで以下のような JSON が表示されます。

{
  "order_id": "ORD-001",
  "item_id": "item-001",
  "quantity": 2,
  "amount": 2000,
  "confirmed_at": "2026-03-01T10:00:00.000000+00:00",
  "status": "confirmed"
}

テスト2: 在庫切れエラー(Parallel Catch の確認)

入力データ:

{
  "order_id": "ORD-002",
  "item_id": "item-999",
  "quantity": 1
}

期待する動作:

  1. ValidateOrder → 成功
  2. ProcessInParallelCheckInventoryValueError を発生させる
  3. ProcessInParallel の Catch が動作 → HandleError へ遷移
  4. HandleError → 成功(エラー情報をログに記録して終了)

実行グラフで確認:

  • CheckInventory赤くなる
  • ProcessInParallel から HandleError へ遷移するパスが強調される

出力を確認:

{
  "status": "error",
  "error_type": "ValueError",
  "error_cause": "在庫不足: item_id=item-999",
  "original_input": {
    "order_id": "ORD-002",
    "item_id": "item-999",
    "quantity": 1,
    "validated": true
  }
}

テスト3: 支払い失敗エラー(Parallel Catch の確認)

入力データ:

{
  "order_id": "ORD-003",
  "item_id": "item-001",
  "quantity": 2,
  "fail_payment": true
}

期待する動作:

  1. ValidateOrder → 成功
  2. ProcessInParallelProcessPaymentRuntimeError を発生させる
  3. ProcessInParallel の Catch が動作 → HandleError へ遷移

テスト4: 検証エラー(ValidateOrder Retry + Catch の確認)

入力データ(order_id を省略):

{
  "item_id": "item-001",
  "quantity": 2
}

期待する動作:

  1. ValidateOrderValueError 発生
  2. Retry: IntervalSeconds: 2 で2秒後に自動リトライ(合計2回試行)
  3. 2回とも失敗 → Catch が動作 → HandleError へ遷移

Retry の確認方法:

実行グラフで ValidateOrder を選択 → 「イベント」タブ で以下の順序を確認します:

TaskStateEntered → TaskScheduled → TaskStarted → TaskFailed
  → TaskScheduled(リトライ1回目)→ TaskStarted → TaskFailed
  → TaskStateExited(Catch 発動)→ HandleError へ

ValidateFunction が合計2回呼ばれていることが分かります。


④ リソースの削除

課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。

1. ステートマシンを削除する

Step Functions → OrderWorkflow → 「削除」→ 確認テキストを入力 → 「削除」

削除後、ステータスが「削除中」に変わります。以下のようなメッセージが表示されます:

ステートマシンに削除のマークが付けられました。すべての実行が停止されると削除されます。

これは正常な動作です。実行中のワークフローがすべて終了するまで完全削除を待つ仕様のため、実行中のものがなければ数秒〜数十秒でリストから消えます。ページをリロードして確認します。


2. Lambda 関数を5つ削除する

Lambda → 関数一覧 → 各関数を選択 → 「アクション」→「削除」

削除対象:

  • ValidateFunction
  • InventoryFunction
  • PaymentFunction
  • ConfirmFunction
  • ErrorHandlerFunction

3. IAM ロールを削除する(任意)

Step Functions の実行ロール(StepFunctions-OrderWorkflow-role-XXXX)と、Lambda 関数のロール(ValidateFunction-role-XXXX など5つ)を削除します。

IAM → ロール → 各ロールを検索して削除


4. CloudWatch Logs のロググループを削除する(任意)

CloudWatch → ロググループ → 各 Lambda の /aws/lambda/関数名 を削除


SAMとの対比

SAMの記述コンソールでやること
AWS::Serverless::StateMachineStep Functions → ステートマシンを作成
Type: STANDARDタイプ = 「標準」
Definition: {...}「{ } コード」タブに ASL JSON を貼り付け
DefinitionSubstitutionsJSON 内の ARN プレースホルダーを手動で置換
LambdaInvokePolicy × 5「設定」タブ → 「新しいロールを作成」で自動生成
sam deleteLambda × 5 / ステートマシン / IAM ロール / ロググループを個別に削除

トラブルシューティング

症状原因対処
実行が即座に ExecutionFailed になるASL 内の Lambda ARN が間違っている① で控えた ARN と再照合する
「テンプレートを選択」を押してギャラリーが開いた新UI操作ミス✕で閉じ、モーダルから「自分で作成する」を選ぶ
「{ } コード」タブが見つからないモーダルが前面に出ている「続行」でモーダルを閉じてから Workflow Studio を操作する
HandleError に渡る error_cause が空Python 例外が Lambda レベルでハンドルされているコードの raise が正しく記述されているか確認
ProcessInParallel が一方しか実行されないParallel ブランチの定義ミスASL JSON の Branches 配列に2つの要素があるか確認
ConfirmFunction でエラー: list indices must be integersevent[0] / event[1] で取り出しているが、入力が配列でないProcessInParallel の直後にのみ呼ばれる関数かを確認する
ステートマシン削除後「削除中」のまま消えない実行中のワークフローが残っている実行一覧から実行中のものを停止してから再確認

まとめ

今回のハンズオンで体験できたこと:

確認項目内容
Task + Retry + CatchValidateOrder で注文検証 → リトライ → それでも失敗したらエラーハンドラへ
Parallel ステート在庫確認と支払い処理を同時実行し、両結果をリストで次へ渡す
ResultPath"$.error" でエラー情報を元の入力にマージ → エラーハンドラで参照
Workflow StudioASL コードと視覚フロー図を双方向で確認できる新UI
新UI操作3択モーダル → 「自分で作成する」→「{ } コード」タブ → 「設定」タブ の流れ

コンソール版とSAM版を比較してみる

コンソールでStep Functionsの概念を理解したら、SAMで同じ構成をコードで定義することで「SAMが何を自動化しているか」が明確になります。DefinitionSubstitutions による ARN の自動差し込みや、LambdaInvokePolicy によるワンライン権限付与など、コンソールでの手動操作がコードに対応しています。


関連記事

Amazon検索[本 AWS 開発]

コメント