AWS App Integration Vol1|SQS×SNS×EventBridge×API GW×AppSync

目次

なぜ Application Integration Vol1 か — メッセージング5層アーキテクチャ概観

Application Integration本番運用シリーズ ナビゲーション

Vol1(統合プラットフォーム基盤・本記事) — つなぐ・流す・制御する

| 章 | テーマ | 主な施策 |
|—-|——–|———|
| §2 | Amazon SQS 本番運用 | Standard/FIFO選定・DLQ設計・Lambda統合 |
| §3 | Amazon SNS 本番運用 | Fan-out・サブスクリプションフィルタ・FIFO Topic |
| §4 | Amazon EventBridge 本番運用 | イベントバス設計・Scheduler・Pipes・Schema Registry |
| §5 | Amazon API Gateway 本番運用 | REST/HTTP API選定・認可統合・スロットリング |
| §6 | AWS AppSync 本番運用 | GraphQLスキーマ・リゾルバ・リアルタイムサブスクリプション |
| §7 | 詰まりポイント7選 + 演習 | 頻出パターンの解決策 + アンチパターン変換5問 |

Application Integration Vol1 メッセージング5層アーキテクチャ全体像
fig01: Application Integration Vol1 メッセージング5層アーキテクチャ全体像

全24軸のAWSハンズオンシリーズを通じて、Computing(EC2/ECS/EKS)・Storage(S3/EFS)・Database(RDS/DynamoDB)・Serverless(Lambda/Step Functions)・Observability(CloudWatch/X-Ray)など主要サービス群を体系的に習得してきた。しかし現場での設計力を問われるとき、最も差が出るのは「個々のサービスを使いこなす力」より「サービス間をどう繋ぐか」だ。

マイクロサービスが当たり前になった今、1つのリクエストが複数のサービスを跨ぐのは標準だ。その接合部——Application Integration——を設計する力こそが、Cloud Architectとして一段上に行くために必要なスキルになる。

メッセージング5層アーキテクチャ

AWSのApplication Integrationサービスは、役割と抽象度で5層に整理できる。

レイヤーサービス役割代表ユースケース
QueueAmazon SQS非同期メッセージキューイング・デカップリングワーカーバッファリング / 非同期処理
Pub-SubAmazon SNSトピックへの発行→複数サブスクライバへFan-out障害通知 / 複数Lambda同時起動
Event BusAmazon EventBridgeイベント駆動ルーティング / スケジューリング / SaaS統合サービス間疎結合 / 定時バッチ
API ManagementAmazon API GatewayREST/HTTP APIの公開・保護・管理モバイル/Web向けAPIエンドポイント
GraphQLAWS AppSyncスキーマ駆動GraphQL / リアルタイムサブスクリプションフロントエンド統合 / リアルタイム更新

5つは競合するサービスではなく、相補的に組み合わせて使う統合レイヤーだ。本番環境での典型的な組み合わせを見てみよう。

API Gateway → SQS → Lambda(非同期処理) → SNS(結果通知) → EventBridge(監査ログ転送)

この1本のフローの中に5サービスのうち4つが登場する。それぞれが独立した役割を持ちながら、疎結合に連携する——これがApplication Integrationの本質だ。

Serverless Vol2との差別化

Serverless Vol2では、Lambda中心のEvent-Driven Architectureを軸に、SQS/SNS/EventBridgeをイベント駆動の「脇役」として解説した。SQS選定マトリクス・SNS Fan-out基礎・EventBridgeイベントバス基本が中心で、API GatewayとAppSyncは対象外だった。

本記事はその逆アプローチをとる。統合プラットフォーム視点でSQS/SNS/EventBridge/API Gateway/AppSyncを「主役」として個別深堀りする。

  • SQS: Standard vs FIFO 5軸選定、DLQ設計(maxReceiveCount根拠・redrive戦略)、Visibility Timeout最適設計、部分バッチ応答
  • SNS: FIFO Topicの活用、サブスクリプションフィルタ設計、モバイルプッシュ、クロスアカウント配信
  • EventBridge: Scheduler(分散Cronの置き換え)、Pipes(サービス間ブリッジ)、Schema Registry(スキーマ管理)
  • API Gateway: REST vs HTTP API選定基準、Cognito/Lambda認可統合、スロットリング・キャッシュ設計
  • AppSync: GraphQLスキーマ設計、リゾルバパイプライン、WebSocketサブスクリプション、Merged API

本記事で獲得できる設計力

本記事を通読することで、以下の設計判断が単独でできるようになる。

  1. SQS: Standard/FIFO選定・DLQ maxReceiveCount設計・Visibility Timeout最適値・Lambda Event Source Mapping部分バッチ応答
  2. SNS: Fan-outパターン・サブスクリプションフィルタ設計・FIFO Topicの用途・クロスアカウント配信
  3. EventBridge: カスタムイベントバス設計・Schedulerによる定時実行・Pipesによるサービス間ブリッジ・Schema Registryによるスキーマ管理
  4. API Gateway: REST vs HTTP API選定・Cognito/Lambda認可統合・スロットリング設定・キャッシュ戦略
  5. AppSync: GraphQLスキーマ設計・リゾルバパイプライン・WebSocketサブスクリプション・Merged API構成

さらに§7の「詰まりポイント7選」とアンチパターン演習5問で、実際の設計現場で直面しやすいミスパターンとその解決策を体験する。Application Integration Seriesのvol1として、第25軸目の起点にふさわしい内容に仕上げた。


Amazon SQS 本番運用 — Standard vs FIFO / DLQ設計 / Visibility Timeout / Lambda統合

SQS Standard/FIFO + DLQ + Lambda統合構成図
fig02: SQS Standard/FIFO + DLQ + Lambda統合構成図

SQSはAWS最古のサービスの一つであり、最も実績のある非同期メッセージキューイングサービスだ。表面上はシンプルに見えるが、本番運用で使いこなすには複数の設計判断が求められる。

Standard vs FIFO — 選定5軸比較

SQSを使う最初の判断は「Standard か FIFO か」だ。5軸で比較する。

選定軸Standard QueueFIFO Queue
順序保証ベストエフォート(順序不保証)厳密な順序保証(送信順)
重複配信At-Least-Once(重複あり)Exactly-Once(5分間ウィンドウ内)
スループット無制限(virtually unlimited)最大3,000 msg/s(バッチ) / 300 msg/s(単体)
コスト基準価格Standard比約10%高
主なユースケース画像変換 / メール送信 / ログ収集金融取引 / 注文処理 / 在庫管理

選定の原則:

  • 「順序が壊れたら業務が壊れる」→ FIFO一択
  • 「スループット10,000 msg/s超が必要」→ Standard一択
  • 「重複処理はアプリ側で冪等性を持って対処できる」→ Standard(コスト効率優先)

DLQ(Dead Letter Queue)設計

DLQはSQS本番運用の要だ。処理失敗メッセージを隔離し、本キューを健全に保つ。

maxReceiveCount設計(失敗許容回数)

Lambdaの処理失敗カウントが maxReceiveCount を超えると、メッセージはDLQへ転送される。

{
  "deadLetterTargetArn": "arn:aws:sqs:ap-northeast-1:123456789012:MyQueue-DLQ",
  "maxReceiveCount": 3
}

推奨値は 3〜5回 だ。根拠を整理する。

  • 1〜2回: 一時的ネットワーク障害で即DLQ転送 → 誤検知が多い
  • 3〜5回: 一時障害を吸収しつつ、無限ループを早期遮断
  • 10回以上: DLQ転送が遅れ、本キューのメッセージ滞留が長引く

LambdaのEvent Source Mappingのリトライ設定(maxRetryAttempts 最大2回)と合わせて設計することが重要だ。bisectOnFunctionError=true と組み合わせると、バッチのどのメッセージが失敗したかを特定できる。

DLQ Redrive(再処理)

DLQ内のメッセージは修正後に本キューへ再投入(Redrive)できる。

import boto3

sqs = boto3.client('sqs')

response = sqs.start_message_move_task(
 SourceArn='arn:aws:sqs:ap-northeast-1:123456789012:MyQueue-DLQ',
 DestinationArn='arn:aws:sqs:ap-northeast-1:123456789012:MyQueue',
 MaxNumberOfMessagesPerSecond=10
)
task_handle = response['TaskHandle']

StartMessageMoveTask は非同期で実行される。最大10 msg/sのレートで制御でき、本番キューへの急激な流入を防ぐ。

DLQアラーム設定

DLQにメッセージが1件でも入ったら即座にアラームを上げるべきだ。

{
  "AlarmName": "SQS-DLQ-MessageVisible",
  "MetricName": "ApproximateNumberOfMessagesVisible",
  "Namespace": "AWS/SQS",
  "Statistic": "Sum",
  "Period": 60,
  "EvaluationPeriods": 1,
  "Threshold": 0,
  "ComparisonOperator": "GreaterThanThreshold",
  "Dimensions": [{"Name": "QueueName", "Value": "MyQueue-DLQ"}]
}
DLQ設計の落とし穴

DLQを設定しないと何が起きるか? maxReceiveCountを超えたメッセージはデフォルトでキュー内に残り続ける。VisibilityTimeout期間を経て再度配信され、また失敗し——という無限ループが発生する。結果として正常メッセージの処理が遅延し、Lambda同時実行数を食い潰すリスクがある。SQSキューには必ずDLQをペアで設定すること。

Visibility Timeout 設計

Visibility Timeoutは「メッセージを受信してから他のコンシューマに見えなくなる時間」だ。コンシューマ(Lambda/EC2)が処理完了前にこの時間を超えると、同じメッセージが再配信される。

デフォルト値と設計指針:

パラメータ
デフォルト30秒
最小0秒
最大12時間

Lambda統合時の推奨値

Visibility Timeout = Lambda Timeout × 6

Lambda Timeoutが30秒なら Visibility Timeout は180秒(3分)に設定する。「×6」の根拠はLambdaの再試行ポリシーを考慮した余裕係数だ。Lambdaがタイムアウトした場合でもメッセージが再配信可能になるまでの時間を十分確保できる。

ChangeMessageVisibility による動的延長

処理が予想より長引いた場合、削除前に Visibility Timeout を延長できる。

import boto3

sqs = boto3.client('sqs')

