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.