Amazon EventBridge の新しいカスタムイベントバスを CLI で試してみた

Amazon EventBridge の新しいカスタムイベントバスを CLI で試してみた

Amazon EventBridge のカスタムイベントバス新方式を aws eventbridgev2 で試しました。put-events と put-raw-events で届く形とフィルタが変わり、新規なら put-raw-events、Classic 互換なら put-events です。
2026.09.25

はじめに

2026年09月24日、新しいカスタムイベントバスがリリースされました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/09/eventbridge-relaunches-custom-event-buses/

新方式では、24時間の組み込みリテンションが付き、最大1年まで延長できるようになりました。課金体系は従来のイベント数ベースではなく転送データ量ベースで、提供リージョンは東京を含む14リージョンです。

新方式の追加に伴い、従来のカスタムイベントバスは Custom event bus - classic に改称されました。

今回、シングルアカウント・SQS 宛ての構成で、新しいカスタムイベントバスを作成し、イベントを publish して、配信先で本文を受け取るまでを CLI で確かめました。

コンソールのバス作成画面

コンソールのバス作成画面では、Bus type が Custom event bus (recommended) と Custom event bus - classic の2択になっており、前者に New バッジが付いています。

新方式と Classic を選べる EventBridge のバス作成画面

左メニューでも Event buses に New バッジが付き、Classic のルーティングは Classic event routing という別グループに分かれています。

Event buses に New バッジが付き、Classic event routing が別グループに分かれた EventBridge コンソール

既存バスの改称について、コンソールのモーダルは「This is a name change only. All other functionality works exactly as before, and you can continue to create and manage Classic event buses.」と案内しています。

検証環境

東京リージョン(ap-northeast-1)で、次の AWS CLI を使いました。

$ aws --version
aws-cli/2.37.2 Python/3.14.6 Linux/7.1.13-402.asahi.fc44.aarch64+16k

リテンション付きでバスを作る

新方式のバスは、Classic の aws events とは別のサービス名 aws eventbridgev2 で操作します。

リテンションは作成時の --storage-configuration で指定します。ここでは7日を指定しました。

$ aws eventbridgev2 create-event-bus \
    --name eb-v2-verify \
    --description "Verification bus for the new custom event bus" \
    --storage-configuration RetentionPeriodInDays=7
{
    "EventBusArn": "arn:aws:events:ap-northeast-1:123456789012:event-busv2/eb-v2-verify/0flgsossjby9l8ls5jd55eb7z",
    "Name": "eb-v2-verify",
    "Description": "Verification bus for the new custom event bus",
    "StorageConfiguration": {
        "RetentionPeriodInDays": 7,
        "RetentionWindowStartTime": "2026-09-25T09:59:28.956000+09:00"
    },
    "State": "CREATING",
    "CreationTime": "2026-09-25T09:59:29.014000+09:00"
}

ARN の形は Classic の event-bus/<name> から event-busv2/<name>/<生成ID> に変わり、末尾の ID は EventBridge が付与します。バス名から ARN を組み立てることはできず、describe-event-bus や Subscriber の作成でもバスは ARN で指定します。

そのため、作成応答の EventBusArn を控えておきます。以降のコマンドではこれを BUS_ARN として使います。

$ BUS_ARN=arn:aws:events:ap-northeast-1:123456789012:event-busv2/eb-v2-verify/0flgsossjby9l8ls5jd55eb7z

作成直後は State が CREATING で返り、少し待つと ACTIVE になります。

Subscriber で SQS へ配信する

新方式では、ルールとターゲットの代わりに Subscriber を作って配信先を指定します。必須パラメータは --name、--event-bus-arn、--invoke-configuration の3つで、フィルタや Transformer は任意です。今回は Subscriber を3本作りました。put-events 用、put-raw-events 用、順序確認用の FIFO です。SQS は配信先の3キューと DLQ の計4本を用意しました。

$ aws eventbridgev2 create-subscriber \
    --name sub-raw \
    --event-bus-arn "$BUS_ARN" \
    --type UNORDERED \
    --filter-configuration '{"Filters":[{"Scope":"DATA","Pattern":"{\"data\":{\"amount\":[{\"numeric\":[\">\",500]}]}}"}]}' \
    --transformer '{"Type":"WITH_METADATA"}' \
    --invoke-configuration '{"TargetArn":"arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-raw-q","RoleArn":"arn:aws:iam::123456789012:role/eb-v2-delivery-role"}' \
    --on-failure-configuration '{"Arn":"arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-dlq"}'
{
    "SubscriberArn": "arn:aws:events:ap-northeast-1:123456789012:subscriber/sub-raw/dm1qvl9dd5p8iyr8946yanvc2",
    "Name": "sub-raw",
    "Type": "UNORDERED",
    "StartingPosition": "LATEST",
    "State": "RUNNING",
    "CreationTime": "2026-09-25T10:01:38.135000+09:00"
}

