目次
19 章

EventBridge / SQS / SNS

AWS のメッセージインフラを整理します。3つのツールの違い、SNS topic / SQS queue / EventBridge bus · rule、fan-out パターン、FIFO vs Standard、DLQ と冪等性(idempotency)、Visibility Timeout、そして Lambda / ECS とどう結びつくかまでを扱います。

第17章 Lambda 基礎第18章 API Gateway + Lambda が同期呼び出しの領域だったとすれば、本章は非同期 / イベント駆動の方式です。呼び出し元が結果を待たず、コンポーネント同士がメッセージで疎結合になるパターンです。

AWS にこの領域のツールが3つあります — SNS / SQS / EventBridge です。似て見えますが強調点が異なります。本章でその違いを正確に分け、fan-out パターン、DLQ、冪等性のような運用ポイントまでを一度に整理します。ここで固めるキューと fan-out は、次の 第20章 Secrets Manager / Parameter Store の設定管理、第21章 Step Functions 入門 のワークフローと噛み合います。

3つの違い #

SNSSQSEventBridge
モデルPub/Sub (push)Queue (pull)Event Bus (push、ルーティングルール)
受け取る側0 ~ N 購読者が同時1つのメッセージにつき 1つだけ0 ~ N (rule マッチに応じて)
保存即座に push、受け取らなければ消える最大 14日キューに保管rule マッチで即座に push
適した場合1イベント → 複数の受け取る側作業キュー、バックプレッシャーイベントベースのルーティング (多重ソース)
統合Lambda、SQS、HTTP、Email、SMSLambda、ECS、EC2 (ポーリング)Lambda、SQS、SNS、ECS、Step Functions、… 25+

代表的な構成を1行で見ます。

3つの構成の流れ
                    ┌──────────────┐
                    │              │
   生産者 ─→ SNS ─→ ├─→ SQS  ─→ Lambda
                    └─→ Lambda    Worker (長い処理)
   (1イベント)        (即座に push)

   生産者 ─→ EventBridge ──┬─→ Lambda (ルール A マッチ)
   (多様なソース)           ├─→ Step Functions (ルール B)
                            └─→ SQS (ルール C)

SNS — Pub/Sub #

Topic に publish するとすべての購読者に即座に伝わります。

モデル #

SNS Topic
publish → Topic ──┬─→ 購読者 1 (Lambda)
                  ├─→ 購読者 2 (SQS)
                  ├─→ 購読者 3 (Email)
                  ├─→ 購読者 4 (HTTP endpoint)
                  └─→ 購読者 5 (SMS)

1イベントが発生したときに複数のコンポーネントが同時に知る必要がある場合です。

作る + Publish #

SNS
TOPIC_ARN=$(aws sns create-topic --name user-events \
  --query TopicArn --output text)

# Lambda 購読
aws sns subscribe \
  --topic-arn $TOPIC_ARN \
  --protocol lambda \
  --notification-endpoint arn:aws:lambda:ap-northeast-2:123456789012:function:on-user-event

# Email 購読 (確認メールのあと有効化)
aws sns subscribe \
  --topic-arn $TOPIC_ARN \
  --protocol email \
  --notification-endpoint admin@example.com

# Publish
aws sns publish \
  --topic-arn $TOPIC_ARN \
  --message '{"userId":42,"action":"signup"}'

Standard vs FIFO #

  • Standard: ほぼ無限の処理量、順序保証なし、重複の可能性あり
  • FIFO: グループ内の順序保証、正確に一度の配信。処理量制限 (3,000 msg/s with batching)

名前に .fifo 接尾辞が必須で、MessageGroupId が必須です。

メッセージフィルタリング #

同じ Topic に publish されても、購読者に一部だけ受け取らせることができます。

フィルターポリシー
aws sns set-subscription-attributes \
  --subscription-arn $SUB_ARN \
  --attribute-name FilterPolicy \
  --attribute-value '{"event": ["signup", "purchase"]}'

publish 時に MessageAttributesevent が一致するときだけ伝わります。

適した場合 #

  • 1イベント → 複数の処理 (メール、通知、分析、監査ログ)
  • Email / SMS / Mobile Push 通知
  • SQS fan-out の入り口

SQS — Queue #

Queue にメッセージを入れると、1つの consumer が polling で受け取り、処理する方式です。

モデル #

SQS Queue
生産者 ─→ Queue ─→ 消費者 (Lambda / ECS Task)
                    pull (polling)