def extend_visibility(queue_url: str, receipt_handle: str, new_timeout: int = 300):
 sqs.change_message_visibility(
  QueueUrl=queue_url,
  ReceiptHandle=receipt_handle,
  VisibilityTimeout=new_timeout
 )

長時間処理(機械学習推論・大容量ファイル変換等)では、処理ループ内で定期的に延長するパターンが有効だ。最大延長時間は初回受信から12時間以内。

Long Polling vs Short Polling

SQSのポーリングには2種類ある。

方式ReceiveMessageWaitTimeSeconds動作コスト傾向
Short Polling0(デフォルト)メッセージがなくてもすぐ返すAPIコール数が多くなりやすい
Long Polling1〜20秒メッセージが来るか指定秒数待つAPIコール数を削減
aws sqs set-queue-attributes \
  --queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/MyQueue \
  --attributes ReceiveMessageWaitTimeSeconds=20

Long Pollingを選ぶべき理由:

  • 空レスポンスが減り、APIコストが約10〜20%削減できる
  • ポーリング間隔が短くなるためレイテンシも低減(メッセージ到着を即検知)
  • 特別な理由がなければ ReceiveMessageWaitTimeSeconds=20 に設定する

バッチ処理 — SendMessageBatch / DeleteMessageBatch

SQSのAPIコストはリクエスト数課金だ。バッチAPIを使うとコストを最大10分の1に削減できる。

import boto3

sqs = boto3.client('sqs')

entries = [
 {'Id': str(i), 'MessageBody': f'message-{i}'}
 for i in range(10)
]

response = sqs.send_message_batch(
 QueueUrl='https://sqs.ap-northeast-1.amazonaws.com/123456789012/MyQueue',
 Entries=entries
)

if response.get('Failed'):
 for failure in response['Failed']:
  print(f"Failed: {failure['Id']} - {failure['Message']}")

削除もバッチで行う。Lambda Event Source Mappingでは自動バッチ削除されるが、EC2/ECSコンシューマでは明示的な削除が必要だ。

def delete_batch(queue_url: str, receipts: list):
 entries = [
  {'Id': str(i), 'ReceiptHandle': rh}
  for i, rh in enumerate(receipts)
 ]
 sqs.delete_message_batch(QueueUrl=queue_url, Entries=entries)

バッチサイズは最大10件。256 KB以下の制約はバッチ全体に適用される(1メッセージあたりの制限ではない)。

Lambda SQS Event Source Mapping

LambdaとSQSの統合はEvent Source Mapping(ESM)を通じて行う。ポーリングとバッチ処理をLambdaが代行するため、コンシューマコードが大幅に簡略化される。

主要パラメータ:

パラメータ説明推奨設定
batchSize1回のLambda呼び出しに含めるメッセージ数Standard: 10〜1000 / FIFO: 10
maximumBatchingWindowInSecondsバッチを積み上げる最大待機時間0〜300秒(コスト最適化時は30〜60秒)
functionResponseTypes部分バッチ応答を有効化["ReportBatchItemFailures"]
bisectOnFunctionErrorバッチ失敗時に二分割して再試行true(デバッグ効率化)

部分バッチ応答(ReportBatchItemFailures)

バッチ内の一部メッセージが失敗した際、失敗したメッセージだけをDLQに送り、成功したものは正常処理できる。

def handler(event, context):
 batch_item_failures = []

 for record in event['Records']:
  try:
process_message(record['body'])
  except Exception as e:
batch_item_failures.append({
 'itemIdentifier': record['messageId']
})

 return {'batchItemFailures': batch_item_failures}

ReportBatchItemFailures を有効化しない場合、バッチ内の1件失敗でバッチ全体が再試行される。成功済みメッセージの重複処理リスクがあるため、必ず有効化すること。

SQS Lambda統合 推奨セット
{
  "EventSourceArn": "arn:aws:sqs:ap-northeast-1:123456789012:MyQueue",
  "BatchSize": 100,
  "MaximumBatchingWindowInSeconds": 30,
  "FunctionResponseTypes": ["ReportBatchItemFailures"],
  "BisectBatchOnFunctionError": true
}

BatchSize=100 + BatchingWindow=30s でスループット向上とコスト削減を両立
ReportBatchItemFailures で部分失敗に対応し、成功済みメッセージの重複処理を防ぐ
BisectBatchOnFunctionError=true で障害切り分けを高速化

FIFO キュー — MessageGroupId 設計

FIFOキューの順序保証は MessageGroupId 単位 で行われる。同一MessageGroupId内のメッセージのみ順序保証・重複排除が適用される。

メッセージ送信例:

import boto3

sqs = boto3.client('sqs')

sqs.send_message(
 QueueUrl='https://sqs.ap-northeast-1.amazonaws.com/123456789012/MyQueue.fifo',
 MessageBody='order-data',
 MessageGroupId='order-123',
 MessageDeduplicationId='order-123-2026-01-01T10:00:00Z'
)

MessageGroupId設計パターン:

設計方針効果トレードオフ
全メッセージ同一(例: “default”)全順序保証並列処理不可(1スレッドのみ)
エンティティID(例: “order-123″)エンティティ内順序保証同一エンティティは順次処理
細粒度(ランダムUUID等)並列処理最大化順序保証なし(Standardと同等)

推奨: 「どの粒度で順序を保証したいか」を業務要件から逆算してGroupIdを設計する。金融取引なら口座ID、注文処理なら注文ID、在庫管理なら商品IDが典型的な設計だ。

MessageDeduplicationId は重複排除に使用する。同一DeduplicationIdが5分以内に再送された場合、2回目以降は無視される。ContentBasedDeduplication(メッセージ内容のSHA-256)を有効化すれば明示指定が不要になるが、本当に同一内容のメッセージが異なるタイミングで正当に送信される場合は必ず明示的に一意のIDを指定すること。


Amazon SNS 本番運用 — Fan-out / サブスクリプションフィルタ / FIFO Topic

sequenceDiagram
 participant Publisher
 participant SNS as SNS Topic
 participant SQS as SQS Queue
 participant Lambda as Lambda Function
 participant HTTP as HTTP Endpoint
 Publisher->>SNS: Publish Message
 SNS-->>SQS: Fan-out (Queue処理)
 SNS-->>Lambda: Fan-out (即時処理)
 SNS-->>HTTP: Fan-out (外部通知)
 Note over SNS: サブスクリプションフィルタで<br/>配信先を選択的に制御

トピック設計: Standard Topic vs FIFO Topic

SNSトピックは用途に応じてStandardとFIFOを選択する。

比較項目Standard TopicFIFO Topic
スループット無制限 (ソフトリミット 30,000 msg/秒)300 msg/秒 (バッチ3,000 msg/秒)
配信保証At-least-once (重複あり)Exactly-once (MessageDeduplicationId)
順序保証なしMessageGroupId単位で保証
サブスクライバーSQS/Lambda/HTTP/Email/SMS/Mobile PushSQS FIFO Queueのみ

FIFO Topicはサブスクライバーが SQS FIFO Queue のみ に制限される点に注意。LambdaやHTTPエンドポイントを直接サブスクライブすることはできない。

import boto3
import json

sns = boto3.client('sns', region_name='ap-northeast-1')

# FIFO Topic作成 (.fifo サフィックス必須)
response = sns.create_topic(
 Name='OrderProcessing.fifo',
 Attributes={
  'FifoTopic': 'true',
  'ContentBasedDeduplication': 'false'  # MessageDeduplicationIdを明示指定する場合はfalse
 }
)
topic_arn = response['TopicArn']

# FIFO Topicへのメッセージ送信
sns.publish(
 TopicArn=topic_arn,
 Message='{"orderId": "ORD-12345", "amount": 5000}',
 MessageGroupId='customer-group-A',# 同グループ内の順序保証
 MessageDeduplicationId='order-ORD-12345-v1'# 5分間の重複排除ウィンドウ
)

サブスクリプションフィルタポリシー

フィルタポリシーで特定のサブスクライバーにだけメッセージを配信する。フィルタスコープは2種類ある。

  • MessageAttributes (デフォルト): メッセージ属性ベースのフィルタ
  • MessageBody: JSONペイロードのフィールドでフィルタ (FilterPolicyScope: MessageBody を設定)
// 属性ベースフィルタ: priority=high/critical かつ amount>=1000 の場合のみ配信
{
  "priority": ["high", "critical"],
  "amount": [{"numeric": [">=", 1000]}]
}
// ペイロードベースフィルタ (MessageBody スコープ)
// サブスクリプション属性 FilterPolicyScope=MessageBody を設定後に有効
{
  "eventType": ["ORDER_CREATED", "ORDER_UPDATED"],
  "metadata": {
 "region": [{"prefix": "ap-northeast"}]
  }
}

フィルタ設計パターン:

パターン記法用途
AND条件複数フィールドを並記全条件一致時のみ配信
OR条件同フィールドを配列で複数値指定いずれか一致で配信
存在チェック[{"exists": true}]フィールドの有無で分岐
数値範囲[{"numeric": [">=", 100, "<", 1000]}]金額・スコアの範囲指定
除外[{"anything-but": ["CANCELLED"]}]特定値を除外
前方一致[{"prefix": "ap-"}]リージョン・IDプレフィックス

Fan-outパターン実装

1つのSNS Topicから複数のサブスクライバーに並列配信する設計パターン。

# SQSサブスクリプション (バッファリング + フィルタリング)
sns.subscribe(
 TopicArn=topic_arn,
 Protocol='sqs',
 Endpoint=sqs_queue_arn,
 Attributes={
  'RawMessageDelivery': 'true', # SNSラッパー除去 (コンシューマーの二重パース不要)
  'FilterPolicy': json.dumps({'eventType': ['ORDER_CREATED']}),
  'RedrivePolicy': json.dumps({'deadLetterTargetArn': dlq_arn})
 }
)

# Lambdaサブスクリプション (即時処理)
sns.subscribe(
 TopicArn=topic_arn,
 Protocol='lambda',
 Endpoint=lambda_function_arn,
 Attributes={
  'FilterPolicy': json.dumps({'priority': ['critical']})
 }
)

Cross-accountサブスクリプション設計:

異なるアカウントのSQSをサブスクライブする場合、SNS側のリソースポリシーとSQS側のキューポリシーの両方が必要になる。

