AWS Amplify Gen 2 Migration: What’s Supported in 2026

Glowing server racks in a modern data center

If you’ve been running an AWS Amplify Gen 1 backend and watching Gen 2 mature from the sidelines, 2026 is the year the wait finally pays off. For a long time the honest answer to “how do I move my app over?” was “you don’t, not really.” That’s changed. There’s now an official Amplify Gen 2 migration tool, it ships inside the Gen 1 CLI, and AWS has published a feature-by-feature matrix telling you exactly what it can and can’t carry across. This guide walks through what’s supported in 2026, how the migration actually works under the hood, and the gotchas that will bite you if you treat it like a one-click upgrade. If you’ve already been studying AWS to level up, our notes on how I passed the AWS AI Practitioner exam share the same “learn the service, then prove it works” mindset that this migration rewards.

One important caveat up front: the tool is in Developer Preview. It operates on production resources, asks for interactive confirmation at every step, and is explicitly not built for unattended runs. So this is a “pilot it carefully,” not a “migrate Friday afternoon” situation.

People with enhanced technology icons illustration

Key takeaways

  • The backend migration tool is in Developer Preview and ships in @aws-amplify/cli@^14.4.0 as the amplify gen2-migration subcommand.
  • It uses a blue/green model: stateless resources get fresh Gen 2 copies, stateful ones (Cognito, S3) are moved via CloudFormation Stack Refactor, and DynamoDB tables are shared so you don’t lose data.
  • Auth, GraphQL data models, REST APIs, S3 storage, and Node.js functions are well covered; DataStore, manyToMany, @searchable, and non-Node Lambdas have no automated path.
  • The old Gen 2 FAQ still tells you to “remain on Gen 1” — that’s stale. The current migration guide and feature matrix are the real sources of truth.

Gen 1 vs Gen 2: two different mental models

Before you plan an Amplify Gen 2 migration, it helps to understand that Gen 1 and Gen 2 aren’t the same product with a new coat of paint. They’re built on opposite philosophies, and almost every migration decision flows from that gap.

Gen 1 is a CLI-wizard experience. You answer prompts, the CLI writes JSON and GraphQL into an amplify/ folder, and that gets compiled down to CloudFormation. You install the CLI globally, spin up parallel copies of your stack with amplify env, mock services locally with amplify mock, and reach for amplify override when you need to tweak something the wizard didn’t expose. Config lands in aws-exports.js or amplifyconfiguration.json.

Gen 2 throws the wizard out and replaces it with TypeScript on top of the AWS CDK. You declare your backend in code — defineAuth, defineData, defineStorage, defineFunction — and the framework figures out the infrastructure. The CLI is a local dev dependency (@aws-amplify/backend-cli) you run through npx ampx. Environments aren’t a separate command anymore; each Git branch is its own environment, with one CloudFormation stack per branch. There’s no local mock — npx ampx sandbox provisions real, per-developer cloud resources instead. Config comes out as amplify_outputs.json, and your escape hatch is just native CDK dropped straight into amplify/backend.ts.

ConcernGen 1Gen 2
AuthoringCLI wizard + JSON/GraphQLCode-first TypeScript on AWS CDK
CLIGlobal @aws-amplify/cliLocal dev-dep, run via npx ampx
Environmentsamplify envGit branches (one stack per branch)
Local devamplify mock (local)npx ampx sandbox (real cloud)
Config outputaws-exports.js / amplifyconfiguration.jsonamplify_outputs.json
Escape hatchamplify overrideNative CDK in backend.ts

The practical upshot: migrating isn’t a data export/import. It’s a translation from a declarative wizard format into hand-shaped (and tool-generated) TypeScript, while keeping your live backend serving traffic the whole time.

The Amplify Gen 2 migration support matrix

AWS publishes a feature parity matrix that grades every capability on two axes at once: can Gen 2 do this at all, and does the migration tool automate it? Read the legend carefully, because “the tool skips it” doesn’t always mean “Gen 2 can’t do it.”

  • 🟢 Fully supported — the tool generates the Gen 2 code and refactors the existing resource.
  • 🟠 Generate only — the tool writes the Gen 2 code, but you move the data over by hand.
  • 🔴 Unsupported — the tool skips it. You hand-write the Gen 2 definition and migrate any data yourself.

Auth and data

FeatureStatusNotes
Auth core (Cognito email/phone/username, social Google/FB/Amazon/Apple, groups, MFA, most triggers, import auth)🟢The bulk of real-world auth setups carry across cleanly.
Auth advanced (admin queries, read/write attribute capability, OAuth scopes/redirect/domain prefix, override auth, verification-link redirect)🔴Gen 2 can do these — the tool just won’t. Wire them in CDK afterward.
GraphQL models (@model, primary/secondary keys, hasOne/hasMany/belongsTo, all @auth rules, custom queries/mutations/subscriptions, function/HTTP/VTL resolvers)🟢Schema is preserved as string-based GraphQL, not rewritten into the a.model() builder.
Data manyToMany🔴No path — Gen 2 lacks it. Remodel as an explicit join model.
Data @searchable (OpenSearch)🔴Re-implement with Zero-ETL DynamoDB→OpenSearch and reindex manually.
Data @predictions🔴Rebuild against the underlying AI services directly.