StartingPosition の既定値は LATEST なので、Subscriber 作成より前に publish したイベントは届きません。動作確認では Subscriber を先に作ります。

配信の権限は、キューのリソースポリシーではなく Subscriber に渡す IAM ロールで与えます。ロールには配信先のキューと、OnFailureConfiguration に指定した DLQ への sqs:SendMessage を含めます。KMS とクロスアカウント共有は今回扱いません。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-subscribers.html

配信ロールの信頼ポリシーと権限ポリシー

信頼ポリシーは検証で使った最小の形で、aws:SourceAccount や aws:SourceArn による呼び出し元の絞り込みは入れていません。共用アカウントで使うなら、これらの条件キーで信頼する呼び出し元を限定します。

信頼ポリシー(trust.json として保存し aws iam create-role --role-name eb-v2-delivery-role --assume-role-policy-document file://trust.json に渡しました):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "events.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}

権限ポリシー(perm.json として保存し aws iam put-role-policy --role-name eb-v2-delivery-role --policy-name send-to-queues --policy-document file://perm.json に渡しました):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sqs:SendMessage",
      "Resource": [
        "arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-events-q",
        "arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-raw-q",
        "arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-ordered-q.fifo",
        "arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-dlq"
      ]
    }
  ]
}

リトライとバッチは指定しなくても既定値が入ります。

`describe-subscriber` で見える既定値
$ aws eventbridgev2 describe-subscriber --subscriber-arn "$SUB_ARN"
{
    "InvokeConfiguration": {
        "RoleArn": "arn:aws:iam::123456789012:role/eb-v2-delivery-role",
        "TargetArn": "arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-raw-q"
    },
    "FilterConfiguration": {
        "Language": "EVENT_BRIDGE_PATTERN",
        "Filters": [
            { "Pattern": "{\"data\":{\"amount\":[{\"numeric\":[\">\",500]}]}}", "Scope": "DATA" }
        ]
    },
    "Type": "UNORDERED",
    "StartingPosition": "LATEST",
    "BatchConfiguration": { "MaxBatchSize": 10, "MaxBatchWindowInSeconds": 0 },
    "Transformer": { "Type": "WITH_METADATA" },
    "RetryPolicy": { "MaxRetryAttempts": 5, "MaxEventAgeInSeconds": 300, "RetryStrategy": "ALL" },
    "OnFailureConfiguration": { "Arn": "arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-dlq" },
    "State": "RUNNING"
}

put-events と put-raw-events で届く形が変わる

publish の API は2つあります。put-events は Source・DetailType・Detail を取る Classic に近い形、put-raw-events は Data にペイロードそのものを渡す形です。

put-raw-events の Data は base64 blob です。AWS CLI の既定の binary format では、渡した JSON を base64 として解釈しようとして失敗します。

$ aws eventbridgev2 put-raw-events --event-bus-arn "$BUS_ARN" \
    --entries '[{"Data":"{\"specversion\":\"1.0\", ...}", ...}]'

aws: [ERROR]: Invalid base64: "{\"specversion\":\"1.0\", ...}"

CLI から生の JSON を渡すには --cli-binary-format raw-in-base64-out を付けます。次は、両 API で同じ注文データを publish した結果です。put-raw-events 側は CloudEvents の形にしました。

$ aws eventbridgev2 put-events --event-bus-arn "$BUS_ARN" \
    --entries '[{"Source":"com.example.myapp","DetailType":"OrderCreated",
      "Detail":"{\"orderId\":\"ORD-101\",\"amount\":1980}",
      "SystemMetadata":{"EventGroupId":"customer-1"}}]'
{
    "FailedEntryCount": 0,
    "Entries": [
        { "EventId": "9d46baf1-640c-4663-9417-9d0e5dc65200", "SequenceNumber": "10000000000000003000", "SuccessCode": "PUBLISHED" }
    ]
}

$ aws eventbridgev2 put-raw-events --cli-binary-format raw-in-base64-out --event-bus-arn "$BUS_ARN" \
    --entries '[{"Data":"{\"specversion\":\"1.0\",\"type\":\"com.example.order.created\",\"source\":\"com.example.myapp\",\"id\":\"ce-101\",\"time\":\"2026-09-25T01:00:00Z\",\"datacontenttype\":\"application/json\",\"data\":{\"orderId\":\"ORD-101\",\"amount\":1980}}",
      "Metadata":{"producer":"checkout-service"},
      "SystemMetadata":{"ContentType":"application/json","EventGroupId":"customer-1"}}]'
{
    "FailedEntryCount": 0,
    "Entries": [
        { "EventId": "9944a059-17d2-4665-a323-d0bd3cb6530a", "SequenceNumber": "10000000000000004000", "SuccessCode": "PUBLISHED" }
    ]
}