// SQS キューポリシー (クロスアカウントSNS許可)
{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Principal": {"Service": "sns.amazonaws.com"},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:ap-northeast-1:TARGET_ACCOUNT:target-queue",
"Condition": {
  "ArnEquals": {
 "aws:SourceArn": "arn:aws:sns:ap-northeast-1:SOURCE_ACCOUNT:source-topic"
  }
}
 }
  ]
}

モバイルプッシュ配信

SNSはAPNs(iOS)・FCM(Android)・ADM(Amazon)へのプッシュ通知を統一APIで提供する。

コンポーネント役割
Platform ApplicationAPNs/FCMの認証情報 (証明書/APIキー) を保持
Platform Endpointデバイストークンと1:1で紐付く個別エンドポイント
Direct PublishPlatform Endpointへのターゲット配信
# Platform Endpoint作成 (アプリ起動時にデバイス登録・更新)
endpoint = sns.create_platform_endpoint(
 PlatformApplicationArn=platform_app_arn,
 Token=device_token,  # APNs/FCMデバイストークン
 CustomUserData='user-id-12345'
)

# Direct Publish (マルチプラットフォーム対応)
sns.publish(
 TargetArn=endpoint['EndpointArn'],
 Message=json.dumps({
  'GCM': json.dumps({ # FCM/Android
'notification': {
 'title': '注文完了',
 'body': 'ORD-12345が発送されました'
}
  }),
  'APNS': json.dumps({# iOS
'aps': {
 'alert': {
  'title': '注文完了',
  'body': 'ORD-12345が発送されました'
 }
}
  })
 }),
 MessageStructure='json' # プラットフォーム別メッセージ分岐
)

Platform Endpointはデバイストークンの有効期限切れで無効化される。CreatePlatformEndpointは既存トークンに対してもべき等に動作するため、アプリ起動のたびに呼び出してエンドポイントを最新状態に保つことが推奨される。

メッセージ属性 (MessageAttributes) の活用

メッセージ属性はフィルタリングとルーティング分岐の両方に利用できる。

sns.publish(
 TopicArn=topic_arn,
 Message='{"orderId": "ORD-12345"}',
 MessageAttributes={
  'eventType': {
'DataType': 'String',
'StringValue': 'ORDER_CREATED'
  },
  'priority': {
'DataType': 'String',
'StringValue': 'high'
  },
  'amount': {
'DataType': 'Number',
'StringValue': '15000'
  }
 }
)

SNS + SQS Fan-outのデッドレタリング

SNSサブスクリプションレベルにDLQを設定することで、SNS→サブスクライバー間の配信失敗を捕捉できる。

# サブスクリプションにDLQ設定 (Redrive Policy)
sns.set_subscription_attributes(
 SubscriptionArn=subscription_arn,
 AttributeName='RedrivePolicy',
 AttributeValue=json.dumps({
  'deadLetterTargetArn': 'arn:aws:sqs:ap-northeast-1:123456789012:sns-dlq'
 })
)

DLQ配置の二層設計:

  • SNSサブスクリプションDLQ: SNS→サブスクライバー間の配信失敗を捕捉 (HTTP 5xx / SQSアクセス拒否等)
  • SQSキューDLQ: コンシューマーの処理失敗を捕捉 (maxReceiveCount超過後に移動)

両方を設定しないと、どの層での失敗かが判断できず障害対応が長引く。CloudWatchで NumberOfMessagesFailedApproximateNumberOfMessagesNotVisible をアラーム監視する。

SNS 本番運用 選定・設計チェックリスト

トピック種別選定
– 順序保証・Exactly-once が必要 → FIFO Topic (サブスクライバーはSQS FIFOのみ)
– 高スループット・Lambda直結が必要 → Standard Topic

フィルタポリシー設計
– MessageBodyスコープはサブスクリプションに FilterPolicyScope: MessageBody を明示設定
– フィルタアクション上限: 5件/秒/サブスクリプション → 大量配信時はSQSバッファを挟む
– 属性フィルタを使う場合は RawMessageDelivery: false を維持 (フィルタはSNSエンベロープの属性を参照)

Fan-out DLQ
– SNSサブスクリプションとSQSキューの両階層にDLQを設定
– CloudWatchで配信失敗数をアラーム監視

SNS アンチパターン: RawMessageDelivery未設定による二重パース問題

問題: SNS→SQS Fan-outでRawMessageDeliveryを設定しないと、SQSコンシューマーはSNSエンベロープ付きJSONを受け取る。コンシューマー側で json.loads(message['Body'])['Message'] という二重パースが必要になり、既存コンシューマーとの互換性が失われる。

正解パターン: サブスクリプション作成時に RawMessageDelivery: true を設定。SNSエンベロープを除去し、publishしたメッセージボディをそのままSQSに格納する。フィルタポリシーを属性ベースで使う場合のみ RawDelivery: false を維持すること。


Amazon EventBridge 本番運用 — イベントバス / Scheduler / Pipes / Schema Registry

EventBridge イベントバス + Scheduler + Pipes + Schema Registry 構成図
fig03: EventBridge イベントバス + Scheduler + Pipes + Schema Registry 構成図

イベントバス設計: Default vs Custom Event Bus

比較項目Default Event BusCustom Event Bus
主用途AWSサービスイベント受信アプリケーション独自イベント
共有性AWSサービス全体で共有ドメイン/環境単位で分割可能
ルール上限300ルール/バス300ルール/バス (緩和申請可)
アーカイブ一部制限あり全イベント対象
クロスアカウント受信不可完全サポート

Custom Event Bus分離戦略:

ドメイン分割: order-events-bus / payment-events-bus / notification-events-bus
環境分割: prod-events-bus / staging-events-bus

Default Event Busにアプリイベントを流すと300ルール上限に到達しやすく、AWSサービスイベントとの混在でデバッグも困難になる。新規設計ではドメイン単位のCustom Event Busを採用する。

import boto3
import json

events = boto3.client('events', region_name='ap-northeast-1')

# Custom Event Bus作成
events.create_event_bus(
 Name='order-events-bus',
 Tags=[{'Key': 'Domain', 'Value': 'OrderManagement'}]
)

# カスタムイベント送信 (PutEvents API)
response = events.put_events(
 Entries=[
  {
'EventBusName': 'order-events-bus',
'Source': 'com.example.orders',  # ドット区切りの逆ドメイン記法推奨
'DetailType': 'OrderCreated',
'Detail': json.dumps({
 'orderId': 'ORD-12345',
 'customerId': 'CUST-789',
 'amount': 15000,
 'status': 'CREATED'
})
  }
 ]
)
# FailedEntryCount > 0 で部分失敗 → 再送が必要
print(f"FailedEntryCount: {response['FailedEntryCount']}")

イベントパターン (Event Pattern) マッチング

EventBridgeのイベントパターンはJSON構造に対して高度なマッチングを行う。

{
  "source": ["com.example.orders"],
  "detail-type": ["OrderCreated", "OrderUpdated"],
  "detail": {
 "status": [{"anything-but": ["CANCELLED", "REFUNDED"]}],
 "amount": [{"numeric": [">=", 1000]}],
 "region": [{"prefix": "ap-northeast"}],
 "requestId": [{"exists": true}]
  }
}
オペレーター記法用途
prefix{"prefix": "ap-"}前方一致 (リージョン・IDプレフィックス)
suffix{"suffix": "-prod"}後方一致
anything-but{"anything-but": ["CANCELLED"]}除外リスト
numeric{"numeric": [">=", 0, "<", 1000]}数値範囲
exists{"exists": true/false}フィールドの有無
equals-ignore-case{"equals-ignore-case": "admin"}大文字小文字無視

ルール (Rules) + ターゲット設計

Input Transformer: イベントデータをターゲット向けのフォーマットに変換する機能。

// InputPathsMap: イベントから抽出するフィールドのマッピング
{
  "orderId": "$.detail.orderId",
  "amount": "$.detail.amount",
  "eventTime": "$.time"
}
// InputTemplate: 送信フォーマット (<変数名> でインジェクト)
{
  "message": "注文 <orderId> が作成されました (金額: <amount>円)",
  "timestamp": "<eventTime>"
}

DLQ on Rule (ターゲット配信失敗時の保全):

events.put_targets(
 Rule='order-created-rule',
 EventBusName='order-events-bus',
 Targets=[
  {
'Id': 'order-processor-lambda',
'Arn': lambda_function_arn,
'DeadLetterConfig': {
 'Arn': dlq_arn # ターゲット配信失敗時にDLQへ退避
},
'RetryPolicy': {
 'MaximumRetryAttempts': 3, # リトライ上限 (最大185)
 'MaximumEventAgeInSeconds': 3600 # イベント有効期間 (最大24h)
}
  }
 ]
)

ルール上限300件に対する設計戦略:

  • イベントパターンのOR条件を活用して複数イベントタイプを1ルールで処理
  • 環境ごとにCustom Event Busを分割してルール上限を独立させる
  • Service Quotasで緩和申請するとバスごとの上限を引き上げ可能

EventBridge Scheduler

EventBridge Schedulerはスタンドアロンのスケジューリングサービス。EventBridgeルールのスケジュールに比べてタイムゾーン対応・Flexible Time Window・One-time実行が追加されている。

スケジュール種別記法
One-timeat(yyyy-mm-ddThh:mm:ss)at(2026-06-01T09:00:00)
Raterate(N unit)rate(5 minutes)
Croncron(分 時 日 月 曜 年)cron(0 0 * * ? *)
scheduler = boto3.client('scheduler', region_name='ap-northeast-1')

# Cron スケジュール (毎日9時 JST)
scheduler.create_schedule(
 Name='daily-report-job',
 ScheduleExpression='cron(0 0 * * ? *)', # UTC 0:00 = JST 9:00
 ScheduleExpressionTimezone='Asia/Tokyo', # タイムゾーン指定 (Schedulerのみ対応)
 Target={
  'Arn': lambda_function_arn,
  'RoleArn': scheduler_role_arn,
  'Input': json.dumps({'reportType': 'daily'}),
  'RetryPolicy': {
'MaximumRetryAttempts': 2,
'MaximumEventAgeInSeconds': 1800
  }
 },
 FlexibleTimeWindow={
  'Mode': 'FLEXIBLE',
  'MaximumWindowInMinutes': 15 # 0-15分内のランダム実行 (雷群れ問題回避)
 },
 State='ENABLED'
)

