EventBridge deduplication strategy for Genesys Cloud routing events

Is there a clean way to implement idempotency when consuming Genesys Cloud events via EventBridge?

I am seeing duplicate routing:queueConversation events hitting my consumer Lambda. The duplicates are not identical; they have different eventId values but represent the same logical state change (e.g., a conversation moving from waiting to accepted within a 500ms window). Genesys Cloud’s documentation mentions eventual consistency, but it does not provide a clear field for deduplication in the EventBridge payload.

Currently, my consumer writes to DynamoDB using the conversationId as the primary key. I am using a conditional write expression to prevent overwrites:

dynamodb.update_item(
 Key={'conversationId': event['conversationId']},
 UpdateExpression='SET #status = :status, #updated_at = :updated_at',
 ExpressionAttributeNames={'#status': 'status', '#updated_at': 'updated_at'},
 ExpressionAttributeValues={':status': event['status'], ':updated_at': event['timestamp']},
 ConditionExpression='attribute_not_exists(#updated_at) OR #updated_at < :updated_at'
)

This works for most cases, but when the duplicate event arrives with the exact same timestamp (down to the millisecond, which happens occasionally with high-volume routing changes), the condition fails or the update is skipped incorrectly. I am trying to avoid complex windowing logic in my Lambda.

ConditionalCheckFailedException: The conditional request failed

Is there a recommended pattern for handling this? Should I be relying on the eventId from the Genesys Cloud webhook header (which is lost in the EventBridge translation layer) or is there a unique identifier in the EventBridge record I should be using instead? I have checked the detail object, but nothing stands out as a unique transaction ID for the event itself.

1 Like

The problem here is relying on eventId for deduplication. Use conversationId and timestamp instead.

  1. Extract routing:conversationId from the event payload.
  2. Store a hash of conversationId + stateChange in DynamoDB with a short TTL.
  3. Check existence before processing. Ignore if present.

This handles logical duplicates regardless of eventId variance.

1 Like

Check your partition key strategy. Using conversationId alone is fine for low volume, but high-volume queues will cause hot partitions in DynamoDB. Hash the conversationId with a random salt or use a composite key including the agent ID to distribute writes.

This seems like a classic eventual consistency trap. The suggestion above about DynamoDB hashing is solid for scale. I verify this in my Newman runs by checking for duplicate conversationId in the event logs. See the deduplication guide here: https://support.genesys.com/s/article/EventBridge-Deduplication.

1 Like

This is a standard eventual consistency issue.

  • Use Redis for deduplication instead of DynamoDB to avoid hot partitions.
  • Store a hash of conversationId + state with a 500ms TTL.
  • Check existence before processing.