消費者が受け取りに行くモデルなのでバックプレッシャーが自然にかかります。消費者が遅ければ Queue にメッセージが積もり、その間は生産者は影響を受けません。

作る + Send / Receive #

SQS
QUEUE_URL=$(aws sqs create-queue --queue-name jobs \
  --query QueueUrl --output text)

# Send
aws sqs send-message \
  --queue-url $QUEUE_URL \
  --message-body '{"job":"resize","key":"photo.jpg"}'

# Receive
aws sqs receive-message \
  --queue-url $QUEUE_URL \
  --max-number-of-messages 10 \
  --wait-time-seconds 20  # long polling

# Delete (処理完了後)
aws sqs delete-message \
  --queue-url $QUEUE_URL \
  --receipt-handle <handle>

Lambda と自動連携 #

Lambda に SQS をトリガーとして付けると、ポーリング / 削除は Lambda インフラが自動でします。

SQS → Lambda
aws lambda create-event-source-mapping \
  --function-name process-jobs \
  --event-source-arn arn:aws:sqs:ap-northeast-2:123456789012:jobs \
  --batch-size 10 \
  --maximum-batching-window-in-seconds 5
Lambda ハンドラ
def handler(event, context):
    for record in event["Records"]:
        body = json.loads(record["body"])
        process_job(body)
    # 正常終了 → Lambda が自動でメッセージを削除
    # 例外 → メッセージがキューに残り visibility timeout のあと再試行

Visibility Timeout — 最も重要な設定 #

消費者がメッセージを受け取ると N 秒の間、他の消費者に見えなくなります。この時間の中で処理と削除が終わらなければなりません。そうでないと再びキューに浮かんで他の消費者が受け取ります → 重複処理のリスクです。

設定推奨
平均処理時間 1秒Visibility Timeout 30秒 (余裕)
平均処理時間 30秒60 ~ 90秒
非常に長くなりうる処理change-message-visibility で処理中に延長

Standard vs FIFO #

SNS と同じです。

  • Standard: ほぼ無限の処理量、順序保証なし、at-least-once (まれに重複)
  • FIFO: グループ内の順序、正確に一度 (MessageDeduplicationId)

Dead Letter Queue (DLQ) #

処理に失敗したメッセージを別のキューに移送します。運用必須です。

DLQ セットアップ
# DLQ を作る
DLQ_URL=$(aws sqs create-queue --queue-name jobs-dlq \
  --query QueueUrl --output text)
DLQ_ARN=$(aws sqs get-queue-attributes \
  --queue-url $DLQ_URL --attribute-names QueueArn \
  --query 'Attributes.QueueArn' --output text)

# Main queue に redrive policy
aws sqs set-queue-attributes \
  --queue-url $QUEUE_URL \
  --attributes '{
    "RedrivePolicy": "{\"deadLetterTargetArn\":\"'"$DLQ_ARN"'\",\"maxReceiveCount\":\"3\"}"
  }'

3回 retry のあと失敗すると DLQ に移送します。DLQ のメッセージは人が分析 / 修正して再びキューに送ります。

適した場合 #

  • 作業キュー (画像処理、メール送信、外部 API 呼び出し)
  • トラフィックスパイクの吸収
  • コンポーネントの分離 (生産者が消費者の速度の影響を受けない)

EventBridge — Event Bus #

EventBridge は複数のソースから入ってくるイベントを複数のターゲットにルールベースでルーティングします。

モデル #

EventBridge
イベントソース (S3, EC2 状態変更, 外部 SaaS, 自分のコード ...)
Event Bus (default またはユーザー定義)
    ├─ Rule A (パターン: source=aws.s3, eventName=ObjectCreated:Put)
    │     → Lambda
    ├─ Rule B (パターン: source=myapp, detail-type=user.signup)
    │     → SQS + Step Functions (どちらもターゲット)
    └─ Rule C (cron: 毎日 03:00)
          → Lambda (バッチ作業)

2種類のイベント #

1) AWS サービスイベント — AWS が自動 publish します。

  • EC2 状態変更 (running → stopped)
  • S3 ObjectCreated
  • CodePipeline 段階完了

2) Custom イベント — 自分のコードが publish します。

Custom イベントの publish
aws events put-events --entries '[{
  "Source": "myapp.users",
  "DetailType": "user.signup",
  "Detail": "{\"userId\":42,\"plan\":\"pro\"}",
  "EventBusName": "default"
}]'

