EventBridge を使ったイベント駆動アーキテクチャを設計・運用するうえでの実践的な指針をまとめたもの。
目次
- コンポーネントの使い分け
- イベント設計
- イベントバスの構成
- ルールとフィルタリング
- 信頼性とエラーハンドリング
- アーカイブとリプレイ
- セキュリティ
- 可観測性
- クォータとパフォーマンス
- コスト最適化
- 開発・運用
- よくあるアンチパターン
1. コンポーネントの使い分け
| コンポーネント | 用途 | 選ぶ場面 |
|---|---|---|
| Event Bus | ルールに基づく多対多のイベントルーティング | 複数のコンシューマーにファンアウトしたい、サービス間を疎結合にしたい |
| Pipes | 1 ソース → 1 ターゲットのポイントツーポイント連携(フィルタ・エンリッチ付き) | SQS / Kinesis / DynamoDB Streams などから特定ターゲットへ流すだけ。Lambda の「つなぎコード」を消したい |
| Scheduler | 時刻ベース・定期実行のタスク起動 | cron / rate / 1 回限りの実行。大量のスケジュール管理 |
| Scheduled Rules(旧来) | ルールでの定期実行 | 新規では基本的に Scheduler を優先 |
- 定期実行は EventBridge Scheduler を使う。 タイムゾーン指定、1 回限りのスケジュール、フレキシブルタイムウィンドウ、リトライ/DLQ 設定、大量スケジュールへのスケールに対応しており、Scheduled Rules より機能が豊富。SDK 統合で多数の AWS API を Lambda なしで直接呼べる。
- 単純な 1 対 1 連携は Pipes を検討する。 ポーリング・バッチ・フィルタ・エンリッチメント・変換をマネージドで行えるため、中継用の Lambda を減らせる。
拡張版 Custom event bus について
2026年9月に、強化された Custom event bus が登場した(従来のバスは「Custom event bus - classic」に改称、既存 API は変更なし)。主な特徴:
- アカウント間でのバス共有
- 厳密な順序保証(strict ordering)とコンテンツベースの重複排除
- CloudEvents など JSON ベースのイベント形式をスキーマを変えずに発行できる新しい発行 API
- 組み込みのリテンション(デフォルト 24 時間、最大 1 年まで延長可)
- フィルタと配信先を定義する新しい Subscriber リソース
- イベント数ではなくデータ転送量に基づく課金
指針: 順序保証・長期リテンション・マルチアカウント共有が必要な新規ワークロードでは拡張版を評価する。ただし提供リージョンが限られているため、利用予定リージョンでの提供状況・料金・既存ツール(IaC、監視)の対応状況を確認してから採用を決めること。既存の classic バスを急いで移行する必要はない。
2. イベント設計
スキーマとエンベロープ
sourceとdetail-typeに命名規約を設ける。source: 逆ドメイン形式で発行元を表す(例:com.example.orders)。aws.プレフィックスは AWS 予約。detail-type: 過去形の業務イベント名(例:OrderPlaced,PaymentFailed)。
detail内にメタデータを持たせる。 バージョン、相関 ID、冪等性キーなどを定型化する。
{
"source": "com.example.orders",
"detail-type": "OrderPlaced",
"detail": {
"metadata": {
"version": "1",
"idempotencyKey": "order-12345-placed",
"correlationId": "c0a8-...",
"domain": "orders"
},
"data": {
"orderId": "12345",
"customerId": "C-001",
"totalAmount": 4800,
"currency": "JPY"
}
}
}- スキーマのバージョニングを最初から決めておく。 後方互換な変更(フィールド追加)を基本とし、破壊的変更は新しい
detail-typeまたはバージョンで出す。 - Schema Registry とスキーマディスカバリを活用する。 スキーマのドキュメント化とコードバインディング生成ができる。ただしディスカバリは開発・検証環境で有効にし、本番では必要に応じて(取り込みに課金されるため)。
- 業界標準形式を検討する。 チーム横断・社外連携があるなら CloudEvents のような形式を採用すると相互運用しやすい。
ペイロードの中身
- 「通知(thin)」か「状態転送(fat)」かを意図的に選ぶ。
- Thin イベント: ID だけを載せ、詳細はコンシューマーが取りに行く。結合は緩いがコールバックが発生する。
- Fat イベント: 必要な情報を載せ、コンシューマーは追加取得不要。プロデューサー側のスキーマ変更の影響が大きい。
- ペイロード上限は 1 MB に拡大された(一部リージョンを除く)が、大きなデータは S3 に置き参照を渡す(Claim Check パターン) 方が、コストと転送量の面で依然有利なことが多い。
- 個人情報・機密情報を不用意に載せない。 多数のコンシューマーやアーカイブに残る前提で設計する。
3. イベントバスの構成
- デフォルトバスは AWS サービスイベント用、アプリケーションイベントはカスタムバスへ。 権限・ルールの境界が明確になる。
- ドメイン(境界づけられたコンテキスト)単位でバスを分けるか、組織共通の単一バスにするかを決める。
- 単一の中央バス: 発見しやすく、ガバナンスを一元化できる。
- ドメイン別バス: 所有権が明確で、影響範囲を限定できる。
- マルチアカウントでは中央バス(ハブ)+各アカウントのバス(スポーク)を検討する。
- クロスアカウントは、ターゲットに別アカウントのバスを指定するか、直接クロスアカウントターゲット(SQS / Lambda など)を使う。
- リソースポリシーで
aws:PrincipalOrgIDなどを使い、Organizations 内に送信元を限定する。
- クロスリージョン配信は DR やリージョン集約に使えるが、遅延とデータ転送コストを考慮する。
4. ルールとフィルタリング
- イベントパターンはできるだけ具体的に書く。
sourceとdetail-typeは必ず指定し、必要ならdetailのフィールドまで絞る。曖昧なパターンは意図しないイベントにマッチし、無限ループやコスト増を招く。 - コンテンツフィルタリングを活用する。 prefix / suffix / anything-but / numeric / exists / wildcard /
$orなどで、ターゲット側でのフィルタ処理を減らす。 - 無限ループに注意する。 ルールのターゲットが、同じルールにマッチするイベントを発生させないようにする(例: S3 オブジェクト作成 → Lambda が同じバケットに書き込む)。
- 入力変換(Input Transformer)でターゲットが必要な形に整形する。 ターゲット側の解析コードを減らせる。
- 1 ルールあたりのターゲット数上限(5)を意識する。 それ以上のファンアウトは SNS / 別バスを挟むか、ルールを分ける。
- ルール名・説明に所有者と用途を明記し、タグを付ける。 誰のルールか分からない状態を避ける。
- パターンはテストする。
TestEventPatternAPI やコンソールのサンドボックスで、マッチ・非マッチの両方を CI で検証する。
5. 信頼性とエラーハンドリング
配信保証の前提
- EventBridge の配信は at-least-once(少なくとも 1 回)。重複配信は起こりうる。
- classic バスでは 順序は保証されない。順序が必要なら、拡張版バスの strict ordering、SQS FIFO、Kinesis などを使う。
冪等性
- コンシューマーは必ず冪等に実装する。 冪等性キー(イベント ID や業務キー)を DynamoDB の条件付き書き込みなどで記録し、重複処理を防ぐ。Powertools for AWS Lambda の Idempotency ユーティリティが便利。
リトライと DLQ
- すべてのターゲットに DLQ(SQS)を設定する。 デフォルトでは最大 24 時間・185 回リトライ後にイベントが破棄される。
- リトライポリシー(最大イベント経過時間・最大リトライ回数)をワークロードに合わせて調整する。 古いイベントが意味をなさない処理では短くする。
- DLQ を監視し、再処理手順(runbook)を用意する。 DLQ にメッセージが入ったらアラートを出す。
バッファリング
- Lambda を直接ターゲットにするより、SQS を挟む方が安全な場合が多い。 バーストの吸収、同時実行数の制御、部分失敗時の再処理がしやすい。
- API Destinations ではレート制限(invocation rate)を設定する。 外部 API の上限を超えないようにする。
発行側
PutEventsのレスポンスのFailedEntryCountを必ず確認する。 HTTP 200 でも一部のエントリが失敗していることがある。失敗分はリトライする。- バッチ発行(最大 10 件/リクエスト)でスループットとコストを最適化する。
- 確実な発行が必要なら Transactional Outbox パターンを使う。 DB 更新とイベント発行の不整合を防ぐ(DynamoDB Streams → Pipes → EventBridge など)。
6. アーカイブとリプレイ
- 重要なバスにはアーカイブを設定する。 障害復旧、バグ修正後の再処理、新しいコンシューマーへのデータ投入に使える。
- 保持期間を明確に決める。 無期限はコストとコンプライアンスの両面で注意。
- アーカイブ対象をイベントパターンで絞る。 すべてを保存する必要はない。
- リプレイ時は冪等性が前提。 リプレイされたイベントは
replay-nameフィールドで判別できるため、外部通知などの副作用は抑制できるようにしておく。 - 拡張版バスでは組み込みリテンションがあるため、要件次第でアーカイブとの役割分担を検討する。
7. セキュリティ
- 最小権限の原則。
- プロデューサーには対象バスへの
events:PutEventsのみを付与し、必要ならevents:source条件キーで発行できるsourceを制限する。 - ルールのターゲット呼び出し用 IAM ロールも、ターゲットごとに最小権限で作る。
- プロデューサーには対象バスへの
- バスのリソースポリシーで送信元アカウント/組織を限定する。
- 暗号化。 機密性の高いデータを扱う場合はカスタマー管理 KMS キーで暗号化する(アーカイブ・DLQ も含めて)。
- API Destinations の認証情報は Connection 経由で管理する。 認証情報は Secrets Manager に保存される。コードやパラメータに直書きしない。
- VPC 内からの発行には VPC エンドポイント(PrivateLink)を使う。
- CloudTrail で管理 API(ルールの作成・変更・削除など)を監査する。
8. 可観測性
- CloudWatch メトリクスを監視・アラーム化する。
FailedInvocations: ターゲット呼び出しの失敗ThrottledRules: スロットリングDeadLetterInvocations: DLQ への送信InvocationsFailedToBeSentToDlq: DLQ 送信の失敗(イベント消失のサイン、最重要)MatchedEvents/Invocations: 想定どおり流れているか(急減も異常)IngestionToInvocationStartLatency: 遅延
- 相関 ID を全イベントに含め、構造化ログで追跡できるようにする。
- AWS X-Ray のトレースコンテキストを伝播させる。
- ログ出力を有効化する。 バスのログ機能でイベントの取り込み・配信状況を確認できる。デバッグ時は CloudWatch Logs をターゲットにした「キャッチオール」ルールを一時的に作るのも有効(本番で常時有効にする場合はコストと機密情報に注意)。
- イベントカタログを整備する。 どのイベントを誰が発行し、誰が購読しているかを可視化する(Schema Registry や EventCatalog などのツール)。
9. クォータとパフォーマンス
PutEventsのスループットクォータ(リージョン・アカウント単位)を確認し、必要なら事前に引き上げ申請する。- ターゲット側の同時実行・スロットリングがボトルネックになりやすい。 Lambda の予約同時実行数、外部 API のレート制限と合わせて設計する。
- ルール数・ターゲット数の上限を把握する。 ルールが増えすぎる場合はバスの分割を検討する。
- EventBridge は低遅延だが、ミリ秒単位のリアルタイム性が必須の処理には向かない。その場合は Kinesis や直接呼び出しを検討する。
10. コスト最適化
- 不要なイベントを発行しない・不要なルールを作らない。 カスタムイベントは発行件数で課金される(classic バスの場合。拡張版はデータ転送量ベース)。
- ペイロードサイズを意識する。 classic バスでは 64 KB 単位で 1 イベントとして課金される。
- AWS サービスイベント(デフォルトバス)は無料だが、クロスアカウント配信やアーカイブには課金される。
- アーカイブの対象と保持期間を絞る。
- Pipes のフィルタで早めに絞り込む。 フィルタで除外されたイベントは課金対象外。
- スキーマディスカバリは本番で常時有効にしない。
11. 開発・運用
- IaC(CloudFormation / CDK / SAM / Terraform)で管理する。 コンソールでの手動変更はドリフトの原因になる。
- ルールとターゲットは、コンシューマー側のスタックで所有する。 プロデューサーはコンシューマーを知らない、という疎結合の原則を IaC の構成にも反映させる。
- 環境(dev / stg / prod)ごとにバスまたはアカウントを分離する。
- テスト戦略。
- ユニット: イベントパターンのテスト、ハンドラーのテスト
- 統合: 実際のバスにテストイベントを送り、テスト用ルール(SQS や CloudWatch Logs をターゲット)で受信を検証
- 契約テスト: プロデューサーとコンシューマー間のスキーマ互換性
- イベントのドキュメント化と変更プロセスを定める。 破壊的変更の事前告知、旧バージョンの非推奨期間など。
12. よくあるアンチパターン
| アンチパターン | 問題 | 対策 |
|---|---|---|
| コンシューマーが冪等でない | 重複配信で二重処理 | 冪等性キーで重複排除 |
| DLQ 未設定 | リトライ枯渇でイベントが無言で消える | 全ターゲットに DLQ + アラーム |
PutEvents の部分失敗を無視 | イベントの取りこぼし | FailedEntryCount を確認してリトライ |
| 曖昧なイベントパターン | 意図しないマッチ、無限ループ | source / detail-type を必ず指定 |
| EventBridge をリクエスト/レスポンスに使う | 同期応答が必要な処理には不向き | API Gateway / 直接呼び出し、または非同期化 |
| 順序に依存した処理を classic バスで実装 | 順序が保証されない | 拡張版バスの順序保証 / SQS FIFO / Kinesis |
| 単純な 1:1 連携を Event Bus + Lambda で実装 | 余計なコードとコスト | Pipes を使う |
| 定期実行を Scheduled Rules で大量に作成 | 管理しにくい、機能不足 | EventBridge Scheduler |
| 巨大なペイロードをそのまま流す | コスト増、機密情報の拡散 | Claim Check パターン |