目次

  1. キュータイプの選択
  2. 冪等性(最重要)
  3. 可視性タイムアウト
  4. デッドレターキュー(DLQ)
  5. メッセージの受信(ポーリング)
  6. 送信・バッチ処理
  7. Lambda との連携(イベントソースマッピング)
  8. 遅延・保持期間
  9. セキュリティ
  10. 監視・アラーム
  11. アーキテクチャパターン
  12. コスト最適化
  13. 運用チェックリスト

1. キュータイプの選択

観点Standard キューFIFO キュー
配信保証少なくとも1回(重複あり得る)正確に1回処理(重複排除ウィンドウ5分)
順序ベストエフォートメッセージグループ単位で厳密
スループットほぼ無制限高スループットモードで大幅に向上(リージョン依存)
主な用途大量の非同期処理、疎結合化順序が重要な処理(決済、在庫更新など)
  • 基本は Standard を選び、順序・重複排除が本当に必要な場合のみ FIFO を選ぶ。
  • FIFO を使う場合は MessageGroupId を細かく分割して並列度を確保する(単一グループだと実質シリアル処理になる)。
  • 高スループットが必要な FIFO は「高スループットモード」(DeduplicationScope=messageGroup、FifoThroughputLimit=perMessageGroupId)を有効化する。
  • マルチテナントの Standard キューで特定テナントが他を圧迫する(noisy neighbor)場合は フェアキュー(MessageGroupId をテナントIDとして付与)を検討する。

2. 冪等性(最重要)

  • Standard キューは 同一メッセージが複数回届く前提 で設計する。FIFO でも、可視性タイムアウト切れ等による再処理は起こり得る。
  • コンシューマーは冪等に実装する。
    • メッセージに一意のID(業務キー)を持たせ、DynamoDB の条件付き書き込み等で処理済みを記録する。
    • 「処理済みチェック → 処理 → 記録」はアトミックに、もしくは処理自体を冪等(UPSERT など)にする。
  • SQS の MessageId は再送時に変わるケースがあるため、業務側で生成した冪等キー を使う。

3. 可視性タイムアウト

  • 処理時間の最大値より十分長く設定する(目安: 想定処理時間の数倍)。短すぎると処理中に他のコンシューマーが同じメッセージを受信してしまう。
  • 処理時間が読めない場合は、処理中に ChangeMessageVisibility でハートビート的に延長する。
  • Lambda をトリガーにする場合は、可視性タイムアウト ≥ Lambda タイムアウト × 6 が推奨値。
  • 処理に失敗した際、即時リトライさせたいなら可視性タイムアウトを 0 に変更して戻すことも可能。

4. デッドレターキュー(DLQ)

  • すべての本番キューに DLQ を設定する。毒メッセージ(何度処理しても失敗するメッセージ)が無限にリトライされるのを防ぐ。
  • maxReceiveCount は一時的な障害を吸収できる程度(例: 3〜5)に設定する。
  • DLQ のメッセージ保持期間は 元キューより長く 設定する(Standard キューではエンキュー時刻が引き継がれるため、短いと DLQ 到着直後に消える)。
  • DLQ のメッセージ数(ApproximateNumberOfMessagesVisible)に CloudWatch アラーム を設定する。
  • 原因修正後は DLQ redrive(コンソール/API)で元キューへ戻す運用手順を用意しておく。
  • FIFO キューの DLQ は FIFO である必要がある。

5. メッセージの受信(ポーリング)

  • ロングポーリングを使う(WaitTimeSeconds を最大 20 秒、またはキュー属性 ReceiveMessageWaitTimeSeconds=20)。空レスポンスが減り、コストとレイテンシの両方が改善する。
  • MaxNumberOfMessages=10 で一度に複数件受信する。
  • 処理が成功したメッセージだけを確実に DeleteMessage(またはバッチ削除)する。削除漏れは重複処理の原因になる。
  • コンシューマーの並列数はキューの滞留状況に応じてスケールさせる(後述の監視メトリクスを利用)。

6. 送信・バッチ処理

  • SendMessageBatch / DeleteMessageBatch / ChangeMessageVisibilityBatch で 最大10件をまとめる。API 呼び出し回数=コストが減る。
  • バッチ API は 部分失敗 があり得るため、レスポンスの Failed を確認して再送する。
  • SDK のリトライ設定(指数バックオフ + ジッター)を適切に構成する。
  • 大きなペイロード(上限超過、または大きなデータ)は S3 に置き、SQS には参照だけを送る(Extended Client Library: Java / Python 等)。小さなメッセージに保つほどスループット・コスト面で有利。

