Amazon Connect の StartOutboundVoiceContact API で冪等性パラメータを使って二重発信を防ぐ考え方を整理してみた

Amazon Connect の StartOutboundVoiceContact API で冪等性パラメータを使って二重発信を防ぐ考え方を整理してみた

SQS、SNS、EventBridgeからLambdaを起動する構成では、同じメッセージが複数回処理される可能性があります。Amazon ConnectのStartOutboundVoiceContact APIの`ClientToken`パラメータを活用した二重発信防止と、DynamoDBによる重複管理の使い分けについてまとめます。
2026.08.03

はじめに

Amazon SQS の標準キュー、Amazon SNS の標準トピック、Amazon EventBridge などを起点に AWS Lambda(以下、Lambda)を起動する構成では、同じメッセージやイベントが複数回処理される可能性があります。

例えば、Lambda から Amazon Connect の StartOutboundVoiceContact API を呼び出して電話を発信する構成を考えます。今回は、同じ通知リクエストに対して、同じ相手へ複数回発信したくないものとします。

重複処理への対策として、Amazon DynamoDB(以下、DynamoDB)などで処理済みフラグを管理する方法があります。一方、後続の API が冪等性をサポートしていれば、API が用意しているパラメータを使って二重発信や重複作成を防げる場合があります。

StartOutboundVoiceContact API には、リクエストの冪等性を確保するための ClientToken パラメータがあります。

今回は、AWS API が提供する冪等性パラメータの一例として、StartOutboundVoiceContact API の ClientToken の使い方と、DynamoDB などによる重複管理との使い分けを整理します。

結論

同じ発信リクエストを再試行する場合は、同じ ClientToken を指定します。

トークンの有効期間内にコンタクトがすでに開始されている場合、StartOutboundVoiceContact API は新しいコンタクトを開始せず、既存の ContactId を返します。

次の条件を満たすのであれば、二重発信防止だけを目的として、DynamoDB に処理済みフラグを保存する必要は基本的にありません。

  • 同じ論理リクエストに対して同じ ClientToken を指定できる
  • 重複処理がトークンの有効期間である7日以内に行われる
  • 重複を防ぎたい対象が StartOutboundVoiceContact API による電話発信である

一方、次のような場合は、DynamoDB などの外部ストアを検討します。

  • 7日を超えて同じ通知の重複を防ぎたい
  • 複数システムからの発信要求を一元的に管理したい
  • 発信履歴や再架電状態を管理したい
  • 電話発信以外の処理も含めて重複を制御したい

整理すると、以下のようになります。

目的 対応
API の再試行による二重発信を防ぎたい 同じ ClientToken を指定する
SQS や EventBridge の再処理を同じ発信として扱いたい 通知 ID などから同じ ClientToken を生成する
7日を超えて重複を防ぎたい DynamoDB などで業務上の重複を管理する
複数システムから同じ要求が来る可能性がある 共通の ID 設計や共有ストアを検討する
発信履歴や再架電状態を管理したい DynamoDB などに業務データとして保存する

ポイントは、ClientToken が防ぐのは Lambda の重複実行そのものではなく、StartOutboundVoiceContact API が再実行された場合の二重発信である点です。

同じメッセージやイベントが複数回処理される可能性がある

SQS 標準キュー、SNS、EventBridge などを起点に Lambda を実行する構成では、同じメッセージやイベントが複数回処理される可能性があります。

SQS、SNS、EventBridge

Lambda

StartOutboundVoiceContact

SQS を Lambda のイベントソースとして利用する場合、Lambda のイベントソースマッピングは各イベントを少なくとも1回処理します。そのため、同じレコードが重複して処理される可能性があります。

https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html

SNS から Lambda を起動する場合も、Lambda は非同期で呼び出されるため、同じイベントが複数回処理される可能性があります。

https://docs.aws.amazon.com/lambda/latest/dg/with-sns.html

EventBridge がターゲットへのイベント配信に失敗した場合は、再試行ポリシーに従って配信が再試行されます。デフォルトでは、24時間、最大185回再試行されます。

https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-retry-policy.html

また、EventBridge から Lambda にイベントが渡された後は、Lambda の非同期呼び出しによる再試行も関係します。関数がエラーを返した場合はデフォルトで追加の実行が2回行われ、エラーを返していない場合でも同じイベントを複数回受け取る可能性があります。

https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-error-handling.html

そのため、これらのサービスを起点に Lambda を実行する場合は、後続の API が複数回呼び出されても二重発信や重複作成が発生しないように設計する必要があります。

AWS API における冪等性パラメータの例

ClientToken のような冪等性パラメータは、Amazon Connect 固有のものではありません。

AWS Builders Library の「Making retries safe with idempotent APIs」では、安全に API を再試行する方法として、呼び出し元が一意のリクエスト識別子を指定する設計が説明されています。