Rule を作る #

Rule (イベントパターンベース)
aws events put-rule \
  --name on-user-signup \
  --event-pattern '{
    "source": ["myapp.users"],
    "detail-type": ["user.signup"],
    "detail": {"plan": ["pro"]}
  }'

# ターゲット追加
aws events put-targets \
  --rule on-user-signup \
  --targets 'Id=1,Arn=arn:aws:lambda:ap-northeast-2:123456789012:function:welcome-pro'
Rule (cron / rate ベース — スケジューラー)
aws events put-rule \
  --name nightly-cleanup \
  --schedule-expression 'cron(0 18 * * ? *)'   # UTC 18:00 = KST 03:00

aws events put-targets \
  --rule nightly-cleanup \
  --targets 'Id=1,Arn=arn:aws:lambda:ap-northeast-2:123456789012:function:cleanup'

スケジューリングはより整理されたツールとして EventBridge Scheduler が別にあります (200,000 個まで / cron または rate / 一回限りまたは反復)。新規プロジェクトでは Scheduler を優先します。

Schema Registry / Pipes #

大規模なイベントエコシステムで使います。

  • Schema Registry: イベントのスキーマを登録 / 自動発見します。コードジェネレータで型安全なクライアントを作ります。
  • EventBridge Pipes: SQS / Kinesis / DynamoDB Streams → (選択的 enrichment / filter) → ターゲットへつなぎます。

適した場合 #

  • AWS サービスイベントへの反応 (S3 アップロード → 処理)
  • ドメインイベントのルーティング (user.signup → 5種類の処理)
  • スケジューリング (cron) — Lambda + EventBridge Scheduler が標準
  • SaaS 統合 (Datadog、PagerDuty、Stripe などのマネージド統合)

Fan-out パターン #

最もよくある運用パターンの1つです。1イベント → 複数の非同期処理です。

SNS + SQS Fan-out
生産者 ─→ SNS Topic ──┬─→ SQS Queue A ─→ Lambda A
                      ├─→ SQS Queue B ─→ Lambda B
                      └─→ SQS Queue C ─→ Lambda C

なぜ SNS + SQS なのか? Lambda を SNS に直接付けてもよいですが、SQS を一段挟むと次の利点があります。

  • 各処理のバックプレッシャーが独立です (B が遅くても A は影響なし)。
  • 各処理の retry / DLQ が独立です。
  • Lambda が一時的に死んでもメッセージが SQS に 14日まで保管されます。

EventBridge も同じパターンです — 1イベントが複数のルールにマッチすると複数のターゲットに同時に伝わります。

冪等性 (Idempotency) の重要性 #

非同期システムの核心です。同じメッセージを2回受け取っても結果が同じでなければなりません。

なぜ2回受け取るのかは次のとおりです。

  • SQS Standard は at-least-once なのでたまに重複します。
  • Visibility Timeout の中で処理を終えられないと再配信されます。
  • Lambda の自動 retry (非同期呼び出し) があります。
  • ネットワーク / クライアントの再試行があります。

パターン 1: 自然な冪等演算 #

# 冪等 (何度やっても結果が同じ)
user.set_status("active")
s3.put_object(Bucket=b, Key=k, Body=data)

# 非冪等
user.add_credit(100)
queue.send(...)

可能なら自然な冪等で設計します。

パターン 2: ID + DB マーカー #

処理 ID の重複防止
def handler(event, context):
    msg = json.loads(event["body"])
    msg_id = msg["id"]

    # すでに処理した ID か?
    if redis.get(f"processed:{msg_id}"):
        return  # skip

    process(msg)
    redis.setex(f"processed:{msg_id}", 86400, "1")  # 1 日保管

Lambda Powertools の Idempotency がこのパターンを DynamoDB バックエンドできれいに処理します。

パターン 3: FIFO Queue の deduplication #

MessageDeduplicationId またはコンテンツベースの deduplication です — 5分以内に同じ ID なら自動で拒否します。

どのツールをいつ #

場合ツール
1イベント、複数の受け取る側SNS Fan-out (+ SQS を挟む) または EventBridge
作業キューSQS
AWS サービスイベントへの反応EventBridge (S3、EC2 などが自動 publish)
スケジューリングEventBridge Scheduler (または EventBridge Rule)
コンポーネント間の単純なメッセージ (1:1)SQS
Email / SMS / Mobile PushSNS
外部 SaaS 統合EventBridge (マネージド統合) または EventBridge Pipes