Flexible Time Window: 同時刻に多数のスケジュールが起動してバックエンドが過負荷になる「雷群れ問題 (Thundering Herd)」を回避するため、指定ウィンドウ内でランダムに実行タイミングをずらす機能。

EventBridge Pipes

Pipesは Source → Enrichment → Target の直線型パイプラインを宣言的に構成する。

[Source] [Filter] [Enrichment]  [Target]
SQS / Kinesis →イベントフィルタ  →  Lambda→  Lambda
DynamoDB Streams  (不要レコード除外)Step Functions SQS / SNS
Kafka / Amazon MQAPI Gateway EventBridge
pipes = boto3.client('pipes', region_name='ap-northeast-1')

pipes.create_pipe(
 Name='order-enrichment-pipe',
 Source=sqs_queue_arn,
 SourceParameters={
  'SqsQueueParameters': {
'BatchSize': 10,
'MaximumBatchingWindowInSeconds': 5
  },
  'FilterCriteria': {
'Filters': [
 {'Pattern': '{"body": {"eventType": ["ORDER_CREATED"]}}'}
]
  }
 },
 Enrichment=lambda_enrichment_arn, # 注文詳細を外部DBから補完
 EnrichmentParameters={
  'InputTemplate': '{"orderId": "<$.body.orderId>"}'
 },
 Target=event_bus_arn,
 TargetParameters={
  'EventBridgeEventBusParameters': {
'DetailType': 'EnrichedOrderEvent',
'Source': 'com.example.pipes'
  }
 },
 RoleArn=pipe_role_arn
)

Pipesの代表的なユースケース:

  • DynamoDB Streams → Lambda → SNS: テーブル変更イベントをフィルタ・エンリッチしてSNS配信
  • SQS → Lambda → EventBridge: キューメッセージを構造化イベントに変換して再配布
  • Kinesis → API Gateway: ストリームレコードをリアルタイムで外部APIに転送

Schema Registry

Schema Registryはイベントスキーマの自動検出・管理・型安全なコード生成を提供する。

# Custom Event Busにスキーマディスカバラーをアタッチ
aws schemas create-discoverer \
  --source-arn arn:aws:events:ap-northeast-1:123456789012:event-bus/order-events-bus \
  --description "Order events schema discoverer"

イベントを数回送信するとSchema Registryが自動でスキーマを推定・登録する。その後コードバインディングを生成して型安全なコードを取得する。

# Python コードバインディング生成
aws schemas get-code-binding-source \
  --registry-name discovered-schemas \
  --schema-name "com.example.orders@OrderCreated" \
  --language Python36 \
  --output text > order_created_schema.py

生成コードはOpenAPI 3.0互換スキーマを基にしており、Pythonではデータクラスとして定義される。Java/TypeScriptも同様の型安全クラスが生成される。スキーマのバージョン管理もRegistry側で自動追跡されるため、イベント仕様の変更履歴を一元管理できる。

SaaS Partner統合

EventBridgeはSaaSパートナーのイベントをネイティブに受信できる。

SaaSパートナーユースケース例
Zendeskチケット作成/更新 → Lambda でCRM自動同期
Datadogモニタリングアラート → SNS でチーム通知
PagerDutyインシデント → Step Functions で自動対応
Salesforceリード/商談イベント → SQS でバッチ処理
GitHubPRイベント → Lambda でCI/CD自動起動

SaaS側でEventBridgeイベントソースを設定し、AWSコンソールでパートナーイベントソースを紐付けたCustom Event Busを作成するだけで受信可能になる。追加インフラは不要。

EventBridge Archive & Replay

アーカイブ機能でイベントを長期保持し、必要に応じてリプレイ (再生) することでバグ修正後の再処理が可能になる。

# Custom Event Busにアーカイブ設定
events.create_archive(
 ArchiveName='order-events-archive',
 EventSourceArn=custom_event_bus_arn,
 Description='30日間イベント保持',
 EventPattern=json.dumps({'source': ['com.example.orders']}),
 RetentionDays=30 # 0=無期限
)

# アーカイブからリプレイ (バグ修正後の再処理)
from datetime import datetime, timezone

events.start_replay(
 ReplayName='replay-2026-05-01-range',
 Description='バグ修正後の再処理',
 EventSourceArn='arn:aws:events:ap-northeast-1:123456789012:archive/order-events-archive',
 EventStartTime=datetime(2026, 5, 1, 0, 0, 0, tzinfo=timezone.utc),
 EventEndTime=datetime(2026, 5, 2, 0, 0, 0, tzinfo=timezone.utc),
 Destination={
  'Arn': custom_event_bus_arn # 再生先のEvent Bus
 }
)

リプレイ時の注意点:

  • リプレイイベントは通常イベントと同じルールで処理される → ターゲットが同じアクションを再実行するため、べき等設計が必須
  • replay-name フィールドがイベントに付与されるため、Lambda側でリプレイフラグを検出して処理分岐が可能
  • 保持期間 RetentionDays: 0 (無期限) はストレージコストが継続増加するため、コンプライアンス要件と照らして期間を設定する
EventBridge Scheduler vs Rules スケジュール 使い分け

| 比較項目 | EventBridge Rules (スケジュール) | EventBridge Scheduler |
|———|——————————-|———————-|
| タイムゾーン指定 | 不可 (UTC固定) | 可能 |
| Flexible Time Window | なし | あり |
| One-time実行 | 不可 | 可能 |
| IAMロール指定 | なし (EventBridgeが自動管理) | 必須 |
| ターゲット数/設定 | 5つ/ルール | 1つ/スケジュール |

推奨: 新規実装はEventBridge Schedulerを採用。タイムゾーン対応・Flexible Time Window・One-time実行が必要な場合はScheduler一択。既存のEventBridgeルールベースのスケジュールは機能的に問題がなければ移行コストに見合わない場合もある。

EventBridge 本番運用チェックリスト

イベントバス設計
– Default Event Busにアプリイベントを流さない (ノイズ増加・300ルール制限に到達しやすい)
– ドメイン/環境単位でCustom Event Busを作成してルール上限を独立させる

ルール・ターゲット設計
– 1バス300ルール上限 → OR条件活用 + ドメイン分割で回避
– DLQ on Ruleを全ターゲットに設定し配信失敗を確実にキャプチャ
– RetryPolicyでMaximumRetryAttempts・MaximumEventAgeInSecondsを要件に合わせて設定

Archive & Replay 運用
– 本番バスには必ずアーカイブを設定 (バグ修正後の再処理コストがゼロに)
– リプレイ時はターゲットのべき等性を事前確認
– 保持期間はコスト・コンプライアンス要件で決定 (0=無期限はコスト注意)


Amazon API Gateway 本番運用 — REST vs HTTP API / 認可統合 / スロットリング

API Gateway REST/HTTP API + Lambda + Cognito認可統合フロー
fig04: API Gateway REST/HTTP API + Lambda + Cognito認可統合フロー

REST API vs HTTP API — 7軸選定ガイド

REST APIとHTTP APIはユースケースで使い分ける。以下7軸で最適解を選定する。

選定軸REST APIHTTP API
認可方式Cognito / Lambda Authorizer / IAM / API KeyJWT Authorizer / Lambda Authorizer / IAM
プロキシ統合Lambda Proxy / AWS統合 / VPC Link (NLB)Lambda Proxy / HTTP Proxy / VPC Link (ALB/NLB/CloudMap)
料金体系$3.50/100万リクエスト$1.00/100万リクエスト
スループット上限10,000 rps (アカウント上限・ステージ分割可)10,000 rps (調整可)
WebSocket対応別途WebSocket API別途WebSocket API
カスタムドメインEdge / Regional 両対応Regional のみ
リクエスト検証モデル / パラメータ Validator非対応 (バックエンド実装)

REST APIは認証統合の複雑さ・リクエスト検証・レスポンスキャッシュ・API Key管理が必要なエンタープライズ向けに適する。HTTP APIはコスト最優先・JWT認証で十分なシンプルユースケース向けで、料金はREST APIの約1/3。

REST API → HTTP API 移行チェックリスト

移行前に以下の機能依存を確認する。

要再実装: リクエスト検証 (Validator)・Usage Plan・レスポンスキャッシュ
そのまま移行: Lambda Proxy統合・カスタムドメイン (Regional)・CloudWatch Logs
コスト削減試算: 月間10億リクエストで年間約$30,000差。機能要件と削減額を比較してから判断する

ステージ管理 — Stage Variables / Canary Release

3ステージ運用パターン

# Stage Variables設定例 (CloudFormation)
RestApiStage:
  Type: AWS::ApiGateway::Stage
  Properties:
 RestApiId: !Ref RestApi
 StageName: prod
 Variables:
lambdaAlias: prod
backendUrl: "https://api.example.com"
 MethodSettings:
- ResourcePath: "/*"
  HttpMethod: "*"
  ThrottlingBurstLimit: 500
  ThrottlingRateLimit: 1000

Stage VariablesでステージごとにLambdaエイリアスやバックエンドURLを差し替える。Lambda統合では arn:aws:lambda:region:account:function:MyFunc:${stageVariables.lambdaAlias} の形式で参照する。dev/stg/prodの3ステージに異なるエイリアス(dev/stg/prod)を割り当て、環境差異をコード変更なしに吸収する。

Canaryデプロイ

{
  "canarySettings": {
 "percentTraffic": 10,
 "deploymentId": "abc123def456",
 "stageVariableOverrides": {
"lambdaAlias": "canary"
 },
 "useStageCache": false
  }
}

percentTraffic: 10 でリクエストの10%をCanaryデプロイに流す。エラー率・レイテンシが正常範囲内であれば UpdateStage でCanary割合を0にして本番切り替えを完了する。ロールバックは percentTraffic を0に戻すだけでよく、Lambdaエイリアス切り戻しと組み合わせると即時復旧できる。

認可統合

Cognito User Pool Authorizer