https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/

AWS API における冪等性パラメータの例は、以下のとおりです。

サービス API 例 パラメータ例 補足
Amazon Connect StartOutboundVoiceContact ClientToken トークンは7日間有効。開始済みの場合は既存の ContactId が返る
Amazon Connect StartChatContactStartTaskContact ClientToken コンタクト開始リクエストの冪等性に利用する
Amazon EC2 RunInstancesCreateVolume など ClientToken 一部の API がクライアントトークンをサポートする
Amazon ECS RunTaskCreateService など clientToken 同じトークンと同じリクエストパラメータによる再試行を冪等に扱う
Amazon DynamoDB TransactWriteItems ClientRequestToken トークンは最初のリクエスト完了後10分間有効
AWS Secrets Manager PutSecretValue ClientRequestToken シークレットバージョンの識別子として利用する
AWS CloudFormation CreateStack ClientRequestToken リクエストの識別やイベントの追跡に利用する
AWS Step Functions StartExecution nameinput STANDARD ワークフローでは、同じステートマシンに対する同じ nameinput の実行が進行中の場合に、元のリクエストと同じレスポンスが返る

API ごとに、パラメータ名、有効期間、適用範囲、同じトークンで異なるパラメータを指定した場合の挙動が異なります。

そのため、利用する API のドキュメントで個別に仕様を確認する必要があります。

参考資料:

StartOutboundVoiceContact API の ClientToken とは

StartOutboundVoiceContact API の ClientToken は、リクエストの冪等性を確保するために指定する識別子です。

項目 内容
パラメータ名 ClientToken
用途 リクエストの冪等性を確保する
大文字小文字 区別される
最大長 500文字
必須かどうか 必須ではない
未指定時 AWS SDK が値を設定する
有効期間 作成後7日間
コンタクトが開始済みの場合 既存の ContactId が返される

https://docs.aws.amazon.com/connect/latest/APIReference/API_StartOutboundVoiceContact.html

同じ ClientToken でリクエストを再試行し、コンタクトがすでに開始されている場合は、既存の ContactId が返されます。

一方、同じ ClientToken を使いながら、宛先電話番号やコンタクトフローなどのリクエストパラメータを変更した場合の挙動は、StartOutboundVoiceContact API の公式ドキュメントには明記されていません。

そのため、同じ ClientToken は、リクエストパラメータも同じである、同一の論理リクエストの再試行にだけ使用するのが安全です。

同じ論理リクエストの再試行
  → 同じ ClientToken と同じリクエストパラメータを使う

別の論理リクエスト
  → 別の ClientToken を使う

ClientToken の決め方

ClientToken は、再処理のたびに新しい値を生成するのではなく、通知 ID や受信者 ID などの業務 ID から決定します。

例えば、「同じ通知 ID、かつ同じ受信者 ID」を同じ発信要求とみなす場合は、次のような値を使用できます。

call-notification-12345-user-67890

SQS メッセージの送信側で clientToken を決め、メッセージ本文に含める方法もあります。

{
  "notificationId": "notification-12345",
  "recipientId": "user-67890",
  "destinationPhoneNumber": "+8190xxxxxxxx",
  "clientToken": "call-notification-12345-user-67890"
}

また、複数の ID を連結してハッシュ化する方法もあります。

ClientToken = SHA-256(
  notificationId + "\n" +
  recipientId
)

重要なのは、同じ論理リクエストからは同じ値が生成され、別の論理リクエストからは別の値が生成されることです。

なお、同じ通知、同じ相手への発信であっても、業務上の意図的な再架電は別の論理リクエストです。その場合は、再架電単位の ID を含めて別の ClientToken を生成します。

Lambda や API の再試行
  → 同じ ClientToken

業務上の意図的な再架電
  → 別の ClientToken

EventBridge の id を利用する場合

EventBridge のイベントには、トップレベルに id フィールドがあります。id はイベントごとに生成される一意な識別子で、イベントの追跡に利用できます。

https://docs.aws.amazon.com/eventbridge/latest/ref/events-structure.html

EventBridge による同じイベントの再配信だけを重複とみなすのであれば、この idClientToken の元にできます。

ただし、同じ通知要求が送信元から複数回 PutEvents された場合、それぞれ別の EventBridge イベントとなり、異なる id が付与されます。

そのため、「同じ通知要求が複数回登録された場合も、1回の発信として扱いたい」という要件では、イベントの detail に通知 ID や受信者 ID を含め、その値から ClientToken を生成します。

{
  "id": "11111111-1111-1111-1111-111111111111",
  "detail": {
    "notificationId": "notification-12345",
    "recipientId": "user-67890",
    "destinationPhoneNumber": "+8190xxxxxxxx"
  }
}
重複とみなす範囲 ClientToken の元にする値
同じ EventBridge イベントの再配信 トップレベルの id
同じ通知要求の複数回登録 notificationIdrecipientId などの業務 ID
複数システムから送信された同じ通知 システム間で共通化した通知 ID