7. Lambda との連携(イベントソースマッピング)

  • 部分バッチレスポンス(ReportBatchItemFailures)を有効にし、失敗したメッセージだけを再試行させる。これがないと1件の失敗でバッチ全体が再処理される。
  • BatchSize と MaximumBatchingWindowInSeconds を調整して、呼び出し回数とレイテンシのバランスをとる。
  • 下流(DB・外部API)を保護するため 最大同時実行数(MaximumConcurrency) を設定する。予約同時実行数で絞るとスロットリング→リトライ→DLQ 行きが起きやすいので、こちらを優先する。
  • スパイクに即応したい・低レイテンシが必要な場合は、ESM の プロビジョンドモード を検討する。
  • 可視性タイムアウトは前述の通り Lambda タイムアウトの6倍以上にする。

8. 遅延・保持期間

  • メッセージ保持期間(デフォルト4日、最大14日)は、障害からの復旧にかかる時間を考慮して設定する。
  • 特定時間後に処理させたい場合は遅延キュー(キュー単位)またはメッセージタイマー(メッセージ単位、Standard のみ)を使う。上限は15分なので、それ以上は EventBridge Scheduler 等を使う。

9. セキュリティ

  • サーバー側暗号化: 新規キューは SSE-SQS がデフォルト有効。キーの管理・監査要件がある場合は SSE-KMS(カスタマー管理キー)を使い、KMS のデータキー再利用期間を調整して KMS 呼び出しコストを抑える。
  • 最小権限: IAM ポリシー・キューポリシーで送信側には sqs:SendMessage、受信側には sqs:ReceiveMessage / sqs:DeleteMessage 等、必要なアクションだけを許可する。
  • キューポリシーで SNS/EventBridge 等から許可する場合は aws:SourceArn / aws:SourceAccount 条件で送信元を限定する(混乱した代理問題対策)。
  • 転送時の暗号化: aws:SecureTransport 条件で HTTPS 以外を拒否する。
  • VPC 内からのアクセスは VPC エンドポイント(PrivateLink) を使い、エンドポイントポリシーで対象キューを限定する。
  • メッセージ本文に機密情報(個人情報・認証情報)をそのまま入れない。必要なら参照IDのみ渡す。

10. 監視・アラーム

主要な CloudWatch メトリクスとアラーム例:

メトリクス見るポイント
ApproximateAgeOfOldestMessage処理遅延の最重要指標。SLA を超えたらアラーム
ApproximateNumberOfMessagesVisible滞留量。コンシューマーのスケール判断に使う
ApproximateNumberOfMessagesNotVisible処理中(インフライト)件数。上限(Standard 約12万、FIFO 2万)に注意
NumberOfMessagesSent / NumberOfMessagesDeleted流入・処理量のバランス
NumberOfEmptyReceives多ければロングポーリング未設定や過剰なコンシューマーを疑う
DLQ の ApproximateNumberOfMessagesVisible1件以上でアラーム
  • EC2/ECS のコンシューマーは「1インスタンスあたりのバックログ」(滞留数 ÷ 稼働タスク数)を指標にターゲット追跡スケーリングする。
  • 分散トレーシングが必要なら AWS X-Ray のトレースヘッダーを伝播させる。

11. アーキテクチャパターン

  • ファンアウト: SNS トピック(または EventBridge)→ 複数 SQS キュー。各サブスクライバーが独立して処理・リトライできる。
  • 負荷平準化(バッファ): スパイクを SQS で吸収し、下流は一定のペースで処理する。
  • 優先度: SQS にはメッセージ単位の優先度がないため、優先度別にキューを分けてコンシューマーで高優先から読む。
  • リクエスト/レスポンス: 一時キュー(Temporary Queue Client)や相関IDを用いる。ただし同期的な用途なら SQS 以外の手段も検討する。
  • EventBridge Pipes を使うと、SQS → フィルタ/変換 → ターゲット をコードなしで構成できる。

12. コスト最適化

  • ロングポーリング、バッチ API で リクエスト数を減らす(課金はリクエスト単位、64KB チャンクごとに1リクエスト換算)。
  • 不要な ReceiveMessage を空打ちしない(コンシューマーの過剰プロビジョニングを避ける)。
  • SSE-KMS 利用時はデータキー再利用期間を長め(例: 最大24時間まで)にして KMS API コストを抑える。
  • FIFO は Standard より単価が高いため、必要な場合のみ使う。

13. 運用チェックリスト

  • Standard / FIFO の選定理由が明確
  • コンシューマーが冪等
  • 可視性タイムアウトが最大処理時間より十分長い(Lambda なら6倍以上)
  • DLQ を設定し、保持期間を元キューより長くしている
  • DLQ・メッセージ滞留時間にアラームがある
  • DLQ redrive の手順がある
  • ロングポーリング(20秒)を設定
  • バッチ API を使用し、部分失敗を処理している
  • Lambda では ReportBatchItemFailures と最大同時実行数を設定
  • 暗号化(SSE)と最小権限ポリシー、HTTPS 強制
  • ペイロードが大きい場合は S3 参照パターン
  • 保持期間が障害復旧時間をカバーしている

参考

0件のページ