SystemMetadata.ContentType に指定できるのは application/json / application/avro / application/protobuf / application/octet-stream です。CloudEvents は application/json として送ります。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-open-formats.html

配信先で受け取る形は、publish API と Subscriber の Transformer の組み合わせで決まります。まず、Transformer を指定しない Subscriber で put-events のイベントを受けると、届くのはユーザーガイドで envelope と呼ばれている構造だけです。ペイロードを detail に包む構造は Classic と同じで、Metadata と SystemMetadata は本文に含まれません。

`Transformer` 指定なしの Subscriber で `put-events` を受けた本文
{
  "version": "0",
  "id": "df3e557b-6282-4df1-84c5-1e8956a533e0",
  "detail-type": "OrderCreated",
  "source": "com.example.myapp",
  "account": "123456789012",
  "time": "2026-09-25T01:02:36Z",
  "region": "ap-northeast-1",
  "resources": [],
  "detail": { "orderId": "ORD-101", "amount": 1980 }
}

Transformer: WITH_METADATA の Subscriber で put-raw-events のイベントを受け取ると、本文は次のようになります。

{
  "Data": {
    "specversion": "1.0",
    "type": "com.example.order.created",
    "source": "com.example.myapp",
    "id": "ce-101",
    "time": "2026-09-25T01:00:00Z",
    "datacontenttype": "application/json",
    "data": { "orderId": "ORD-101", "amount": 1980 }
  },
  "Metadata": { "producer": "checkout-service" },
  "SystemMetadata": {
    "EventGroupId": "customer-1",
    "DeduplicationId": "47befe33-072e-4afd-86d1-0d89ef4216d4",
    "ContentType": "application/json",
    "aws:IngestionTime": "2026-09-25T01:02:58.740Z",
    "aws:EventId": "9944a059-17d2-4665-a323-d0bd3cb6530a",
    "aws:SequenceNumber": "10000000000000004000",
    "aws:DeliveryType": "LIVE"
  }
}

送った CloudEvents の JSON が Data にそのまま入っており、EventBridge のエンベロープで包み直されて二重になることはありません。受信側ではそのまま CloudEvents として扱えます。Metadata には publish 時に付けたキーが入り、EventBridge が付与する値は SystemMetadata に分かれます。

フィルタは publish API に合わせて書く

フィルタは、配信されるデータ構造に合わせて書きます。同じ「amount が500を超える」という条件でも、起点のキーが publish API によって変わります。

publish API フィルタのパターン amount: 1980 amount: 100
put-events {"detail":{"amount":[{"numeric":[">",500]}]}} 届く 届かない
put-raw-events {"data":{"amount":[{"numeric":[">",500]}]}} 届く 届かない
両 API(フィルタなしの Subscriber) — 届く 届く

起点を取り違えたフィルタはエラーにならず、どのイベントにもマッチしないまま動作します。

順序保証と重複排除

順序が必要なら Subscriber を --type FIFO で作ります。SQS の FIFO キューへ配信するには MessageGroupId が必要で、JSONata 式で publish 時の EventGroupId を渡せます。配信先の FIFO キューは FifoQueue=true,ContentBasedDeduplication=true で作りました。

$ aws eventbridgev2 create-subscriber \
    --name sub-fifo \
    --event-bus-arn "$BUS_ARN" \
    --type FIFO \
    --invoke-configuration '{"TargetArn":"arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-ordered-q.fifo","RoleArn":"arn:aws:iam::123456789012:role/eb-v2-delivery-role","SqsParameters":{"MessageGroupId":"{% $events.SystemMetadata.EventGroupId %}"}}' \
    --on-failure-configuration '{"Arn":"arn:aws:sqs:ap-northeast-1:123456789012:eb-v2-dlq"}'
{
    "SubscriberArn": "arn:aws:events:ap-northeast-1:123456789012:subscriber/sub-fifo/dl7sjpulnlearuy29hne8lr75",
    "Name": "sub-fifo",
    "Type": "FIFO",
    "StartingPosition": "LATEST",
    "State": "RUNNING",
    "CreationTime": "2026-09-25T10:01:49.110000+09:00"
}

EventGroupId を customer-1 に揃えて、ORD-201 から ORD-205 までを1件ずつ publish しました。FIFO キューには publish した順に届き、SQS 側の SequenceNumber も昇順でした。