ClientToken を指定しない場合

StartOutboundVoiceContact API では、ClientToken を指定しなかった場合、AWS SDK が値を設定します。

ただし、SQS や EventBridge の再処理によって Lambda が改めて実行された場合、前回の Lambda 実行と同じ ClientToken が自動的に使われることは保証されません。

1回目の Lambda 実行
  → AWS SDK が ClientToken を自動設定

同じメッセージによる2回目の Lambda 実行
  → 前回と同じ ClientToken が設定される保証はない

異なる ClientToken が使われた場合、Amazon Connect からは別の発信リクエストとして扱われる可能性があります。

そのため、SQS や EventBridge の再処理を含めて二重発信を防ぎたい場合は、通知 ID などから決定した ClientToken をアプリケーション側で明示的に指定します。

DynamoDB を検討するケース

ClientToken は、StartOutboundVoiceContact API の再試行による二重発信を防ぐための仕組みです。通知単位の長期的な重複排除や、発信履歴の管理をすべて置き換えるものではありません。

7日を超えて重複を防ぎたい場合

ClientToken の有効期間は作成後7日間です。

例えば、次のような要件は業務ルールとしての重複排除であり、DynamoDB などで管理する必要があります。

同じ通知 ID と同じユーザー ID への発信は、
30日間に1回だけにしたい

次のような運用がある場合は、同じ通知が7日を超えて再処理される可能性があります。

  • DLQ のメッセージを後日再投入する
  • 障害復旧後に過去のイベントを再処理する
  • EventBridge のアーカイブからイベントをリプレイする
  • 過去の通知を手動で再実行する

DynamoDB を利用する場合でも、StartOutboundVoiceContact API の呼び出しには ClientToken を指定します。

DynamoDB
  → 業務上の通知単位で重複を管理する

ClientToken
  → API の再試行による二重発信を防ぐ

DynamoDB への書き込みと StartOutboundVoiceContact API の呼び出しは、1つのトランザクションとして実行できません。そのため、DynamoDB を利用する場合も、API を安全に再試行できるようにしておく必要があります。

複数システムから発信する場合

複数のシステムが別々のルールで ClientToken を生成すると、業務上は同じ通知でも、Amazon Connect からは別の発信要求として扱われる可能性があります。

複数システムをまたいで重複を防ぎたい場合は、次のような対応を検討します。

  • システム間で共通の通知 ID を使用する
  • ClientToken の生成ルールを共通化する
  • 発信要求を1つのサービスに集約する
  • DynamoDB などの共有ストアで重複を管理する

発信履歴や再架電状態を管理する場合

ClientToken は、発信履歴や再架電状態を保存するための仕組みではありません。

次のような情報を管理したい場合は、DynamoDB などに業務データとして保存します。

  • 通知 ID
  • 受信者 ID
  • ClientToken
  • ContactId
  • 発信日時
  • 発信状態
  • 再架電回数
  • エラー内容
ClientToken
  → API 再試行時の二重発信防止

DynamoDB
  → 発信履歴、監査、再架電状態などの管理

また、Lambda 内でメール送信や他の API 呼び出しも行う場合、ClientToken によって冪等になるのは StartOutboundVoiceContact の呼び出しだけです。Lambda の処理全体については、別途冪等性を検討する必要があります。

まとめ

SQS、SNS、EventBridge などから Lambda を起動する構成では、同じメッセージやイベントが複数回処理される可能性があります。

Amazon Connect の StartOutboundVoiceContact API では、同じ論理リクエストに同じ ClientToken を指定することで、API の再試行による二重発信を防ぎやすくなります。

同じ論理リクエストの再試行
  → 同じ ClientToken

別の論理リクエストや意図的な再架電
  → 別の ClientToken

同じ論理リクエストの再処理が7日以内に行われ、再処理時にも同じ ClientToken を指定できるのであれば、二重発信防止だけを目的として DynamoDB に処理済みフラグを保存する必要は基本的にありません。

一方、次のような要件には DynamoDB などの外部ストアを利用します。

  • 7日を超える重複を防ぐ
  • 複数システムからの発信要求を一元管理する
  • 発信履歴や再架電状態を管理する
  • 電話発信以外の処理も含めて重複を制御する

ClientToken と DynamoDB は、次のように役割を分けて考えます。

ClientToken
  → StartOutboundVoiceContact API の再試行による二重発信を防ぐ

DynamoDB
  → 業務上の重複、長期間の重複、履歴や状態を管理する

まずは API が提供する冪等性の仕組みを利用し、それだけでは扱えない期間や範囲に対して、DynamoDB などの外部ストアを組み合わせるのがよさそうです。

参考資料

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事