Blog

AWS Cognito User Data Replication Across Regions: Step-by-Step Guide

ByAkshay Mewara
June 19th . 6 min read
AWS Cognito User Data Replication Across Regions: Step-by-Step Guide

Introduction

AWS Cognito is a powerful tool for managing users on your website or mobile application. It handles user registration, sends confirmation codes, and assigns users to groups with distinct permissions.

However, a challenge arises when you need to synchronize users across multiple AWS Regions, such as from a Production environment to a Disaster Recovery (DR) environment. This synchronization is crucial because if one AWS Region becomes unavailable, users can still sign in through the DR Region without disruption, ensuring a seamless service experience.

Solution Overview

To address this challenge, we can use AWS services like AWS DynamoDB and AWS Lambda to replicate user data from one region to another. This setup ensures that any new user created in the production environment is also created in the disaster recovery environment, allowing for uninterrupted service.

Here’s a detailed step-by-step guide to setting up this solution:

Architecture Diagram

CognitoArchitecture.jpg

Step 1: Create a Lambda Function in Production Region (Region 1)

First, create a AWS Lambda function in the production region (Region 1). This function will be triggered whenever a new user is created in the AWS Cognito user pool of the production region (using the post-confirmation trigger).

The function’s code will extract the user’s email address and other relevant attributes, and then insert this data into a DynamoDB global table. This step ensures that the user data is captured and prepared for replication. Ensure the Lambda function’s role has appropriate permissions to access the DynamoDB table.

Steps:

  • Go to the AWS Lambda console.
  • Click on "Create function."
  • Choose "Author from scratch."
  • Name your function and select the runtime (e.g., Python 3.10).
  • Set up the Lambda execution role with the necessary permissions for DynamoDB.
  • Add the post-confirmation trigger for your AWS Cognito user pool.
  • Write the code to extract user attributes and insert them into DynamoDB.

Here’s the example code (python):

import boto3
 
def lambda_handler(event, context):
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('UserTable')
    
    user_data = {
        'email': event['request']['userAttributes']['email'],
        'sub': event['userName']
    }
    
    table.put_item(Item=user_data)
    
    return event

Step 2: Create a Global Table (DynamoDB) with Replica in Disaster Region (Region 2)

Next, create a DynamoDB global table in the production region. A global table allows for automatic replication of data across multiple AWS Regions. Add a replica of this table in the disaster region (Region 2).

This setup ensures that any data inserted into the DynamoDB global table in the production region is automatically replicated to the disaster region.

Steps:

  • Go to the AWS DynamoDB console.
  • Click on "Create table."
  • Define the table name and primary key (e.g., email).
  • After creating the table, click on "Global tables" Tab and click on "Create replica".
  • Add the disaster region (Region 2) to the table.

Step 3: Create a Lambda Function in Disaster Region (Region 2)

In the disaster region (Region 2), create another AWS Lambda function. This function will be responsible for creating users in the AWS Cognito user pool of the disaster region using the replicated data.

The function will handle the user creation process and ensure that the user attributes are correctly mapped and synchronized. Ensure the Lambda function’s role has appropriate permissions.

Steps:

  • Go to the AWS Lambda console in Region 2.
  • Click on "Create function."
  • Choose "Author from scratch."
  • Name your function and select the runtime (e.g., Python 3.10).
  • Set up the Lambda execution role with necessary permissions for Cognito and DynamoDB.
  • Write the code to create users in the Cognito user pool using the data from DynamoDB global table.

Here’s the example code (python):

import boto3
 
def lambda_handler(event, context):
    cognito = boto3.client('cognito-idp')
    user_pool_id = 'your_user_pool_id'
    
    for record in event['Records']:
        if record['eventName'] == 'INSERT':
            new_image = record['dynamodb']['NewImage']
            email = new_image['email']['S']
            sub = new_image['sub']['S']
            
            cognito.admin_create_user(
                UserPoolId=user_pool_id,
                Username=sub,
                UserAttributes=[
                    {'Name': 'email', 'Value': email},
                    {'Name': 'email_verified', 'Value': 'true'}
                ]
            )
            
    return 'User created'

Step 4: Add a DynamoDB Stream Trigger in Disaster Region (Region 2)

Enable DynamoDB Streams on the global table and add a trigger for the AWS Lambda function created in the disaster region.

This trigger will activate the Lambda function whenever a change is made to the DynamoDB global table in the disaster region. The Lambda function will then use the stream data (which includes the new user’s attributes) to create the user in the AWS Cognito user pool of the disaster region.

Steps:

  • Go to the DynamoDB console.
  • Select the DynamoDB global table.
  • Click on "Exports and streams" Tab and Enable DynamoDB Streams if not already enabled (enabled by default for global tables).
  • Click on create trigger.
  • Select the function created in Step 3.

Dynamo.jpg

Putting It All Together

When a new user is created in the AWS Cognito user pool of the production region, a post-confirmation Lambda function is triggered. This function inserts the user’s email address and other attributes into the DynamoDB global table.

The global table, with its replica in the disaster region, automatically replicates this data. The stream trigger on the DynamoDB global table in the disaster region activates the corresponding Lambda function, which processes the new data and creates a user in the AWS Cognito user pool of the disaster region. This seamless flow ensures that user data is consistently and reliably replicated across regions.

Enabling Time To Live (TTL) for Global Table

To optimize storage and ensure efficient data management, enable Time To Live (TTL) on the global DynamoDB table. Specify an attribute for TTL that will automatically delete data after a certain period. This prevents unnecessary data accumulation and helps reduce storage costs.

Steps:

  • Go to the DynamoDB console.
  • Select the global table.
  • Go to the "Additional settings" tab.
  • Enable TTL and specify the attribute name (e.g., expiryDate).

Benefits of the Proposed Solution

  • Serverless Architecture: This solution does not require EC2 instances, leveraging AWS Lambda for all computational needs, which significantly reduces infrastructure management overhead.
  • Cost Efficiency: AWS Lambda functions are triggered only when a user is created in the production region, minimizing computational costs.
  • Optimized Storage: Enabling TTL on the DynamoDB table helps manage the data lifecycle and reduces storage costs by automatically deleting unused data.
  • High Availability: Ensures that user authentication remains uninterrupted even if the production region becomes unavailable, by seamlessly switching to the disaster recovery region.

Conclusion

By implementing this solution, you can achieve efficient and reliable user data replication across multiple AWS Regions, ensuring high availability and continuity of service for your application users.

This setup leverages AWS’s serverless and scalable services, offering a robust method to synchronize user data and maintain service availability across regions. The combination of AWS Lambda and AWS DynamoDB global tables provides a cost-effective and automated approach to handle user data replication, ensuring your application remains resilient in the face of regional outages.

Share:
0
+0