CognitoAuthorizer:
  Type: AWS::ApiGateway::Authorizer
  Properties:
 RestApiId: !Ref RestApi
 Name: CognitoAuth
 Type: COGNITO_USER_POOLS
 IdentitySource: method.request.header.Authorization
 ProviderARNs:
- !GetAtt UserPool.Arn

クライアントはAuthorizationヘッダにCognito IDトークン(JWT)を付与して送信する。API GatewayがJWT署名・issuer・audienceを自動検証するため、バックエンドLambdaは認証ロジックを実装しなくてよい。

Lambda Authorizer

種別IdentitySource用途
Token型BearerトークンSS (Authorizationヘッダ)OAuth2/JWT独自検証
Request型ヘッダ・クエリ・コンテキスト複合IP制限・複合条件認可

AuthorizerはIAMポリシーを返す。TTL設定(デフォルト300秒)でLambda呼び出しコストとレイテンシを削減する。

def lambda_handler(event, context):
 token = event["authorizationToken"]
 if is_valid(token):
  return {
"principalId": "user",
"policyDocument": {
 "Version": "2012-10-17",
 "Statement": [{
  "Action": "execute-api:Invoke",
  "Effect": "Allow",
  "Resource": event["methodArn"]
 }]
}
  }
 raise Exception("Unauthorized")

IAM認可 (Signature V4)

AWS_IAM認可タイプを設定するとSigV4署名が必須になる。ECS→API Gatewayなどサービス間通信に適する。クライアントはAWS SDKのSigV4署名機能かrequests-aws4authライブラリを使用する。

API Key + Usage Plan

# API Key作成とUsage Plan関連付け
aws apigateway create-api-key --name "partner-key" --enabled

aws apigateway create-usage-plan \
  --name "partner-plan" \
  --throttle burstLimit=100,rateLimit=50 \
  --quota limit=10000,period=MONTH

aws apigateway create-usage-plan-key \
  --usage-plan-id <planId> \
  --key-id <keyId> \
  --key-type API_KEY

Usage PlanはパートナーやAPIクライアント単位でレート制限とクォータを設定する手段として使う。API Keyはx-api-keyヘッダで送信する。

スロットリング設計

スロットリングは3階層で制御する。

階層設定箇所デフォルト上限
アカウントレベルサービスクォータ10,000 rps / 5,000 バースト
ステージレベルStage > Default Method Throttlingアカウント上限を複数ステージで分割
メソッドレベルStage > Method Settingsステージ設定を上書き

アカウントレベルの上限はService Quotasから引き上げ申請が可能。ステージごとに上限を分割し、特定エンドポイントへの集中を防ぐ。書き込み系APIのメソッドレベル制限を絞り込むことで読み取り系の安定性を保証できる。

# CDK: メソッドレベルスロットリング
const api = new apigateway.RestApi(this, "MyApi");
const orders = api.root.addResource("orders");
orders.addMethod("POST", lambdaIntegration);

const stage = api.deploymentStage;
stage.addMethodSettings("POST", "/orders", {
  throttlingBurstLimit: 50,
  throttlingRateLimit: 20,
});

レスポンスキャッシュ (REST API専用)

RestApiStage:
  Type: AWS::ApiGateway::Stage
  Properties:
 CacheClusterEnabled: true
 CacheClusterSize: "0.5"# 0.5/1.6/6.1/13.5/28.4/58.2/118/237 GB
 MethodSettings:
- ResourcePath: "/products"
  HttpMethod: "GET"
  CachingEnabled: true
  CacheDataEncrypted: true
  CacheTtlInSeconds: 300

キャッシュキーはデフォルトでURLパスパラメータとクエリ文字列を含む。クライアントからの強制無効化は Cache-Control: max-age=0 ヘッダを付与することで実現する(メソッド設定でInvalidateCache権限を許可する必要あり)。HTTP APIはキャッシュ機能を持たないため、CloudFrontを前段に置くことで代替する。

キャッシュコスト — 常時課金に注意

キャッシュクラスターはステージ単位で時間課金される。0.5GBで月間約$14。ステージ削除後もキャッシュ設定が残っていると課金継続するため、不要ステージのキャッシュは CacheClusterEnabled: false で明示的に無効化する。本番環境では CacheDataEncrypted: true を必ず設定する。

カスタムドメイン + ACM + Route 53

# 1. ACM証明書発行 (Regionalタイプはデプロイリージョン、Edgeはus-east-1必須)
aws acm request-certificate \
  --domain-name "api.example.com" \
  --validation-method DNS \
  --region ap-northeast-1

# 2. カスタムドメイン作成
aws apigateway create-domain-name \
  --domain-name "api.example.com" \
  --endpoint-configuration types=REGIONAL \
  --regional-certificate-arn arn:aws:acm:ap-northeast-1:123456789:certificate/xxxx

# 3. APIマッピング (ベースパスでバージョン管理)
aws apigateway create-base-path-mapping \
  --domain-name "api.example.com" \
  --rest-api-id <apiId> \
  --stage prod \
  --base-path "v1"

Route 53ではALIASレコード(AレコードまたはAAAAレコード)でカスタムドメインのRegionalDomainNameをターゲットに設定する。Edgeタイプは証明書をus-east-1で発行が必須。ベースパスマッピングによりapi.example.com/v1api.example.com/v2で異なるAPIステージを同一ドメインで運用できる。

VPC Link — プライベート統合

# REST API: NLB経由VPC Link
VpcLink:
  Type: AWS::ApiGateway::VpcLink
  Properties:
 Name: my-vpc-link
 TargetArns:
- !GetAtt NetworkLoadBalancer.LoadBalancerArn

# HTTP API: ALB/NLB/CloudMap対応
HttpApiVpcLink:
  Type: AWS::ApiGatewayV2::VpcLink
  Properties:
 Name: http-api-vpc-link
 SubnetIds:
- !Ref PrivateSubnetA
- !Ref PrivateSubnetB
 SecurityGroupIds:
- !Ref VpcLinkSg

VPC Linkを使うとインターネットを経由せずVPC内のプライベートリソース(ALB/NLB/ECS)へルーティングできる。REST APIはNLBのみ対応。HTTP APIはALB・NLB・Cloud Map(ECSサービスディスカバリ)に対応し、より柔軟なプライベート統合が可能。ECSサービスはCloud MapでVPCリンク経由で公開することでAPI Gatewayから直接到達できる。

アクセスログとモニタリング

{
  "requestId": "$context.requestId",
  "ip": "$context.identity.sourceIp",
  "httpMethod": "$context.httpMethod",
  "resourcePath": "$context.resourcePath",
  "status": "$context.status",
  "responseLatency": "$context.responseLatency",
  "integrationLatency": "$context.integrationLatency",
  "authorizerError": "$context.authorizer.error"
}

アクセスログはCloudWatch LogsまたはKinesis Data Firehoseへ転送できる。上記JSON形式はAthenaでのアドホック分析とCloudWatch Logs Insightsのレイテンシ集計に適する。

推奨モニタリングメトリクス:

メトリクス用途
4XXErrorクライアントエラー率 (認可失敗・バリデーションエラー検知)
5XXErrorバックエンドエラー率
Latencyエンドツーエンドレイテンシ (p99監視推奨)
IntegrationLatencyバックエンド (Lambda等) のレイテンシ
Countリクエスト総数 (スロットリング設計の基準値)

アクセス制御 — リソースポリシーとVPCエンドポイント