APIs, sync, storage, and functions

FeatureStatusNotes
GraphQL / AppSync auth (API key, Cognito, IAM)🟢OIDC and Lambda authorizer modes are 🔴 in the tool.
DataStore / conflict resolution (offline sync)🔴No path. You must disable conflict resolution before migrating; Gen 2 has no DataStore replacement (only “planned”).
REST API (API Gateway)🟢Tool generates the full CDK construct; repoint apiName in the frontend.
Storage S3 (bucket, auth/guest CRUD, group access, Lambda triggers)🟢Import bucket and override storage are 🔴 (do them manually).
Functions — Node.js🟢Gen 2 defaults to a TypeScript runtime.
Functions — Python / Go / Java / .NET / plain JS🔴Redefine as a CDK custom function. They’re stateless, so there’s no data to move.
Function secrets, Lambda layers, custom IAM policies🔴Reattach by hand.

Hosting, geo, analytics, AI, and custom resources

FeatureStatusNotes
Hosting — Amplify Console Git-based CD🟢Tool emits amplify.yml; you connect the branch.
Hosting — manual deploy / Amplify-managed S3+CloudFront / amplify publish🔴Removed in Gen 2. Manual-deploy apps must create a brand-new Amplify app, forfeiting reuse of the existing custom domain.
Geo — Map, PlaceIndex🟢Carried across.
Geo — GeofenceCollection🟠Code generated; move geofence data manually.
Analytics — Kinesis🟢Repoint streamName.
Analytics — Pinpoint🔴No automated path.
Predictions (Rekognition/Translate/etc.), Interactions (Lex), in-app messaging / push (Pinpoint)🔴Rebuild on the underlying services. (Client-side PubSub over IoT/MQTT has no backend resource, so it’s not applicable.)
Custom resources — CDK🟢Drop straight into backend.ts.
Custom resources — raw CloudFormation🔴Wrap with CfnInclude manually.

The headline reading: if your app is the common Amplify shape — Cognito auth, a GraphQL data layer, S3 storage, a few Node.js functions, and Amplify Console hosting — you’re in good shape. If you lean on DataStore offline sync, manyToMany, OpenSearch, or polyglot Lambdas, budget real engineering time, because those are manual.

How the Amplify Gen 2 migration actually works

The tool runs a partial blue/green migration through an amplify gen2-migration subcommand baked into Gen 1 CLI v14.4.0 and up. The whole design is built so your existing frontends keep working while the new stack stands up beside the old one. It splits your resources into three buckets:

  • Stateless resources (AppSync API, API Gateway, Lambda, IAM roles) get fresh copies in Gen 2. The Gen 1 originals stay live, so nothing breaks for users still hitting the old endpoints.
  • Stateful resources (Cognito User Pool, Identity Pool, S3 bucket) are moved into the Gen 2 stacks via CloudFormation Stack Refactor — a metadata-only move that preserves the data.
  • DynamoDB model tables are shared between Gen 1 and Gen 2 from the moment you deploy. They don’t get refactored; Gen 2 just reads your Gen 1 data immediately.
npm install -g @aws-amplify/cli@^14.4.0
amplify pull --appId <app-id> --envName main

amplify status   # should report no changes
git diff         # should show no changes

amplify gen2-migration assess     # read-only report
amplify gen2-migration lock       # deny-all stack policy + Retain on stateful
amplify gen2-migration generate   # writes Gen 2 TypeScript into amplify/

The documented flow is nine steps, and the order matters. You assess (a read-only report of what’s covered), lock the stack (deny-all stack policy plus Retain on stateful resources so nothing can be accidentally deleted), then generate the Gen 2 TypeScript into amplify/. After that comes a round of manual edits, a deploy, and then the step you cannot skip: functional testing of the new Gen 2 backend. Only once it passes do you run refactor --to <gen2-root-stack>, which moves the stateful resources across. From that point Gen 1 becomes non-updatable, so this is effectively the point of no return. Finally you uncomment postRefactor() in backend.ts and deploy one more time.

Developer editing TypeScript code on a laptop, refining a generated Amplify Gen 2 backend
The tool generates the scaffolding; the post-generate edits are hands-on TypeScript work.

A lot of that “manual edits” phase is mechanical translation rather than creative design: flipping CommonJS exports.handler over to ESM export async function handler, swapping config references from aws-exports.js to amplify_outputs.json, and fixing up auth directives that didn’t survive generation. That kind of repetitive, pattern-following refactor is exactly what AI coding assistants are good at — if you’re choosing one for the job, our breakdown of Cursor vs Copilot vs Claude Code in 2026 compares the agentic editors that handle this sort of multi-file rewrite well. Just keep a human reviewing every diff, because auth rules are the one area where a wrong edit quietly opens or closes access.

