「状態」ではなく「変化」を軸にする設計思想

サービス間の通信が同期的なAP``I呼び出しに依存しすぎると、1つの障害がシステム全体を停止させるリスクを抱えます。イベント駆動アーキテクチャ(Event-Driven Architecture、略称EDA)は、この問題を根本から解消するソフトウェアアーキテクチャパターンです。

EDAの核心は「現在の状態」ではなく「状態の変化」をシステム設計の中心に据える点にあります。「注文が作成された」「在庫が減った」「決済が完了した」といった状態変化をイベントとして発行し、関心のあるコンポーネントがそれを受信して処理します。送信側は受信側の存在を知る必要がなく、受信側は送信側の実装詳細に依存しません。

イベントドリブンとは何か

イベントドリブン(イベント駆動型)とは、外部からの要求や状態変化を「イベント」として検知し、それに反応して処理を実行する方式の総称です。従来の同期型リクエスト/レスポンスモデルでは、呼び出し元が処理の完了を待ち続ける必要がありました。EDAではイベントの発行と消費が非同期に行われるため、各コンポーネントが独立して動作できます。

「イベント駆動型プログラミング」との違い

イベント駆動型プログラミングとイベント駆動アーキテクチャは、同じ「イベント駆動」という名前でも適用範囲が異なります。

観点イベント駆動型プログラミングイベント駆動アーキテクチャ
適用範囲単一プロセス内分散システム全体
イベントの例マウスクリック、キー入力注文確定、決済完了、在庫変動
通信方式プロセス内コールバックメッセージブローカー経由
代表技術GUIフレームワーク、JavaScript DOMApache Kafka、AWS EventBridge

イベント駆動方式とは、上記いずれの文脈でも「イベントの発生をトリガーとして処理を実行する手法」を指しますが、本記事ではシステム間の連携を扱うアーキテクチャレベルのEDAに焦点を当てます。

EDAを構成する3つの基本要素

EDAは3つの役割を持つコンポーネントで構成されます。

イベント駆動アーキテクチャの3構成要素:Producer(注文・決済・ユーザーサービス)がEvent Broker(Kafka/EventBridge)にイベントを発行し、Consumer(在庫・通知・分析サービス)に配信される構成図

プロデューサー(イベント発行者) は、状態変化が発生したときにイベントを生成してブローカーに送信します。プロデューサーはイベントの消費先を意識しません。

イベントブローカー / チャネル(仲介者) は、プロデューサーから受け取ったイベントを適切なコンシューマーに配信します。Apache Kafka、Amazon EventBridge、Google Cloud Pub/SubなどがブローカーやチャネルとしてBrokerの役割を担います。

コンシューマー(イベント消費者) は、関心のあるイベントをブローカーから受信し、自身の責務に応じた処理を実行します。1つのイベントを複数のコンシューマーが並行して処理できる点が、同期呼び出しとの大きな違いです。

同期型設計の限界とEDAが求められる背景

リクエスト/レスポンス型が抱える密結合

同期型アーキテクチャでは、サービスAがサービスBのAPIを直接呼び出し、レスポンスを待って次の処理に進みます。サービスBが遅延すればサービスAも遅延し、サービスBが停止すればサービスAも処理を継続できません。サービスが増えるほどこの依存関係は複雑化し、カスケード障害のリスクが高まります。

手続き型アプローチとの根本的な違い

手続き型(プロシージャル)設計では、処理の順番を上から下へ明示的に記述します。一方、イベント駆動型設計では処理の実行順序はイベントの発生タイミングに委ねられます。

観点手続き型イベント駆動型
処理の流れ呼び出し順に逐次実行イベント発生時に非同期実行
結合度呼び出し先を直接参照(密結合)ブローカー経由で間接参照(疎結合)
スケーリングボトルネック箇所の特定が難しいコンシューマー単位で個別スケール可能
障害の影響範囲呼び出しチェーン全体に波及イベント未処理分のみ影響

マイクロサービスとEDAの相互補完

マイクロサービスアーキテクチャでサービスを細分化しても、サービス間通信が同期RPCのままではモノリスの密結合問題をネットワーク上に再現するだけです。EDAは、マイクロサービス間の連携を非同期イベントで行うことで、真の疎結合を実現します。

4つの主要な設計パターン

Pub/Sub(発行 / 購読)モデル

