SJ blog
backend
A

信頼度ランク

S 公式ソース確認済み
A 成功実績多数・失敗例少数
B 賛否両論
C 動作未確認・セキュリティリスク高
Z 個人所感

S3イベント通知 — SNS/SQS/Lambda/EventBridgeの使い分け

S3イベント通知の設定方法、SNS・SQS・Lambda・EventBridgeへの連携パターン、イベントタイプの種類、ファンアウト設計、重複通知の可能性と対策を解説。

一言結論

S3イベント通知はat-least-once配信のため重複が起こりうるので処理側の冪等性が必須であり、1つのイベントを複数処理へ渡すにはSNSファンアウト、高度なフィルタリングにはEventBridgeという使い分けが設計の基本だ。

S3イベント通知の仕組み

S3バケットでオブジェクトの作成・削除・復元等のイベントが発生すると、設定した通知先にイベント情報が送信される。

通知先(デスティネーション):

  • SNS(Simple Notification Service)
  • SQS(Simple Queue Service)
  • Lambda関数
  • EventBridge(より高度なルーティングに対応)

主要なイベントタイプ

オブジェクト作成:
  s3:ObjectCreated:*       (全作成イベント)
  s3:ObjectCreated:Put
  s3:ObjectCreated:Post    (マルチパートアップロード完了)
  s3:ObjectCreated:Copy
  s3:ObjectCreated:CompleteMultipartUpload

オブジェクト削除:
  s3:ObjectRemoved:*
  s3:ObjectRemoved:Delete
  s3:ObjectRemoved:DeleteMarkerCreated

Glacierからの復元:
  s3:ObjectRestore:Post    (復元リクエスト)
  s3:ObjectRestore:Completed(復元完了)

レプリケーション:
  s3:Replication:OperationFailedReplication
  s3:Replication:OperationMissedThreshold

Lambda連携の設定

# 1. LambdaにS3からの呼び出し権限を付与
aws lambda add-permission \
  --function-name image-processor \
  --statement-id s3-trigger \
  --action lambda:InvokeFunction \
  --principal s3.amazonaws.com \
  --source-arn arn:aws:s3:::my-uploads-bucket \
  --source-account 123456789012

# 2. S3バケットに通知設定を追加
aws s3api put-bucket-notification-configuration \
  --bucket my-uploads-bucket \
  --notification-configuration '{
    "LambdaFunctionConfigurations": [{
      "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:image-processor",
      "Events": ["s3:ObjectCreated:*"],
      "Filter": {
        "Key": {
          "FilterRules": [
            {"Name": "prefix", "Value": "uploads/"},
            {"Name": "suffix", "Value": ".jpg"}
          ]
        }
      }
    }]
  }'
# Lambda関数でS3イベントを処理する例
def handler(event, context):
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = record['s3']['object']['key']
        size = record['s3']['object']['size']
        
        print(f"処理開始: s3://{bucket}/{key} ({size} bytes)")
        
        # 画像のサムネイル生成など
        process_image(bucket, key)

ファンアウトパターン(SNS → 複数SQS)

一つのS3イベントを複数の処理に渡す場合:

S3イベント → SNSトピック → SQS A (画像リサイズ処理)
                         → SQS B (メタデータ抽出)
                         → Lambda (通知送信)
// S3通知設定(SNSへ)
{
  "TopicConfigurations": [{
    "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:s3-events",
    "Events": ["s3:ObjectCreated:*"]
  }]
}

S3通知は1つのイベントタイプに対して1つの通知先しか設定できない(同じプレフィックス/サフィックスへの重複設定は不可)。複数の処理に渡す場合はSNSを経由するファンアウトが必要だ。

EventBridgeへの転送

EventBridgeを使うとより高度なルーティングが可能だ。

# バケットのEventBridge転送を有効化
aws s3api put-bucket-notification-configuration \
  --bucket my-bucket \
  --notification-configuration '{
    "EventBridgeConfiguration": {}
  }'
// EventBridgeルール: 5MB以上のファイルアップロードのみ処理
{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": ["my-bucket"]
    },
    "object": {
      "size": [{"numeric": [">=", 5242880]}]
    }
  }
}

EventBridgeの利点:

  • イベントのフィルタリングが細かく設定できる
  • 複数の宛先に同時に送信できる(ルールを複数作成)
  • クロスアカウント・クロスリージョン転送が容易

重複通知の可能性

S3のイベント通知はat-least-once delivery(少なくとも1回配信)だ。稀に重複通知が発生する可能性がある。

対策:

# DynamoDBで重複処理を防ぐ(冪等性の確保)
def handler(event, context):
    for record in event['Records']:
        etag = record['s3']['object']['eTag']
        key = record['s3']['object']['key']
        
        # ETAGをキーに重複チェック
        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table('processed-objects')
        
        try:
            table.put_item(
                Item={'etag': etag, 'key': key},
                ConditionExpression='attribute_not_exists(etag)'
            )
        except table.meta.client.exceptions.ConditionalCheckFailedException:
            print(f"既に処理済み: {key}")
            return
        
        # 実際の処理
        process_object(record)

試験頻出ポイント

シナリオ回答
1つのS3イベントを複数の処理に渡したいSNSファンアウトパターン
イベントを特定の条件でフィルタしたいEventBridgeを使う
重複処理を防ぎたい処理側で冪等性を担保(DynamoDB等)
プレフィックスとサフィックスの両方でフィルタS3通知のFilterRulesで設定可能

まとめ

シンプルな1対1のイベント連携にはS3ネイティブ通知(Lambda/SQS)、複数処理への分配にはSNSファンアウト、複雑なフィルタリングや高度なルーティングにはEventBridgeを使う。重複通知を前提とした冪等な処理設計が重要だ。