One hard rule worth repeating: always run the whole thing on a Step-0 clone first, and when you eventually decommission Gen 1, do it through amplify gen2-migration retain plus a manual stack deletion — never amplify env remove, which would try to tear down resources Gen 2 now depends on.

Gotchas: when not to migrate yet

The matrix tells you what’s supported; these are the sharp edges the matrix doesn’t shout about. Read them before you commit a production app.

  • It’s Developer Preview. Pilot it on a clone and validate hard before pointing it at anything mission-critical.
  • DataStore / offline conflict resolution has no path. You must disable conflict resolution before migrating, and Gen 2 still has no DataStore replacement.
  • The default @model auth flips. An unprotected Gen 1 @model is effectively public via @aws_api_key; in Gen 2 the default becomes private @aws_iam. Add an explicit @auth(rules: [{allow: public}]) if you need the old behavior — otherwise data silently stops being readable.
  • IAM-auth GraphQL trap. After the refactor, the Identity Pool’s AuthRole repoints to Gen 2, so Gen 1 loses IAM access to its own API. Pre-add a custom-roles.json with {"adminRoleNames": ["amplify-${appId}"]} to avoid locking yourself out.
  • Non-Node Lambdas mean rewrites. Python, Go, Java, and .NET functions become hand-written CDK, and even your JS functions may need the CommonJS→ESM conversion mentioned above.
  • Circular CloudFormation dependencies can surface during generation and need untangling by hand.

Don’t overlook the prerequisites, either, because they fail loudly at the worst moment. The managed AdministratorAccess-Amplify policy is not enough — you also need cloudformation:CreateStackRefactor, DescribeStackRefactor, ExecuteStackRefactor, plus Get/SetStackPolicy. Your account/region must be CDK-bootstrapped, you need Node ≥20, TypeScript ^5, and aws-amplify ^6.16.2, and you should have deployed the Gen 1 app with CLI v14 first. Finally, set expectations with your team: Gen 2 has no Console/Studio visual config and no UI Builder — the Figma plugin is the closest substitute for the old drag-and-drop workflow.

FAQ

Should I migrate from Gen 1 to Gen 2 right now?

Pilot it, don’t commit it. The tool is in Developer Preview, so the sensible play is to clone a Gen 1 environment, run the full nine-step flow against the clone, and learn where your app falls outside the support matrix. Hold the production cutover until the tooling reaches GA unless you have a strong, time-sensitive reason to move sooner.

Is DataStore supported in Gen 2?

No. There’s no migration path for DataStore or offline conflict resolution, and Gen 2 has no DataStore replacement yet — it’s only “planned.” You have to disable conflict resolution before migrating. If your app’s core value is offline-first sync, this is the single biggest reason to wait.

Will I lose my data — DynamoDB records or Cognito users?

No, not if you follow the flow. DynamoDB model tables are shared between Gen 1 and Gen 2, so Gen 2 reads your existing records immediately. Cognito User Pools, Identity Pools, and S3 buckets are moved with a CloudFormation Stack Refactor, which is a metadata-only operation that preserves the underlying data. The lock step also applies a Retain policy as a safety net.

Can Gen 1 and Gen 2 run at the same time?

Yes — that’s the whole point of the blue/green model. Stateless resources get fresh Gen 2 copies while the Gen 1 originals keep serving traffic, and DynamoDB tables are shared across both. Your existing clients keep working through the transition, and you only decommission Gen 1 deliberately via amplify gen2-migration retain followed by a manual stack deletion.

Which Lambda runtimes migrate automatically?

Only Node.js. Gen 2 defaults to a TypeScript runtime, so Node functions carry across as 🟢. Python, Go, Java, and .NET functions are 🔴 — you redefine them as CDK custom functions. Since functions are stateless, there’s no data to move, but you’ll reattach secrets, layers, and custom IAM policies by hand.

The bottom line on Amplify Gen 2 migration in 2026

For the first time, moving an Amplify app from Gen 1 to Gen 2 is a documented, supported process rather than a hand-rolled rewrite. The blue/green design is genuinely thoughtful — your data stays put, your live app keeps serving, and the tool generates a real TypeScript starting point. But “supported” still means Developer Preview, and the gaps (DataStore, manyToMany, polyglot Lambdas, the auth-default flip) are exactly the things that quietly break apps if you skip the assessment.

One more thing to watch: the older Gen 2 FAQ still says migration tooling is under development and tells you to “remain on Gen 1.” That guidance is stale — it predates this release. Treat the migration guide and the feature matrix as your sources of truth, and check the Developer Preview announcement for the latest status. So: clone first, run the assessment, fix the diffs with care, test before you refactor, and you’ll be ready the moment this graduates to GA. If you’re sharpening your AWS skills alongside this, our write-up on passing the AWS AI Practitioner exam is a good companion read for the same developer audience.

You Missed