Pub/Subは、プロデューサーが「トピック」にイベントを発行し、そのトピックを購読するすべてのコンシューマーにイベントが配信されるモデルです。新しいコンシューマーを追加してもプロデューサー側の変更は不要で、拡張性に優れます。Amazon SNS + SQS、Google Cloud Pub/Sub、Azure Service Busなどがこのモデルを提供しています。

イベントストリーミング

イベントストリーミングは、イベントを永続的なログとして順序付きで保存し、コンシューマーが任意の時点からイベントを再読み込みできるモデルです。Apache Kafkaが代表的な実装です。Pub/Subとの最大の違いは、イベントが配信後も保持される点にあります。過去のイベントを再処理(リプレイ)できるため、新しいコンシューマーの追加やデータ復旧が容易です。

ブローカートポロジーとメディエータートポロジー

Microsoftの Azure Architecture Center のドキュメントでは、EDAの構造を2つのトポロジーに分類しています。

特性ブローカートポロジーメディエータートポロジー
制御方式中央制御なし。各コンシューマーが自律判断中央のオーケストレーターがフロー制御
柔軟性高い。新規コンシューマー追加が容易フロー変更にはオーケストレーター修正が必要
フローの可視性低い。全体の処理経路を追跡しにくい高い。処理フロー全体を一元管理
障害リスク個別コンシューマーの障害に局所化オーケストレーターが単一障害点(SPOF)になりうる
適用例Kafka + 自律コンシューマー群AWS Step Functions, Azure Durable Functions

ブローカー型は各コンシューマーが独立して判断するため柔軟性が高い反面、処理フロー全体の把握には分散トレーシングなどの観測基盤が必要です。メディエータ型はワークフロー全体の可視性と制御性に優れますが、オーケストレーターの設計がシステムの信頼性を左右します。

イベント処理の3段階:SEP・ESP・CEP

イベントの処理方式は、扱うイベントの複雑さに応じて3段階に分類されます。

SEP(Simple Event Processing) は、単一のイベントに対して即座に反応する最もシンプルな処理です。「注文を受信したら確認メールを送信する」「ファイルがアップロードされたらサムネイルを生成する」といったケースが該当します。

ESP(Event Stream Processing) は、連続するイベントの流れ(ストリーム)をパイプラインで処理します。Webサイトのクリックストリーム分析、リアルタイムのログ集約、センサーデータのフィルタリングなど、時系列データを継続的に処理する場面で利用されます。Apache Kafka StreamsやApache Flinkが代表的なESPエンジンです。

CEP(Complex Event Processing) は、複数のイベントソースからのデータを相関分析し、パターンを検出して高次の判断を下します。「同一クレジットカードで10分以内に3か国から決済が発生」というパターン検出による不正利用検知や、複数センサーの異常値の組み合わせによる設備故障予測などがCEPの典型例です。

CQRSとイベントソーシング

CQRS(コマンドクエリ責務分離)

CQRSは、データの書き込み操作(コマンド)と読み取り操作(クエリ)を別々のモデル・ストアに分離するパターンです。ECサイトを例にとると、商品の注文処理(書き込み)と商品一覧の表示(読み取り)では、アクセスパターンもスケーリング要件も大きく異なります。CQRSを導入すると、読み取り側は検索に最適化されたデータストア(Elasticsearch等)を使い、書き込み側はトランザクション処理に強いRDBを使うといった使い分けが可能になります。

EDAとの組み合わせでは、コマンド側が書き込みイベントを発行し、クエリ側がそのイベントを受信して読み取り用ビューを非同期に更新する構成が一般的です。

イベントソーシング

イベントソーシングは、エンティティの「現在の状態」ではなく「状態に至るまでのイベント履歴」をすべて保存する手法です。

観点従来のCRUDイベントソーシング
保存対象最新の状態のみすべてのイベント(変更履歴)
状態の復元DBの現在値を参照イベントを先頭から再生
監査対応別途ログ実装が必要イベントログ自体が監査証跡
データ修正UPDATEで上書き補正イベントを追記
ストレージ状態のみで省スペースイベント蓄積で容量増大

たとえば銀行口座の残高管理では、「入金10,000円」「出金3,000円」「入金5,000円」という3つのイベントを保存し、再生することで現在残高12,000円を算出します。途中の状態をいつでも再現できるため、会計監査や障害後のデータ復旧に強い利点があります。

EDA導入で得られる5つのメリット

1. 疎結合による耐障害性の向上