リソースポリシーを使用してIPアドレス・VPCエンドポイント単位でAPIへのアクセスを制限する。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-northeast-1:123456789:api-id/*",
"Condition": {
  "IpAddress": {
 "aws:SourceIp": ["203.0.113.0/24", "198.51.100.0/24"]
  }
}
 }
  ]
}

VPCエンドポイントポリシーと組み合わせることで、特定のVPCからのみAPIアクセスを許可するプライベートAPIを構成できる。外部からの不正アクセス遮断にはリソースポリシーによるIP制限・VPCエンドポイント制限が第一選択肢。トラフィック全体へのルールベース検査が必要な場合は、API GatewayへのAWS WAFアタッチメントを補完的に検討する。


AWS AppSync 本番運用 — GraphQLスキーマ / リゾルバ / リアルタイムサブスクリプション

sequenceDiagram
 participant Client
 participant AppSync as AWS AppSync
 participant Resolver as Resolver Pipeline
 participant DDB as DynamoDB
 participant Lambda as Lambda Function
 Client->>AppSync: GraphQL Query/Mutation
 AppSync->>Resolver: Pipeline実行
 Resolver->>DDB: データ取得/更新
 Resolver->>Lambda: カスタムロジック
 Resolver-->>AppSync: レスポンス集約
 AppSync-->>Client: JSON Response
 Note over Client,AppSync: Subscription (WebSocket)<br/>リアルタイム更新通知

GraphQLスキーマ設計 — スキーマファーストアプローチ

AppSyncはスキーマファーストアプローチを採用する。GraphQL SDL(Schema Definition Language)でAPIの型・クエリ・ミューテーション・サブスクリプションを定義し、各フィールドにリゾルバをアタッチしてデータソースと接続する。

Type / Query / Mutation / Subscription 基本構造

type Todo {
  id: ID!
  title: String!
  completed: Boolean!
  owner: String!
  createdAt: AWSDateTime!
}

type TodoConnection {
  items: [Todo]
  nextToken: String
}

type Query {
  getTodo(id: ID!): Todo
  listTodos(limit: Int, nextToken: String): TodoConnection
}

type Mutation {
  createTodo(title: String!, completed: Boolean): Todo
  updateTodo(id: ID!, completed: Boolean!): Todo
  deleteTodo(id: ID!): Todo
}

type Subscription {
  onCreateTodo: Todo @aws_subscribe(mutations: ["createTodo"])
  onUpdateTodo: Todo @aws_subscribe(mutations: ["updateTodo"])
}

ページネーション — nextToken パターン

大量データを取得する場合、DynamoDBのLastEvaluatedKeyをBase64エンコードしたnextTokenを返す。クライアントは次のリクエストでnextTokenを指定することで続きのアイテムを取得する。全件取得ループはクライアント側で実装する。

type ItemConnection {
  items: [Item]
  nextToken: String
}

type Query {
  listItems(
 filter: ModelItemFilterInput
 limit: Int
 nextToken: String
  ): ItemConnection
}

リゾルバ — Unit / Pipeline / Direct Lambda

リゾルバはGraphQLフィールドとデータソースを接続するロジックを定義する。AppSyncでは3種類のリゾルバが利用可能で、ユースケースに応じて使い分ける。

Unit Resolver

1フィールドに対して1つのデータソース操作を実行するシンプルなリゾルバ。DynamoDBのGetItemやPutItemなど単純なCRUD操作に適する。

Pipeline Resolver

複数のFunction(パイプライン関数)を順番に実行し、前のFunctionの出力を次のFunctionの入力として渡す。「認可チェック → データ取得 → 後処理」のような複数ステップを組み合わせる場合に有効。

JavaScript Resolver — VTLからの移行

AppSyncは2022年よりJavaScript/TypeScriptベースのリゾルバをGAリリース。従来のVTL(Velocity Template Language)と比べてデバッグが容易で、型安全な開発が可能になった。新規プロジェクトではJavaScript Resolverを標準とする。

import { util } from "@aws-appsync/utils";

export function request(ctx) {
  return {
 operation: "GetItem",
 key: util.dynamodb.toMapValues({ id: ctx.args.id }),
  };
}

export function response(ctx) {
  if (ctx.error) {
 util.error(ctx.error.message, ctx.error.type);
  }
  return ctx.result;
}

Direct Lambda Resolver

LambdaをデータソースとしてAppSyncが直接呼び出す方式。VTL/JSのマッピングテンプレート記述を省略でき、Lambda関数のハンドラにfieldNameargumentsが渡される。複雑なビジネスロジックや外部API連携に適する。

データソース別選定指針

データソース典型ユースケース注意点
DynamoDBプロファイル・タスク管理・設定保存トランザクション操作はPipeline Resolver必須
RDS (Aurora Serverless v2)リレーショナルクエリ・レポート生成コールドスタートとコネクション上限に注意
Lambda複雑なビジネスロジック・外部API連携タイムアウト管理が重要(最大30秒)
HTTP外部RESTエンドポイント呼び出しエラーハンドリングを丁寧に実装
OpenSearch全文検索・ファセット集計DynamoDBとの二重書きアーキテクチャが基本
AppSync リゾルバ選定チートシート

| シナリオ | 推奨リゾルバ | 理由 |
|———|————|——|
| 単一DynamoDB操作 | Unit Resolver (JS) | シンプル・高速 |
| 認可チェック→データ取得→変換 | Pipeline Resolver | 複数Functionを順次実行 |
| 複雑なビジネスロジック | Direct Lambda Resolver | Lambdaで自由に実装 |
| 外部REST API呼び出し | HTTP データソース | VTL/JSでリクエスト/レスポンスを変換 |
| 全文検索 | OpenSearch データソース | DynamoDBと二重書き構成を併用 |

新規プロジェクトはJavaScript Resolverを選択。VTLは既存資産がある場合のみ継続。

リアルタイムサブスクリプション — WebSocket接続管理

AppSyncのサブスクリプションはWebSocketを通じて実装される。クライアントがsubscribe操作でWebSocket接続を確立すると、指定したMutationが実行されるたびにリアルタイムで更新が配信される。AppSyncがWebSocket接続の管理・スケーリングを自動で処理するため、独自のWebSocketサーバー管理は不要になる。

@aws_subscribe ディレクティブ

スキーマのSubscriptionタイプに@aws_subscribeディレクティブを付与し、購読するMutation名を指定する。

type Subscription {
  onCreateTodo: Todo
 @aws_subscribe(mutations: ["createTodo"])

  onUpdateTodo: Todo
 @aws_subscribe(mutations: ["updateTodo"])

  onDeleteTodo: Todo
 @aws_subscribe(mutations: ["deleteTodo"])
 @aws_auth(cognito_groups: ["Admins"])
}

Enhanced Subscription Filtering

サーバーサイドフィルタリングにより、各クライアントは自身に関連するイベントのみを受け取る。フィルタはリゾルバ内で定義でき、接続ごとに動的な条件を設定できる。

export function request(ctx) {
  return { payload: null };
}

export function response(ctx) {
  const filter = {
 owner: { eq: ctx.identity.username },
  };
  extensions.setSubscriptionFilter(
 util.transform.toSubscriptionFilter(filter)
  );
  return null;
}

Merged API — マイクロサービス間のスキーマ統合

Merged APIは複数のAppSync API(Source API)のスキーマを1つのエンドポイントに統合する機能。各チームが独立して自サービスのスキーマを管理しながら、クライアントには単一のGraphQL APIを提供できる。

概念説明
Source API各マイクロサービスが独立管理するAppSync API
Merged API複数Source APIを統合した単一エンドポイント
MergingBehaviorAUTO_MERGE推奨(型衝突は手動解決が必要)
更新タイミングSource API更新後、Merged APIの再マージが必要

サーバーサイドキャッシュ

AppSyncのキャッシュは内部的にElastiCacheを使用し、同一クエリへの重複データソースアクセスを削減する。

キャッシュタイプ対象適用場面
Full Request Cacheクエリ全体同一クエリ+変数の組合せをまとめてキャッシュ
Per-resolver Cacheリゾルバ単位フィールドレベルで細かく制御したい場合
{
  "ttl_recommendations": {
 "マスタデータ(ほぼ変更なし)": "3600秒",
 "ユーザープロファイル(低頻度更新)": "300秒",
 "リアルタイム性が求められるデータ": "0(Per-resolver TTLを0に設定)"
  }
}

認可 — 5方式とMulti-auth設計

AppSyncは最大5つの認可方式を同時設定できる(マルチ認証)。プライマリ認証を1つ設定し、残りはセカンダリ認証として追加する。

認可タイプ典型ユースケース特徴
API_KEYパブリックAPI・開発テスト有効期限365日まで。本番での単独使用は非推奨
AWS_IAMバックエンドサービス間通信SigV4署名が必要。マシン間通信の標準
OPENID_CONNECTAuth0等サードパーティIdPJWTトークンで認証
AMAZON_COGNITO_USER_POOLSエンドユーザー認証Cognitoユーザープールと直接統合
AWS_LAMBDAカスタム認可ロジックLambda関数で任意の認証/認可ロジックを実装
type Query {
  getMyProfile: User @aws_cognito_user_pools
  listPublicPosts: [Post] @aws_api_key
  adminGetUser(id: ID!): User @aws_iam
}
AppSync Multi-auth 設計 3原則

1. プライマリ認証は Cognito User Pools — エンドユーザー向けAPIの標準構成
2. バックエンド連携は AWS_IAM — SigV4署名でサービス間認証。APIキー共有を排除
3. カスタムロジックは AWS_LAMBDA — 外部IdP統合・IP制限・レートリミット等を実装

Multi-auth設定後は@aws_authディレクティブでフィールドレベルのアクセス制御を追加し、認可漏れを防ぐ。


詰まりポイント7選 + アンチパターン→正解パターン変換

詰まり1 — SQS Visibility Timeout 不足で同一メッセージ二重処理

詰まり1: SQS Visibility Timeout 不足で同一メッセージ二重処理

症状: 同一メッセージがLambdaで複数回処理され、データの重複が発生する。

原因: Lambda関数の処理時間がSQSのVisibility Timeoutを超えた場合、メッセージが再度キューに表示され、別のLambdaインスタンスが同じメッセージを取得する。デフォルトのVisibility Timeout は30秒で、長時間バッチ処理では不足しやすい。

解決策:
– VisibilityTimeoutをLambdaタイムアウトの6倍以上に設定(Lambda 5分 → SQS 30分以上)
– 処理時間が変動する場合はLambda内からChangeMessageVisibility APIを呼び出して動的に延長
– 冪等性設計(DynamoDBの条件付き書き込み等)でダブル処理を許容する設計も有効

{
  "VisibilityTimeout": 1800,
  "_comment": "Lambdaタイムアウト5分の場合: 5分×6倍=30分=1800秒"
}

詰まり2 — SNS サブスクリプションフィルタ誤設定でメッセージ消失

詰まり2: SNS サブスクリプションフィルタ誤設定でメッセージ消失

症状: SNSにメッセージをPublishしているのに、SQS/Lambdaにメッセージが届かない。SNSコンソール上は送信成功になっている。

原因: サブスクリプションにフィルタポリシーを設定した場合、メッセージ属性が存在しないか値が一致しないメッセージは静かに破棄される。CloudWatch MetricsのNumberOfNotificationsFilteredOutで確認できるが、ログには何も残らない。

解決策:
– フィルタポリシー設定後はCloudWatch MetricsのNumberOfNotificationsFilteredOutを必ず監視
– PublisherがMessageAttributesを正しく付与しているかデバッグ時に確認
– フィルタなしサブスクリプションをDLQ向けに追加して破棄されたメッセージをモニタリング

import boto3

sns_client = boto3.client("sns")

# フィルタポリシーの値と一致するMessageAttributesを付与
response = sns_client.publish(
 TopicArn="arn:aws:sns:ap-northeast-1:123456789012:MyTopic",
 Message="payload",
 MessageAttributes={
  "eventType": {
"DataType": "String",
"StringValue": "ORDER_CREATED",
  }
 },
)

詰まり3 — EventBridge イベントパターン不一致で静かに捨てられる

詰まり3: EventBridge イベントパターン不一致で静かに捨てられる

症状: EventBridgeルールにイベントを送信しているが、ターゲット(Lambda/SQS等)が一度も呼ばれない。

原因: EventBridgeのイベントパターンは部分一致ではなく完全一致で評価される。sourcedetail-typeが大文字小文字を含めて完全に一致しないとルールはマッチしない。またdetailフィールドの構造がイベントと異なる場合も静かに無視される。

解決策:
– AWSコンソールの「Test event pattern」機能でイベントJSONとパターンの一致を確認
– デバッグ用にすべてのイベントをキャッチするルールを追加してCloudWatch Logsに転送
aws events test-event-patternコマンドでCLIから確認

{
  "source": ["myapp.orders"],
  "detail-type": ["OrderCreated"],
  "detail": {
 "status": ["CONFIRMED"]
  }
}

詰まり4 — API Gateway スロットリング未設定でバースト時429/502

詰まり4: API Gateway スロットリング未設定でバースト時429/502

症状: 負荷テスト時や一時的なバースト時に429 Too Many RequestsまたはLambdaで502 Bad Gatewayが発生する。

原因: API Gatewayのデフォルトスロットリングはアカウントレベル(10,000 req/s、バースト5,000)でのみ設定されており、個別APIやステージのスロットリングは未設定のことが多い。LambdaのConcurrency制限に先に達してしまう場合もある。

解決策:
– ステージレベルのデフォルトスロットリングを設定(rate/burst)
– 重要なリソースパスにはメソッドレベルのスロットリングを個別設定
– Lambda reserved concurrencyと合わせてリソース容量を設計する

{
  "throttle": {
 "rateLimit": 1000,
 "burstLimit": 2000,
 "_comment": "ステージレベルのデフォルトスロットリング設定"
  }
}

詰まり5 — AppSync Resolver VTL構文エラーでGraphQL null応答

詰まり5: AppSync Resolver VTL構文エラーでGraphQL null応答

症状: AppSync GraphQLクエリでnullが返り、エラーメッセージも不明瞭。CloudWatch LogsにTemplateProcessingExceptionが記録されている。

原因: VTL(Velocity Template Language)のリクエスト/レスポンスマッピングテンプレートに構文エラーがある場合、AppSyncはフィールドをnullとして返す。エラーはerrors配列に含まれるが、クライアント側でのエラーハンドリングが不十分だと見落としやすい。

解決策:
– CloudWatch LogsのフィールドログレベルをALLに設定してVTLのデバッグ情報を確認
– AWSコンソールの「Query」タブでクエリ結果のerrorsフィールドを確認
– 新規プロジェクトはVTLをJavaScript Resolverに移行してデバッグ容易性を向上

// JavaScript Resolverでエラーを明示的にスロー
export function response(ctx) {
  if (ctx.error) {
 util.error(ctx.error.message, ctx.error.type, ctx.result);
  }
  return ctx.result;
}

詰まり6 — SQS FIFO MessageGroupId設計ミスで全キュー直列化

詰まり6: SQS FIFO MessageGroupId設計ミスで全キュー直列化

症状: SQS FIFOキューのスループットが極端に低い。メッセージが高速で届くはずなのに処理が追いつかない。

原因: SQS FIFOキューは同一MessageGroupId内でメッセージの順序を保証するため、同一グループのメッセージは直列に処理される。MessageGroupIdを"default"や固定値1つに設定すると、全てのメッセージが1グループになり完全直列化する。

解決策:
– MessageGroupIdはメッセージの独立処理単位(ユーザーID・注文ID等)に設定
– 異なるグループのメッセージはLambdaで並列処理(最大300コンカレントポーリング)
– FIFOが不要ならStandardキューに変更してスループットを最大化

import boto3

sqs_client = boto3.client("sqs")

# 良い設計: user_idをMessageGroupIdに使用してユーザーごとに独立
sqs_client.send_message(
 QueueUrl="https://sqs.ap-northeast-1.amazonaws.com/123456789012/MyFIFO.fifo",
 MessageBody=order_payload,
 MessageGroupId=f"user-{user_id}",
 MessageDeduplicationId=str(order_id),
)

詰まり7 — EventBridge Archive未設定でイベント再生不能

詰まり7: EventBridge Archive未設定でイベント再生不能

症状: バグ修正後にイベントを再処理したいが、過去のイベントデータが存在せず再処理できない。

原因: EventBridgeのArchiveは明示的に設定しないとイベントが保存されない。デフォルトでは送信後のイベントは即時破棄される。本番環境でのデバッグや障害復旧時にイベント再生が必要になることは多い。

解決策:
– カスタムイベントバスと合わせてArchiveを設定(保存期間は最低30日を推奨)
– イベントパターンフィルタで必要なイベントのみArchiveしてコスト最適化
– 復旧時はaws events start-replayでArchiveからイベントを再実行

{
  "ArchiveName": "MyBusArchive",
  "EventSourceArn": "arn:aws:events:ap-northeast-1:123456789012:event-bus/MyBus",
  "RetentionDays": 90,
  "EventPattern": "{}"
}

アンチパターン→正解パターン変換 演習5問

本番環境で頻繁に見られるアンチパターンと、その正解パターンを示す。それぞれのパターンを理解し、自社の構成を点検してほしい。

演習1: SQS — 受信数上限なしでメッセージがDLQに移動しない

{
  "_comment": "❌ アンチパターン: RedrivePolicy未設定(メッセージが永久にキューに残る)",
  "QueueName": "MyQueue",
  "RedrivePolicy": null
}
{
  "_comment": "✅ 正解パターン: DLQとmaxReceiveCountを設定",
  "QueueName": "MyQueue",
  "RedrivePolicy": {
 "deadLetterTargetArn": "arn:aws:sqs:ap-northeast-1:123456789012:MyQueue-DLQ",
 "maxReceiveCount": 3
  }
}

演習2: SNS — MessageAttributes なしでフィルタポリシーを設定

# ❌ アンチパターン: メッセージ属性を付与せずに発行
# フィルタポリシーにマッチせずメッセージが破棄される
sns_client.publish(
 TopicArn="arn:aws:sns:ap-northeast-1:123456789012:MyTopic",
 Message="payload",
)

# ✅ 正解パターン: フィルタポリシーに対応したメッセージ属性を付与
sns_client.publish(
 TopicArn="arn:aws:sns:ap-northeast-1:123456789012:MyTopic",
 Message="payload",
 MessageAttributes={
  "eventType": {
"DataType": "String",
"StringValue": "ORDER_CREATED",
  }
 },
)

演習3: EventBridge — ルールが汎用的すぎて意図しないイベントをキャッチ

{
  "_comment": "❌ アンチパターン: sourceのみ指定でdetail-typeを限定しない",
  "source": ["aws.ec2"]
}
{
  "_comment": "✅ 正解パターン: detail-typeとdetail.stateで絞り込み",
  "source": ["aws.ec2"],
  "detail-type": ["EC2 Instance State-change Notification"],
  "detail": {
 "state": ["terminated"]
  }
}

演習4: API Gateway — 環境をハードコードしてステージ変数を使わない

# ❌ アンチパターン: バックエンドURLをハードコード
# Uri: "https://prod-api.example.com/endpoint"

# ✅ 正解パターン: ステージ変数でデプロイ環境を切り替え
Uri: !Sub "https://${stageVariables.backendHost}/endpoint"
# ステージ変数 backendHost に dev/stg/prod で異なる値を設定

演習5: AppSync — 全リゾルバにAPI_KEY認証のみ設定

# ❌ アンチパターン: 全フィールドにAPI_KEYのみ — 認可が実質ない
type Query {
  listAllUsers: [User] @aws_api_key
  getMyProfile: User@aws_api_key
  adminGetStats: Stats @aws_api_key
}

# ✅ 正解パターン: 用途別に認可方式を使い分け
type Query {
  listPublicItems: [Item] @aws_api_key
  getMyProfile: User @aws_cognito_user_pools
  adminGetStats: Stats @aws_iam
}

まとめ — Application Integration Vol1 起点宣言 + 全軸クロスリンク

§8-1: 5サービス要点まとめ表

Application Integration Vol1で取り上げた5サービスの要点を一覧にまとめる。サービス選定や本番運用時の参照テーブルとして活用してほしい。

サービス主要ユースケース選定基準本番運用キーポイント
Amazon SQS非同期処理・メッセージキューイング・Lambda統合順序保証が必要→FIFO、それ以外→StandardVisibility Timeout=Lambdaタイムアウト×6倍以上・DLQ必須・Long Polling設定
Amazon SNSPub/Sub・Fan-out・モバイルプッシュ複数エンドポイントへの同時配信→SNSサブスクリプションフィルタ設定時はMessageAttributes必須・FIFO TopicはSQSのみ対応
Amazon EventBridgeイベント駆動アーキテクチャ・スケジュール実行・SaaS統合ルールベースのルーティング・Schema Registry活用Archive設定必須・イベントパターンの完全一致検証・Pipes活用でコード削減
Amazon API GatewayREST/HTTP APIの公開・管理・認可統合低レイテンシ→HTTP API、拡張機能→REST APIステージレベルスロットリング設定・認可統合設計・キャッシュ活用
AWS AppSyncGraphQL API・リアルタイムサブスクリプションリアルタイム更新・型安全なAPIJavaScript Resolver採用・Multi-auth設計・Enhanced Subscription Filtering

5サービスの連携パターン例

パターン構成ユースケース
非同期注文処理API Gateway → SQS → Lambda注文受付のバックプレッシャー対応
イベント駆動通知EventBridge → SNS → SQS/Lambdaマイクロサービス間の疎結合連携
リアルタイムダッシュボードAppSync Subscription + DynamoDB Streamsライブデータ更新
スケジュールバッチEventBridge Scheduler → SQS → Lambda定期バッチ処理のキュー管理
APIオーケストレーションAPI Gateway → Lambda → AppSyncREST/GraphQL統合エンドポイント
Application Integration Vol1 全体サマリー

Vol1 達成したこと:

SQS: Standard/FIFO選定・DLQ設計・Visibility Timeout・Lambda統合・バッチ処理
SNS: Fan-outパターン・サブスクリプションフィルタ・FIFO Topic・モバイル配信
EventBridge: イベントバス設計・Scheduler・Pipes・Schema Registry・SaaS統合
API Gateway: REST/HTTP API選定・認可統合・スロットリング・キャッシュ・カスタムドメイン
AppSync: GraphQLスキーマ設計・リゾルバパイプライン・リアルタイムサブスクリプション・Merged API

5サービスを統合運用することで、疎結合・高可用・スケーラブルなAWSアーキテクチャを実現できる。

§8-2: 全軸クロスリンク

Application Integration Vol1は第25軸目として位置づけられる。既存の24軸と本記事の関連性を一覧にまとめる。

テーマ本記事との関連リンク
第1軸VPC/ネットワーク基盤設計SQS/SNSのVPCエンドポイント設計の基盤記事を読む
第2軸ハイブリッド接続 (Direct Connect/VPN/TGW)オンプレ→AWS間のEventBridgeイベント連携記事を読む
第3軸ネットワーク高度化 (TGW/PrivateLink/VPN)API GatewayのVPCリンク・PrivateLink統合記事を読む
第4軸Network Vol3 (Cloud WAN/VPC Lattice)AppSync/API GatewayのVPC Lattice統合記事を読む
第5軸データベース基盤 (RDS/Aurora/DynamoDB)SQS/AppSyncのデータソースとしてのDynamoDB記事を読む
第6軸データベースVol4 (Aurora DSQL/DynamoDB Strong)AppSync + DynamoDB強整合性設計記事を読む
第7軸コンテナVol1 (ECS/Fargate)SQS Consumerとしての Fargate タスク設計記事を読む
第8軸コンテナVol2 (EKS/ArgoCD/Kustomize)EventBridge → EKS イベント駆動ジョブ実行記事を読む
第9軸サーバーレスVol1 (Lambda/API GW/Step Functions)★最関連: API GatewayとLambda統合の深堀り記事を読む
第10軸サーバーレスVol2 (EventBridge/SQS/SNS/Kinesis)★最関連: イベント駆動視点での4サービス解説記事を読む
第11軸データ分析Vol1 (Athena/Glue/Redshift)EventBridgeでのデータパイプライントリガー記事を読む
第12軸データ分析Vol2 (Kinesis/MSK/QuickSight)SNS/SQSからKinesisへのデータ連携記事を読む
第13軸セキュリティVol3 (IAM/KMS/Secrets Manager)AppSync AWS_IAM認証・SQS暗号化 (KMS)記事を読む
第14軸可観測性Vol2 (X-Ray/OpenTelemetry/ADOT)API Gateway/AppSyncのX-Rayトレーシング記事を読む
第15軸コスト最適化Vol1 (Cost Explorer/Budgets)SQS/SNS/EventBridgeのコスト可視化記事を読む
第16軸コスト最適化Vol2 (RI/Spot/Graviton)AppSyncキャッシュによるコスト削減効果の計測記事を読む
第17軸DevOps/CI-CD Vol1 (CodePipeline/Build/Deploy)EventBridgeによるCI-CDパイプライントリガー記事を読む
第18軸DevOps/CI-CD Vol3 (CDK Pipelines/GitOps)AppSync CDKによるInfrastructure as Code管理記事を読む
第19軸エッジ/CDN Vol1 (CloudFront/Lambda@Edge/Route53)API Gatewayカスタムドメイン + CloudFront配置記事を読む
第20軸管理/ガバナンスVol1 (Organizations/Control Tower)マルチアカウントでのSNSクロスアカウント配信記事を読む
第21軸マイグレーションVol1 (DMS/MGN/Snow Family)オンプレアプリのAPIをAPI Gatewayで段階移行記事を読む
第22軸IoT Vol1 (IoT Core/Greengrass/SiteWise)IoT CoreからSNS/SQS/EventBridgeへのルーティング記事を読む
第23軸ML/AI Vol3 (SageMaker MLOps/Feature Store)EventBridgeによるMLパイプライントリガー記事を読む
第24軸生成AI/Bedrock (Agents/RAG/Knowledge Bases)AppSync GraphQL + Bedrock Agents統合記事を読む
第25軸Application Integration Vol1(本記事)SQS×SNS×EventBridge×API GW×AppSync統合プラットフォーム本記事
本記事との特に強い連携軸

第9軸(サーバーレスVol1): API GatewayとLambda統合の深堀り — 本記事のAPI Gateway章と双方向で参照
第10軸(サーバーレスVol2): イベント駆動アーキテクチャ視点でSQS/SNS/EventBridgeを解説 — 補完関係
第5軸(データベース基盤): AppSyncのDynamoDBリゾルバを実装する際の基礎知識を提供
第13軸(セキュリティVol3): AppSyncのIAM認証・SQS/SNSのKMS暗号化の詳細を解説

§8-3: 次記事予告 + シリーズ展望

Application Integration Vol1は第25軸目として「統合プラットフォーム」視点で5サービスを体系化した。Vol1完成により、AWS本番運用の全軸体系が60記事に達し、主要なAWSサービス領域をほぼ網羅したことになる。

Application Integration Vol2 (予定) — 次のフロンティア

Vol1で基礎を固めた5サービスに対し、Vol2では以下の高度化トピックを扱う予定:

トピック内容
Amazon MQActiveMQ/RabbitMQ対応のマネージドメッセージブローカー。オンプレメッセージングの移行先
AWS AppFlowSalesforceやGoogle Analytics等SaaSとS3/Redshiftのノーコードデータ転送
Step Functions × SQS/SNSDistributed Map + SQS/SNSを組み合わせた高スケールバッチオーケストレーション
EventBridge Pipes 高度活用フィルタ・エンリッチメント・SQS/Kinesis/DynamoDB Streamsとの統合パターン
AppSync Merged API 深堀りマイクロサービスチームでの分散スキーマ管理・衝突解決・CI-CD統合

AWS本番運用 全25軸 達成

[基盤層] VPC × ネットワーク × ハイブリッド接続
[コンピューティング] コンテナ(ECS/EKS) × サーバーレス(Lambda)
[データ層]  データベース × データ分析 × ML/AI × 生成AI
[統合層] Application Integration ← 第25軸 (本記事) ★NEW
[運用層] 可観測性 × セキュリティ × DevOps × コスト最適化 × ガバナンス

Vol1からVol2へ進む前に、全25軸のクロスリンクを通じて体系的な知識を深めてほしい。特にサーバーレスVol2(第10軸)はイベント駆動アーキテクチャの補完として必読だ。

§8-4: 読者アクションリスト — 明日から始める5ステップ

明日から始める Application Integration 5ステップ

Step 1: 既存アーキテクチャの統合点を棚卸し(1〜2日)
– 現在のサービス間連携がREST同期呼び出しになっていないか確認
– 失敗時の再試行・タイムアウト設計が欠如している箇所を特定
– SQS/SNS/EventBridgeで非同期化できる候補を洗い出す

Step 2: SQS DLQを全キューに設定(半日)
– 既存SQSキューのRedrivePolicy未設定を確認
– maxReceiveCount=3 + DLQをペアで作成
– DLQのCloudWatchアラームを設定

Step 3: EventBridge Archiveを本番イベントバスに設定(半日)
– カスタムイベントバスにArchiveを追加(保存期間90日以上を推奨)
– 将来の障害復旧・デバッグ時のイベント再生に備える

Step 4: API GatewayステージスロットリングをTerraform/CDKで管理(1日)
– 現在の設定をコードで表現してバージョン管理
– 本番/ステージング/開発で異なるスロットリング値を環境変数で切り替え

Step 5: AppSync新規プロジェクトでJavaScript Resolverを採用(1日)
– VTLで書かれた既存リゾルバをJS Resolverに移行する候補を1つ選ぶ
– Unit → JavaScript → テスト → 本番適用のサイクルを確立

§8-5: 参考リンク + 次のステップへ

Application Integration Vol1 の理解をさらに深めるためのリソースと、次の記事への案内を示す。

Application Integration Vol1 完走おめでとうございます。 SQS・SNS・EventBridge・API Gateway・AppSyncの5サービスを統合プラットフォーム視点で学んだことで、AWSにおけるサービス間連携の全体像が掴めたはずだ。

次のステップは サーバーレスVol2(第10軸) でイベント駆動アーキテクチャをより深く学ぶか、データ分析Vol1(第11軸) でEventBridgeで駆動するデータパイプラインを構築してほしい。Application Integration Vol2(Amazon MQ/AppFlow/Step Functions高度化)も今後公開予定なので、シリーズを引き続き追ってほしい。

本番運用 最終チェックリスト

本番環境に投入する前に、以下のチェックリストで5サービスの設定を確認してほしい。

Amazon SQS チェックリスト

  • [ ] 全キューにDLQ(Dead Letter Queue)を設定し、maxReceiveCountを適切に設定している
  • [ ] VisibilityTimeoutをLambdaタイムアウトの6倍以上に設定している
  • [ ] Long Polling(ReceiveMessageWaitTimeSeconds=20)を有効にしている
  • [ ] FIFOキューのMessageGroupIdがユーザー/エンティティ単位で設計されている
  • [ ] DLQのメッセージ滞留数にCloudWatchアラームを設定している

Amazon SNS チェックリスト

  • [ ] サブスクリプションフィルタを設定している場合、Publisherが正しいMessageAttributesを付与している
  • [ ] FIFO Topicを使用する場合、サブスクリプション先をSQS FIFOのみにしている
  • [ ] クロスアカウント配信の場合、リソースポリシーを適切に設定している
  • [ ] モバイルプッシュ通知のプラットフォームアプリケーションが有効期限内の証明書を使用している

Amazon EventBridge チェックリスト

  • [ ] 本番カスタムイベントバスにArchiveを設定し、保存期間を30日以上にしている
  • [ ] イベントパターンをAWSコンソールの「Test event pattern」で検証済み
  • [ ] スケジュールルールのタイムゾーン設定が意図したものになっている
  • [ ] Pipesでのエラー時の送信先(DLQ)を設定している

Amazon API Gateway チェックリスト

  • [ ] ステージレベルのデフォルトスロットリング(rate/burst)を設定している
  • [ ] 本番ステージでアクセスログを有効にしている
  • [ ] カスタムドメインのSSL証明書が有効期限内
  • [ ] 使用量プランとAPIキーを設定してクライアント別のレート制限を実装している

AWS AppSync チェックリスト

  • [ ] プライマリ認証にAPI_KEY単独を使用していない(本番環境)
  • [ ] CloudWatch Logsのフィールドログレベルを適切に設定している(本番:ERROR、開発:ALL)
  • [ ] サブスクリプションを使用している場合、Enhanced Subscription Filteringを設定している
  • [ ] キャッシュのTTL設定がデータの更新頻度に合っている
Application Integration Vol1 完了宣言

本記事でAWS Application Integration Vol1の全セクションを完走した。SQS・SNS・EventBridge・API Gateway・AppSyncの5サービスは、個々の理解だけでなく「組み合わせてシステムを設計する」視点が本番運用の核心だ。

詰まり7選とアンチパターン演習5問を自社の既存構成と照らし合わせ、改善できる点から一歩ずつ進めてほしい。Vol2の公開まで、全25軸のクロスリンクを活用して体系的な知識を深めることを勧める。