AWS SQS FIFO + Lambda による Prepare-Challenge パターン実装ガイド
1. 概要
非同期処理を確実に完了させるPrepare-Challengeパターンを、AWS SQS FIFO(First-In-First-Out)キューとLambdaを使って実装するためのガイドです。
1.1 パターンの目的
- 外部システムとの非同期処理を確実に完了
- 処理の順序性を保証
- システム負荷の制御
- 処理状態の追跡容易性
1.2 AWS サービスの選定理由
- 
SQS FIFO - メッセージの厳密な順序保証
- 重複排除機能
- メッセージグループによる並列処理の制御
- デッドレターキュー(DLQ)によるエラー処理
 
- 
Lambda - サーバーレスでの柔軟なスケーリング
- SQSとの統合が容易
- コスト効率の良い実行環境
- 監視・ログ収集の容易さ
 
2. キュー設計パターン
2.1 優先度別キューの構成
高優先度キュー
const highPriorityQueue = new sqs.Queue(this, 'HighPriorityQueue', {
  fifo: true,
  contentBasedDeduplication: true,
  retentionPeriod: Duration.minutes(15),
  visibilityTimeout: Duration.seconds(30)
});
- 即時処理が必要な重要な業務処理用
- 短い保持期間と可視性タイムアウト
- 1メッセージずつの即時処理
標準優先度キュー
const standardPriorityQueue = new sqs.Queue(this, 'StandardPriorityQueue', {
  fifo: true,
  contentBasedDeduplication: true,
  retentionPeriod: Duration.hours(1),
  visibilityTimeout: Duration.seconds(30)
});
- 通常の業務処理用
- 適度な保持期間
- バッチサイズによる効率的な処理
低優先度キュー
const lowPriorityQueue = new sqs.Queue(this, 'LowPriorityQueue', {
  fifo: true,
  contentBasedDeduplication: true,
  retentionPeriod: Duration.hours(2),
  visibilityTimeout: Duration.seconds(60)
});
- バッチ処理など、時間的余裕のある処理用
- 長めの保持期間と可視性タイムアウト
- 大きめのバッチサイズでの処理
2.2 共通の設定ポイント
- 
コンテンツベースの重複排除 - contentBasedDeduplication: true
- メッセージ本体に基づく自動的な重複排除
- 5分間の重複排除ウィンドウ
 
- 
デッドレターキュー(DLQ) deadLetterQueue: { queue: dlqQueue, maxReceiveCount: 3 }- 失敗メッセージの分離
- 再処理ポリシーの設定
- 長期の保持期間設定
 
- 
メッセージグループID - 同一処理グループ内での順序保証
- 業務単位での並列処理制御
 
3. Lambda Trigger設定
3.1 基本設定
const eventSource = new lambdaEventSources.SqsEventSource(queue, {
  batchSize: 10,
  maxBatchingWindow: Duration.seconds(5),
  reportBatchItemFailures: true
});
3.2 優先度別の設定例
高優先度キューのトリガー
{
  batchSize: 1,
  maxBatchingWindow: Duration.seconds(0),
  reportBatchItemFailures: true
}
標準優先度キューのトリガー
{
  batchSize: 5,
  maxBatchingWindow: Duration.seconds(5),
  reportBatchItemFailures: true
}
低優先度キューのトリガー
{
  batchSize: 10,
  maxBatchingWindow: Duration.seconds(10),
  reportBatchItemFailures: true
}
4. メッセージ送信パターン
4.1 基本的なメッセージ構造
interface PrepareChallengeMessage {
  processType: string;
  priority: 'HIGH' | 'STANDARD' | 'LOW';
  requestId: string;
  timestamp: string;
  payload: {
    [key: string]: any;
  };
  metadata?: {
    retryCount?: number;
    originalTimestamp?: string;
  };
}
4.2 送信パラメーター例
const sendParams = {
  QueueUrl: queueUrl,
  MessageBody: JSON.stringify(message),
  MessageGroupId: groupId,
  MessageDeduplicationId: deduplicationId
};
4.3 メッセージグループIDの設定パターン
- 
注文処理の場合 MessageGroupId: `ORDER_${orderId}`- 同一注文の順序性保証
 
- 
顧客単位の処理の場合 MessageGroupId: `CUSTOMER_${customerId}`- 同一顧客の処理順序保証
 
- 
バッチ処理の場合 MessageGroupId: `BATCH_${batchType}`- 同種バッチの順序性保証
 
5. エラーハンドリング
5.1 Lambda側の実装
export const handler = async (event: SQSEvent) => {
  const batchItemFailures: { itemIdentifier: string }[] = [];
  for (const record of event.Records) {
    try {
      const success = await processMessage(record);
      if (!success) {
        batchItemFailures.push({ 
          itemIdentifier: record.messageId 
        });
      }
    } catch (error) {
      batchItemFailures.push({ 
        itemIdentifier: record.messageId 
      });
    }
  }
  return { batchItemFailures };
};
5.2 再処理戦略
- 
Prepare Phase失敗時 - 同一キューの後方に再エンキュー
- バックオフ時間の設定
- 最大再試行回数の管理
 
- 
Challenge Phase失敗時 - DLQへの移動
- アラート通知
- 手動再処理の検討
 
6. モニタリングと運用
6.1 CloudWatchメトリクス
- キューの深さ
- 処理遅延時間
- エラー率
- DLQメッセージ数
6.2 アラート設定
new cloudwatch.Alarm(this, 'DLQAlarm', {
  metric: dlqQueue.metricApproximateNumberOfMessagesVisible(),
  threshold: 1,
  evaluationPeriods: 1,
  alarmDescription: 'Messages in DLQ detected'
});
6.3 運用上の注意点
- 
キャパシティ管理 - FIFOキューの制限(1秒あたり300メッセージ)
- Lambda同時実行数の制限
- メモリ使用量の監視
 
- 
コスト最適化 - バッチサイズの適切な設定
- Lambda実行時間の最適化
- 保持期間の適切な設定
 
- 
メンテナンス性 - ログレベルの適切な設定
- エラーメッセージの明確化
- デバッグ情報の充実
 
7. ベストプラクティス
- 
設計原則 - 単一責任の原則を守る
- 疎結合な設計を心がける
- 監視可能性を確保する
 
- 
実装のポイント - メッセージの冪等性確保
- タイムアウト値の適切な設定
- エラーハンドリングの徹底
 
- 
運用面での推奨事項 - 定期的なDLQの確認
- パフォーマンスメトリクスの監視
- キャパシティプランニングの実施