// eb-v2-ordered-q.fifo(FIFO Subscriber)での到着順
[
  { "orderId": "ORD-201", "MessageGroupId": "customer-1", "SqsSequenceNumber": "18905060493981423616" },
  { "orderId": "ORD-202", "MessageGroupId": "customer-1", "SqsSequenceNumber": "18905060494079727616" },
  { "orderId": "ORD-203", "MessageGroupId": "customer-1", "SqsSequenceNumber": "18905060494186223616" },
  { "orderId": "ORD-204", "MessageGroupId": "customer-1", "SqsSequenceNumber": "18905060494296303616" },
  { "orderId": "ORD-205", "MessageGroupId": "customer-1", "SqsSequenceNumber": "18905060494416111872" }
]

同じイベントを --type UNORDERED の Subscriber でも受けたところ、ORD-202 → 205 → 201 → 203 → 204 の順で届きました。

重複排除は publish 側の設定です。put-events に --deduplication-configuration DeduplicationType=CONTENT_BASED を付けて、同一内容を2回続けて publish しました。

// 1回目
{ "EventId": "f6fda443-afe5-4daa-a971-d254be085d74", "SequenceNumber": "10000000000000012000", "SuccessCode": "PUBLISHED" }
// 2回目(同じコマンド)
{ "EventId": "f6fda443-afe5-4daa-a971-d254be085d74", "SequenceNumber": "10000000000000012000", "SuccessCode": "DEDUPLICATED" }

2回目は SuccessCode が DEDUPLICATED になり、EventId と SequenceNumber は1回目と同じでした。配信先に届いたのも1件です。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-ordering.html

Classic から移すときに変わる3点

同一アカウント内で SQS に配信する構成を Classic と新方式の両方で組みました。

Classic(aws events) 新方式(aws eventbridgev2)
バス ARN event-bus/<name> event-busv2/<name>/<生成ID>。名前から組み立てられない
SQS への配信権限 キューのリソースポリシー Subscriber に渡す IAM ロール
publish 応答の EventId 配信された本文の id と一致 一致しない。SystemMetadata.aws:EventId が一致する

ユーザーガイドでは、JSON のイベントで Classic と同じエンベロープが欲しい場合は put-events を選ぶよう案内しています。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-custom-bus-publish.html

エンベロープの構造は実測でも Classic と同じでした。次は、この確認のために別途作成したバスに Transformer: WITH_METADATA の Subscriber を1本用意し、put-events のイベントを受けた結果です。

// publish 応答
{ "EventId": "0d8fd5c4-524b-4d4f-9149-b11cd66aecfd", "SuccessCode": "PUBLISHED" }

// SQS で受け取った本文
{
  "Data": {
    // version / source / account / time / region / resources は省略
    "id": "3027f30e-bfb2-4ab5-a5e5-d6b67c5790a4",
    "detail-type": "OrderCreated",
    "detail": { "orderId": "ORD-401", "amount": 1980 }
  },
  "Metadata": {},
  "SystemMetadata": {
    // EventGroupId / DeduplicationId / aws:IngestionTime は省略
    "ContentType": "application/eventbridge+json",
    "aws:Source": "com.example.myapp",
    "aws:DetailType": "OrderCreated",
    "aws:EventId": "0d8fd5c4-524b-4d4f-9149-b11cd66aecfd",
    "aws:SequenceNumber": "10000000000000003000",
    "aws:DeliveryType": "LIVE"
  }
}

put-events では、ペイロードは Data の下の detail に入り、SystemMetadata.ContentType には EventBridge が application/eventbridge+json を設定します(put-raw-events では publish 時に指定した値、今回は application/json)。受信側はこの値で put-events 経由かを判別できます。

publish 応答の EventId は、配信された本文の id ではなく SystemMetadata.aws:EventId と一致します。EventId で publish と配信を突き合わせているなら、Subscriber の Transformer を WITH_METADATA にして SystemMetadata.aws:EventId を参照してください。

まとめ

新方式のカスタムイベントバスで最初に決めるのは、put-events と put-raw-events のどちらで publish するかです。ここで配信先に届く形が決まります。

新規に組むなら put-raw-events をおすすめします。ユーザーガイドは put-events を「Classic と同じエンベロープが欲しい場合」、put-raw-events を「ペイロードをそのまま届けたい、独自のメタデータを付けたい、JSON 以外を扱う場合」と使い分けており、Classic 互換が要らないなら後者に当てはまります。送った JSON がエンベロープに包まれずそのまま届くので、CloudEvents のようにスキーマが決まっている形式を、受信側で EventBridge 独自のエンベロープから取り出す処理を挟まずにそのまま扱えます。Step Functions のように JSONata で入力を参照するターゲットでも、detail を1段掘らずにペイロードを扱えるようになると期待できます。

Classic との互換性を保つなら put-events です。Classic と同じ構造のエンベロープを作るので、既存の受信処理とフィルタパターンをそのまま使えます。

今回取り上げなかった AWS RAM による他アカウントや Organizations へのバス共有については、追って検証して紹介する予定です。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事