EventBridge が豊富なルール / フィルター / AWS サービス統合を提供します。単純な fan-out だけなら SNS + SQS です。

コスト #

価格
SQS100万 request あたり $0.40 (Standard)、$0.50 (FIFO)
SNSpublish 100万あたり $0.50 (Email / SMS / Mobile は別途)
EventBridgepublish 100万あたり $1.00 (custom イベント)、AWS 自体のイベントは無料

月 1,000万メッセージの SQS は $4 です。小さなワークロードは事実上無視できる水準です。

よく出会う落とし穴 #

1) メッセージの重複処理 #

自然な冪等ではない演算 (決済 / クレジット追加など) を SQS Standard でやると、1回の決済が2回の決済になります。常に冪等パターンまたは FIFO を使います。

2) Visibility Timeout のミス #

処理に 60秒かかるのに Visibility Timeout が 30秒だと、処理中のメッセージが再びキューに浮かんで他の消費者が受け取ります → 2回処理されます。Visibility Timeout を処理時間 + 余裕にしておきます。

3) DLQ なし #

失敗したメッセージが永遠にキューに浮かんでいると CloudWatch アラームだけがうるさくなります。すべてのキューに DLQ + アラームを置きます。DLQ 自体にもアラームを置きます (DLQ にメッセージが入る = 人が見るべき)。

4) Lambda の SQS ポーリングが高く見える #

Lambda が空のキューを高頻度でポーリングすると SQS request コストがかかります。long polling (WaitTimeSeconds=20) がデフォルトか確認します。

5) EventBridge rule が多くなりすぎる #

ドメインイベントごとにルールが増えるとコンソールがカオスになります。ドメインごとにユーザー定義の Event Bus (default ではない) を分離し、IaC で管理します。

6) SNS Email / SMS の用途 #

SNS の Email は形式が単調で (テキストのみ、From の変更が難しい) Spam に分類されやすいです。トランザクショナルメール (会員登録など) は Amazon SES が正解です。SNS Email は運用者への通知程度にだけ使います。

7) 非同期処理の結果をクライアントに知らせる方法 #

API → SQS → Lambda の処理後、結果をクライアントにどう知らせるのか? 2つのパターンがあります。

  • クライアントが polling (作業 ID で GET リクエスト)
  • WebSocket (API Gateway WebSocket API) で push

非同期システムの設計時に最初に決めるべき基準です。

練習問題 #

  1. 自分のシステムに「1人のユーザーが登録すると歓迎メール · 分析記録 · 管理者通知を同時に送る」という要求があるとして、§「どのツールをいつ」を根拠に SNS · SQS · EventBridge のどの組み合わせを使うかを1段落で設計してみましょう(第18章 API Gateway + Lambda の同期呼び出しとどこで分かれるかも併せて書きます)。
  2. 決済処理を SQS Standard + Lambda でやるとして、§「冪等性」の3つのパターンのうちどれを適用するかを選び、Visibility Timeout をどう設定すれば §「よく出会う落とし穴」の重複処理を防げるかを 第17章 Lambda 基礎 の同時実行とまとめて説明してみましょう。
  3. すべての作業キューに DLQ が必要な理由を §「Dead Letter Queue」と §「よく出会う落とし穴」を根拠に1行で書き、DLQ にメッセージが積もったとき運用者が何をすべきかを書いておきましょう。

一行まとめ: 非同期メッセージのツールは SNS(pub/sub push)、SQS(queue pull)、EventBridge(ルーティングルール)に分かれる。SQS はバックプレッシャーをかけてくれて Visibility Timeout が最も重要な設定で、すべてのキューに DLQ が必須。1イベントを複数の場所に送るには SNS → 複数の SQS → 各 Lambda の fan-out を使い、AWS サービスイベントへの反応とスケジューリングは EventBridge と Scheduler が担う。at-least-once 環境なので自然な冪等 · DB マーカー · FIFO dedup で冪等性を保証しなければならず、トランザクショナルメールは SNS ではなく SES が正解。

次の章 #

次の 第20章 Secrets Manager / Parameter Store では、運用の真剣な一軸であるパスワードと設定値をどこに保管するのかを扱います。2つのツールの違い、自動回転、コードから取得、ECS / Lambda 統合、IaC 連携、コスト比較まで AWS のシークレット管理2ツールを整理します。

X