プロデューサーとコンシューマーがブローカーを介して間接的にやり取りするため、一方のサービスが停止しても他方への影響が限定されます。コンシューマーの障害時はブローカーがイベントを保持し、復旧後に処理を再開できます。

2. リアルタイム応答とスケーラビリティ

イベント発生と同時に処理が開始されるため、ポーリングのような遅延がありません。また、負荷が高いコンシューマーだけを水平スケールさせることで、システム全体のリソース効率を最適化できます。

3. サービスの独立デプロイと開発速度の向上

各サービスがイベントの「契約」(スキーマ)のみを共有し、内部実装は自由に変更できます。チーム単位での独立デプロイが可能になり、リリースサイクルが短縮されます。

4. 監査・履歴トレーサビリティ

イベントログは「何が」「いつ」「どの順序で」発生したかの完全な記録です。イベントソーシングと組み合わせれば、任意の時点のシステム状態を再現でき、コンプライアンス対応や障害分析に活用できます。

5. push型配信によるインフラコスト削減

AWSの公式ドキュメントでは、EDAのコスト面の利点として、ポーリング型と比較したCPU遊休コストと帯域消費の削減が強調されています(出典: AWS)。ポーリング型では変更がなくてもコンシューマーが定期的にリソースを確認し続けるため、無駄なCPUサイクルとネットワーク帯域を消費します。push型のEDAでは、イベントが発生したときだけ処理が走るため、アイドル時のコストがほぼゼロになります。

見落としがちなデメリットと運用上の落とし穴

デバッグ・障害調査の複雑さ

同期型システムではスタックトレースを追えば処理の流れを把握できますが、EDAでは1つのリクエストが複数のサービスを非同期に横断するため、ログの時系列を追うだけでは因果関係を特定できません。OpenTelemetryなどのオブザーバビリティフレームワークを導入し、イベントにコリレーションIDを付与して処理フロー全体を可視化する仕組みが必須です。

メッセージ配信保証と冪等性設計

分散システムにおけるメッセージ配信には3つのセマンティクスがあり、選択を誤ると重複処理やデータ欠損の原因になります。

配信保証特性リスク適用場面
At-most-once最大1回配信。失敗時は再送しないイベント欠損の可能性ログ収集など欠損許容
At-least-once最低1回配信。失敗時は再送する重複配信の可能性多くの業務システム
Exactly-once正確に1回配信実装コストが高い金融取引など厳密さが必要

現実的にはAt-least-onceを採用し、コンシューマー側で冪等性を確保するアプローチが主流です。冪等キー(リクエストごとの一意なID)をイベントに含め、処理済みIDを記録して重複を検出する方法が一般的です。

Fatイベント vs Thinイベントの設計判断

イベントのペイロード(データ本体)に何をどこまで含めるかは、EDA設計の重要な意思決定ポイントです。

観点FatイベントThinイベント
ペイロード内容エンティティの全フィールドイベント種別 + エンティティID のみ
コンシューマーの自己完結性高い。追加API呼び出し不要低い。詳細データを別途取得が必要
ネットワーク負荷イベントサイズが大きいイベントサイズは最小限
データ整合性イベント発行時点のスナップショット常に最新データを取得可能
推奨シーンコンシューマーが多く、低レイテンシが重要エンティティの変更頻度が高い

どちらが正解というわけではなく、コンシューマーの数やレイテンシ要件、データの変更頻度に応じて使い分ける必要があります。

デッドレターキューとリトライ戦略

コンシューマーが処理に失敗したイベントを無限にリトライすると、システム全体のスループットが低下します。一般的には指数バックオフ(1秒→2秒→4秒→…)でリトライ回数を制限し、上限に達したイベントはデッドレターキュー(DLQ)に退避させます。DLQに溜まったイベントは、障害原因を特定・修正した後にバッチで再処理します。サーキットブレーカーパターンとの併用で、障害が連鎖しない仕組みも合わせて構築することが重要です。

クラウド別EDAサービス比較

3大クラウドはそれぞれEDA向けのマネージドサービスを提供しています。

プロバイダーイベントルーティングメッセージキューストリーミングワークフロー制御料金体系
AWSEventBridgeSQSKinesis Data StreamsStep Functionsイベント数課金(EventBridge: 100万件あたり$1.00)
AzureEvent GridService BusEvent HubsDurable Functionsイベント数 + スループット単位課金
Google CloudEventarc- (Pub/Subが兼務)Pub/SubWorkflowsメッセージ量課金(Pub/Sub: 10GBまで無料)

