What’s the best way to migrate Cognito users to a new user pool?

Yan Cui

I help clients go faster for less using serverless technologies.

I shared on Linkedin [1] the other day that you should avoid using Cognito subs as the user ID for your system. One of the reasons is that a user’s sub does not carry over when you need to do a Cognito User Pool migration.

Someone responded by asking “Is this type of Cognito User Pool migration really that common that it necessitates consideration?

It’s a great question, so let’s dive into it.

  1. When should you consider a Cognito User Pool migration?
  2. How best to do this migration?

When to consider Cognito User Pool migration

Migrating users from one Cognito User Pool to another can be highly disruptive. But sometimes it’s our last resort.

Here are some common reasons why you have to consider it:

Changing user pool settings

Many user pool settings cannot be changed after it’s created. Most notably, immutable attributes cannot be changed to mutable later. For example, if you mark the email attribute as immutable but change your mind later.

This is by far the most common reason for migration between Cognito User Pools.

Reorganization of environments/apps

Another reason is when you need to reorganize your application(s) and AWS environments. Maybe you want to consolidate multiple user pools into one. Or maybe you want to move your production users to a new production account.

This might be to meet regulatory requirements.

For example, you may need to limit the no. of people who have access to production user data. But if you had one AWS account for all environments then it’s difficult to meet that access control requirement. So to stay compliant, you have to move the production user data into its own account and restrict access to it.

Data sovereignty requirements

You may need to move some users to a different region to comply with data protection regulations. This means moving some users from one user pool to another.

The BEST way to migrate to a new user pool

The challenge with a Cognito User Pool migration is that the user password cannot be extracted from Cognito.

This is a good thing. It shows that Cognito follows security best practices and does not store user passwords in plain text.

But it makes our lives more difficult during a Cognito User Pool migration.

Broadly speaking, here are three ways to approach this migration:

Option 1. Add existing users to the new user pool and set a temporary password. Email the users with their temporary password and ask them to log in and change the password.

Option 2. Use the migrate user Lambda trigger [2] (on the new user pool) to migrate users from the old user pool when the user next signs in. This trigger fires whenever a user is not found at the time of sign-in or in the forgot password flow. See the official guide [3] on how to use this trigger to import users into Cognito.

Both of these options suck…

Option 1 puts the burden of the migration on the users. Some users will churn, and it’s not a rabbit that you can pull out of the hat too many times.

Option 2 has a loooong tail. You have to keep the Lambda trigger until the last user has been migrated. Chances are some users have churned and will never come back and sign in.

In practice, most people use a combination of these two options:

  • Use the migrate user Lambda trigger to migrate active users. Leave the trigger running for, say, 6 months.
  • After 6 months, disable the trigger and apply option 1) on all remaining users. Those who have not churned will log back in and set a new password.

And that leaves us with my favourite.

Option 3. Go passwordless.

If passwords make Cognito User Pool migration difficult, then ditch them! Use this opportunity and modernize your app with passwordless authentication.

Cognito doesn’t support passwordless authentication out-of-the-box. But you can implement these custom flows with Lambda triggers.

I shared two ways to implement passwordless authentication with Cognito:

Besides these, you should also consider social sign-in with Google, LinkedIn, X/Twitter and so on.


Migrating users to a new Cognito user pool is perhaps more nuanced than you might think. There are technical limitations to consider. And you have to worry about the impact on your user experience.

It’s something that I try to avoid if I can. But if I must, I prefer to turn my misfortunes into an opportunity and improve my sign-in experience with passwordless authentication.

Do you agree?


[1] Why you should stop using Cognito subs as user ID

[2] Migrate user Lambda trigger

[3] Importing users into user pool with a user migration Lambda trigger

[4] Passwordless authentication with Cognito: one-time passcodes

[5] Passwordless authentication with Cognito: magic email links

Related posts

How to perform database migration for a live service with no downtime

Whenever you’re ready, here are 4 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
  2. Do you want to know how to test serverless architectures with a fast dev & test loop? Check out my latest course, Testing Serverless Architectures and learn the smart way to test serverless.
  3. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
  4. Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.