AWS は最もサービスの種類が多く、EventBridgeをハブとしてSNS/SQS/Step Functionsを組み合わせる構成が公式で推奨されています。200以上のAWSサービスからイベントを自動取得でき、さらにShopifyやDatadogなど多数のSaaSパートナーとも連携可能なEventBridgeの統合力が強みです。

Azure はEvent GridとEvent Hubsで用途を明確に分けている点が特徴です。Event Gridは軽量なイベントルーティング、Event Hubsは高スループットのストリーム処理に特化しています。

Google Cloud はPub/Subがキューイングとストリーミングの両方を兼ね、Eventarcがトリガー管理を担うシンプルな構成です。サービス数が少ない分、学習コストが低い傾向があります。

代表的なユースケース5選

1. ECサイトの注文・在庫・決済連携

注文サービスが「OrderCreated」イベントを発行すると、在庫サービスが引き当て処理、決済サービスがオーソリ処理、通知サービスが確認メール送信をそれぞれ並行して実行します。各サービスが独立して障害回復できるため、決済サービスが一時停止しても注文受付自体は継続可能です。

2. IoTセンサーデータのリアルタイム処理

数千台のセンサーが毎秒送信する温度・湿度・振動データをイベントストリームとして受信し、ESPで異常値フィルタリング、CEPで複合条件による設備故障予測を行います。Apache KafkaやAWS Kinesis Data Streamsが大量イベントの受け口として利用されます。

3. 金融取引の不正検知

CEPの典型的な適用例です。「同一カードで異なるIPアドレスから短時間に高額決済が連続」「通常と異なる国からのアクセス後の送金」といった複合パターンをリアルタイムに検出し、取引をブロックまたはアラートを発行します。

4. マイクロサービス間の非同期オーケストレーション

Sagaパターンを用いて、複数マイクロサービスにまたがるビジネストランザクションをイベントチェーンで実現します。各ステップの成功/失敗イベントに基づいて補償トランザクション(ロールバック処理)を実行する構成です。

5. SaaS間のイベント連携

外部SaaSのWebhookイベントをEventBridgeやPub/Subで受信し、社内システムと連携させるパターンです。たとえばStripeの決済完了Webhookを受信して、社内の請求管理システムと会計システムに同時反映するケースがあります。

EDAを選ぶべき場面と避けるべき場面

採用が適しているケース

  • 複数サービスが同一イベントに反応する必要がある(ファンアウト)
  • リアルタイム性が求められる(秒単位での応答)
  • サービスごとに異なるスケーリング要件がある
  • 障害の影響範囲を局所化したい
  • 監査ログや変更履歴の完全な記録が必要
  • 将来的にコンシューマーの追加が見込まれる

避けるべきケース

  • 単純なCRUD操作のみのアプリケーション
  • 処理の順序が厳密に保証されなければならない(EDAでも実現可能だが複雑度が増大)
  • リクエスト/レスポンスで即座に結果を返す必要がある(同期APIが適切)
  • チームの分散システム経験が不足しており、運用体制が整っていない
  • システム全体のサービス数が少なく、疎結合の恩恵が限定的

導入判断フローチャート

EDA導入判断フローチャート:複数サービスの反応要否・リアルタイム性・チームの運用経験で判断を分岐する図

まとめ

イベント駆動アーキテクチャの本質は、システム間の連携を「直接呼び出し」から「状態変化の通知」に転換する設計思想です。疎結合・スケーラビリティ・リアルタイム性といったメリットを得られる一方で、分散トレーシング・冪等性設計・配信保証といった運用面の複雑さが伴います。

自社システムにEDAを適用する際は、次の3ステップで進めるのが現実的です。

  1. 小さく始める - 既存システムの一部(通知送信やログ収集など副作用的な処理)をイベント駆動に切り出す
  2. 段階的に拡大する - 成功パターンを横展開し、コアビジネスロジックのイベント化を検討する
  3. 運用体制を整備する - 分散トレーシング、デッドレターキュー監視、イベントスキーマのバージョン管理を導入する

EDAは万能薬ではありませんが、マイクロサービスの疎結合化やリアルタイムデータ処理が求められる場面では、現時点で最も実績のあるアーキテクチャパターンの1つです。まずは小規模なPub/Sub構成から試し、チームの運用知見を蓄積しながら適用範囲を広げていく方法が、導入の成功確率を高めます。