vercel → aws · 2026 next.js migration playbook

Vercel to AWS — the target architecture, the Next.js gotchas, and who runs it for you.

Vercel is the fastest place to ship a Next.js app and, past a certain traffic level, one of the most expensive places to run it. This is the senior-engineer playbook for moving off Vercel onto AWS: the four realistic targets (Amplify Hosting, SST/OpenNext on Lambda + CloudFront, ECS/Fargate, or pure S3 + CloudFront for static), how every Vercel primitive maps — serverless and edge functions, ISR, image optimization, middleware, preview deploys — the real cost-at-scale math, the Next.js-on-AWS quirks that actually bite, and the cutover. A MAP-funded AWS partner can run the whole thing — often at little-to-no cost to you.

typical cost cut
50–80%
cutover downtime
0–5 min
project length
2–6 weeks
cost to you (MAP)
$0–low
TL;DR
  • Teams leave Vercel for one dominant reason — cost at scale. Vercel's convenience layer (bandwidth billed well above raw CDN egress, per-million function invocations, separately-metered edge middleware and ISR writes, per-1,000 image-optimization counts) compounds fast: a high-traffic Next.js app on a Pro/Enterprise plan that runs a few hundred dollars a month commonly lands 50–80% lower on AWS once you own the CloudFront + Lambda + S3 stack directly.
  • There is no single "AWS Vercel," there are four sensible targets. AWS Amplify Hosting is the closest managed Next.js experience (SSR/ISR support, git-push deploys, preview branches). SST / OpenNext compiles your Next.js app onto Lambda + CloudFront + S3 — the most faithful self-owned Vercel replacement. ECS/Fargate runs Next.js in standalone/Node server mode behind an ALB for teams that want a long-running container. Pure S3 + CloudFront is the cheapest path for fully static (output: export) sites.
  • The hard parts are Next.js-specific, not infrastructure: ISR/on-demand revalidation, edge middleware, the Image Optimization API, and preview deploys all map to AWS primitives but need deliberate wiring (OpenNext or Amplify does most of it). CloudRoute routes you to a vetted AWS partner who runs it end-to-end — and when the workload qualifies for the AWS Migration Acceleration Program (MAP), AWS funds the migration and the customer pays little-to-nothing.
the trigger

IWhy teams leave Vercel — the cost curve at scale

Nobody migrates off Vercel because the developer experience is bad — it's the best in the category. They migrate because that experience is priced as a multiplier on every unit of traffic, and once the app is successful, the multiplier becomes the line item finance asks about.

The dominant reason is cost at scale, and it's structural rather than a billing accident. Vercel resells AWS (and other) infrastructure with a convenience margin, and it meters the things a busy app does most. Bandwidth is billed well above raw CDN egress — past the plan allowance you pay per-GB at a rate that is a multiple of what CloudFront egress costs at the same volume. Serverless and edge function execution is billed per invocation plus duration, so a high-traffic SSR app generates millions of billable invocations a month. ISR (Incremental Static Regeneration) writes, edge-middleware invocations, and the Image Optimization API are each separately metered. None of these are unreasonable individually; together, at scale, they compound into a bill that grows faster than your traffic.

The second reason is control and lock-in. Vercel abstracts the CDN, the function runtime, the build pipeline, and the edge network into a single opinionated product. That is exactly what you want at v1 and exactly what chafes once you need a VPC-private connection to your database, a custom WAF rule set, a specific caching policy, multi-account isolation for compliance, or co-location with the rest of your AWS estate (queues, RDS, S3, Bedrock). On Vercel those needs route through Vercel's primitives and pricing; on AWS you own them directly.

The third reason is consolidation. Most teams that outgrow Vercel already run the rest of their backend on AWS — the database is on RDS or Aurora, the queue is SQS, object storage is S3, auth touches Cognito, and increasingly the AI features run on Bedrock. Keeping the Next.js front end on Vercel means a second vendor, a second bill, cross-cloud egress between your front end and your AWS data, and a second security/compliance surface. Pulling the front end onto AWS removes the egress, unifies the bill, and puts the whole app inside one account boundary.

The honest counterpoint: Vercel's DX, preview deploys, and zero-config Next.js support are genuinely excellent, and AWS asks you to own more — a build pipeline, a CDN distribution, function packaging, and the Next.js-on-Lambda adapter layer. That operational surface is precisely why most teams don't run this migration alone — and the CloudRoute angle is that a vetted AWS partner runs it for you, with AWS often funding the work.

the cost math

A successful Next.js app serving real traffic commonly runs $350–$2,000+/month on Vercel Pro/Enterprise once bandwidth, function invocations, ISR, and image optimization stack up — and it scales roughly linearly with traffic. The same app on AWS — CloudFront + Lambda (via OpenNext) or Fargate + S3, with the image API on Lambda and a CloudFront cache policy — commonly lands at $80–$500/month at the same traffic, because you pay AWS list/committed price for egress and compute instead of a platform multiplier. That recovered margin is what pays for the migration (and with MAP, AWS pays for it instead).

four targets

IIThe four realistic targets on AWS — and which one fits

The single most common mistake is assuming Vercel→AWS means one specific architecture. It doesn't. There are four sensible targets, and the right one depends on whether you're running a full Next.js app (SSR/ISR/middleware) or a static export, and how much operational control you want versus how close to the Vercel experience you want to stay.

Picking the wrong target is what turns a two-week migration into a two-month one. The CloudRoute routing logic for a Vercel inquiry is essentially this triage: is the app fully static or dynamic, does it lean on ISR / edge middleware / the image API, and does the team want a managed Vercel-like product or a self-owned serverless stack?

Target A — AWS Amplify Hosting (the closest managed experience)

What it is: AWS's managed web-hosting product with first-class Next.js support — server-side rendering, ISR/SSG, API routes, image optimization, git-based deploys, and preview branches. It is the closest thing AWS offers to the Vercel experience: connect the repo, Amplify builds and deploys, and it provisions the CloudFront + Lambda + S3 behind the scenes for you.

Best for: teams that want to leave Vercel for the cost and consolidation but keep a managed, low-ops, git-push workflow — and don't need deep control over the underlying CloudFront/Lambda configuration.

The tradeoff: Amplify supports a defined set of Next.js versions and features; bleeding-edge App Router / streaming / advanced-middleware behavior can lag what Vercel ships day-one. Verify your exact Next.js version and feature set against Amplify's supported matrix in the Assess phase — this is the single most important compatibility check for this target.

Target B — SST / OpenNext on Lambda + CloudFront (the faithful self-owned stack)

What it is: OpenNext is an open-source adapter that compiles a Next.js build into the AWS primitives Vercel uses under the hood — the server runs on Lambda (or Lambda@Edge), static assets sit in S3, CloudFront is the CDN, ISR uses S3 + a revalidation queue (SQS) + DynamoDB for tag/revalidation tracking, and the Image Optimization API runs as its own Lambda. SST is the infrastructure framework that deploys this stack (and the surrounding resources) as code.

Best for: teams that want the full Vercel feature set — SSR, ISR/on-demand revalidation, edge middleware, image optimization — but self-owned in their own AWS account, with full control over caching, networking, and cost, and no platform margin.

The tradeoff: you (or the partner) own the OpenNext/SST configuration and its upgrade cadence as Next.js evolves. This is the most faithful Vercel replacement and the most common landing spot for "we love Next.js, we just can't afford Vercel at this traffic" — but it is real infrastructure-as-code, not a managed product.

Target C — ECS on Fargate (the long-running container)

What it is: run Next.js in output: 'standalone' (Node server) mode inside a container on ECS/Fargate behind an Application Load Balancer, with CloudFront in front for caching and static assets on S3. The app is one always-on Node server rather than per-request Lambdas.

Best for: teams that already run other services on ECS/Fargate (consolidation), want predictable always-on latency with no cold starts, need long-lived connections (WebSockets, SSE/streaming), or run a custom Node server alongside Next.js.

The tradeoff: you pay for the container 24/7 rather than per-request, so it is most cost-effective at steady, sustained traffic; ISR and on-demand revalidation work but you manage the shared cache (e.g. via a shared volume or a cache handler backed by S3/Redis) across tasks. It does not give you the per-request edge scaling Lambda does, which is fine for most apps.

Target D — S3 + CloudFront (pure static export)

What it is: if the app is fully static — next build && next export (output: 'export'), a marketing site, docs, or a SPA with a separate API — the entire thing is static files in an S3 bucket served by CloudFront, with ACM for TLS and Route 53 for DNS. No Lambda, no server.

Best for: static sites, documentation, landing pages, and SPAs where there is no server-side rendering. This is by far the cheapest target — pennies-to-single-dollars a month for most sites — and the lowest-ops.

The tradeoff: none if the app is genuinely static; but the moment you need SSR, ISR, API routes, or middleware, you're back to Target A or B. Many teams discover that what they think is "static" actually uses a couple of dynamic routes — flag that in Assess so you don't pick D and then have to re-platform.

the lookup

IIIHow each Vercel primitive maps to AWS (the principles behind the table)

The full row-by-row mapping — every Vercel feature, where it lands on AWS, and the effort — lives in the comparison table further down. Three principles make reading that table safe, because the Vercel→AWS mapping is less about servers and more about translating Vercel's edge-and-function model into CloudFront + Lambda primitives.

First, the static and CDN layer is the easy part. Vercel's global edge network is CloudFront; the static assets Vercel serves from its edge cache live in S3 fronted by CloudFront with an appropriate cache policy. Custom domains and automatic TLS become Route 53 + ACM (free certificates). For a static export, that is the entire migration — these are the "trivial/low" rows.

Second, the compute layer is the substantive part, and it maps cleanly once you choose a target. Vercel Serverless Functions and Next.js API routes / Route Handlers become Lambda functions (Amplify and OpenNext generate these for you; on Fargate they run inside the Node server). Vercel Edge Functions and Next.js Middleware become Lambda@Edge or CloudFront Functions — CloudFront Functions for lightweight header/redirect logic at the edge, Lambda@Edge for heavier middleware that needs a full runtime. This is where an adapter (OpenNext) or a managed product (Amplify) earns its place: it does this translation so you don't hand-wire every function.

Third, the stateful Next.js features are the ones that need deliberate design: ISR and on-demand revalidation need a cache store (OpenNext uses S3 + DynamoDB + an SQS revalidation queue; Amplify manages it; Fargate needs a shared cache handler) and the Image Optimization API needs its own Lambda (or a service like a CloudFront image handler). Environment variables and secrets move from Vercel's project settings into AWS Secrets Manager + SSM Parameter Store, injected at build and runtime. These are the "medium/high effort" rows — and exactly the work a migration partner does for you.

the hands-on part

IVServerless functions, edge middleware, and ISR on AWS

The substantive engineering in a Vercel→AWS move is reproducing Vercel's function-and-edge behavior on AWS primitives. It is well-trodden ground — OpenNext and Amplify exist precisely to do it — but it is where teams without serverless experience slow down, so here is exactly what each piece involves.

Serverless functions and API routes are the most direct mapping. A Vercel Serverless Function (or a Next.js API route / App Router Route Handler) becomes an AWS Lambda function fronted by CloudFront (and, in OpenNext, a single "server" Lambda handles SSR and route handlers). The runtime model is the same — request in, response out, scale to zero — so the main differences you tune are the memory/timeout settings, cold-start behavior (provisioned concurrency if a route is latency-critical), and packaging. On Amplify and OpenNext the function packaging is generated from your build; on Fargate the routes simply run inside the always-on Node server, sidestepping cold starts entirely.

Edge functions and middleware are the part that genuinely differs. Vercel runs middleware on its edge runtime at every matched request. On AWS you split this by weight: lightweight logic (auth-cookie checks, header rewrites, redirects, A/B bucketing) runs as a CloudFront Function — extremely fast, extremely cheap, runs at the edge, but a constrained JS runtime; heavier middleware that needs a full Node runtime (calling an API, complex rewrites) runs as Lambda@Edge. The nuance worth knowing up front: Lambda@Edge has its own limits (size, timeout, no VPC access at edge) and deploys globally, so it has a slightly longer deploy cycle. OpenNext maps Next.js Middleware onto this automatically; the design decision is just which logic belongs at the edge versus in the origin Lambda.

ISR and on-demand revalidation are the most Next.js-specific piece. On Vercel, ISR "just works." On AWS you need somewhere to store the regenerated pages and a mechanism to revalidate them. OpenNext implements this with S3 (the rendered page cache), DynamoDB (tag and revalidation tracking), and an SQS queue (to debounce and process background revalidation) — so revalidate intervals and revalidateTag()/revalidatePath() on-demand calls behave as they do on Vercel. Amplify manages this internally. On Fargate you configure a custom Next.js cache handler backed by a shared store (S3 or Redis/ElastiCache) so all tasks share one cache rather than each task regenerating independently. This is the row most likely to surprise a team doing it by hand — and the strongest argument for using OpenNext or Amplify rather than rolling it from scratch.

The Image Optimization API (next/image) becomes its own Lambda that resizes/optimizes on demand and caches the results in S3/CloudFront — OpenNext ships an image-optimization function; Amplify includes image handling; on Fargate it runs in-process or as a sidecar. It is metered per-image on Vercel and is frequently a meaningful chunk of the Vercel bill, so moving it to a cached Lambda is often where a surprising amount of the savings comes from.

the workflow

VPreview deploys, env vars, and the build pipeline

The piece teams worry about losing most is Vercel's git workflow — the preview deployment per pull request and the per-environment env vars. Both reproduce on AWS; the fidelity depends on which target you chose.

On Amplify Hosting this is nearly a like-for-like swap: Amplify connects to your Git provider, builds on every push, and provisions preview deployments per pull request with their own URLs — the same mental model as Vercel preview deploys. Per-branch and per-environment environment variables are managed in the Amplify console, mapped to your main/staging/preview branches. For teams whose attachment to Vercel is really an attachment to the preview-deploy workflow, Amplify is the path of least disruption.

On the self-owned targets (OpenNext/SST or Fargate), the build pipeline becomes AWS CodePipeline + CodeBuild, or — very commonly — you keep GitHub Actions (or GitLab CI) and have it run the SST/OpenNext deploy or build-and-push the container to ECR and update the service. Preview environments are reproduced by deploying a per-pull-request stage (SST makes ephemeral per-stage deploys straightforward) or a per-branch CloudFront distribution; it is more configuration than Amplify's built-in previews, but it is fully under your control and there is no per-seat or per-preview platform cost.

Environment variables and secrets move out of Vercel's project settings and split by sensitivity, exactly as in any AWS migration: real secrets (API keys, database credentials, signing secrets) into AWS Secrets Manager, non-sensitive config (public URLs, feature flags, the deployment environment) into SSM Parameter Store, injected at build time and runtime. The one Next.js subtlety to get right: NEXT_PUBLIC_* variables are inlined at build time, so they must be present in the build environment (CodeBuild/Amplify/Actions), while server-only secrets are resolved at runtime from Secrets Manager — a partner scripts the export-and-sort so nothing is missed or accidentally baked into a public bundle.

the short window

VIThe cutover: build, smoke-test, and a near-zero-downtime DNS flip

A Vercel→AWS cutover is one of the gentler ones in the migration cluster, because a front end is largely stateless — the database usually doesn't move (it's often already on RDS/Aurora or a managed provider). The whole new stack can be built, deployed, and tested in parallel without touching production, and the switch is a DNS change.

Because the app tier is stateless, the cutover technique is straightforward: stand up the full AWS target (Amplify app, or the OpenNext/SST stack, or the Fargate service + CloudFront), point it at the same backend/database, and deploy the app there behind a temporary hostname. Run the full test suite and a manual smoke test against that hostname — every route, SSR pages, ISR revalidation, middleware/auth behavior, image optimization, API routes, and the preview workflow. Nothing in production is affected yet because public traffic still goes to Vercel.

When the AWS stack is validated, the cutover is a DNS switch: lower the TTL on your domain a day ahead, then repoint the apex/CNAME from Vercel to the CloudFront distribution (or the Amplify domain). Because both serve the same backend and the front end holds no durable state, there is no data to migrate at the flip — user-visible downtime is effectively the DNS propagation window, commonly 0–5 minutes, and you can run both in parallel during propagation so requests resolve to whichever endpoint they hit. If your database is also moving (e.g. you're leaving a Vercel-integrated Postgres for RDS), that database cutover follows the standard DMS/continuous-replication pattern covered in the Heroku and database-migration guides, and it — not the front end — sets the downtime window.

The rollback is equally clean and is the reason this cutover is low-risk: keep the Vercel project live until you're confident, and if anything is wrong, repoint DNS back to Vercel. With a 60-second TTL the rollback is as fast as the cutover. Most teams keep Vercel running for a few days to a couple of weeks as a warm fallback, then cancel the plan — and that cancellation is the moment the 50–80% savings become real.

why this cutover is low-risk

A Next.js front end is stateless — the durable state lives in your database, which usually isn't moving. So the cutover is a DNS repoint between two stacks serving the same backend, not a data migration. That makes Vercel→AWS one of the safest moves in the cluster: near-zero downtime, instant DNS rollback, and no risk to your data. The work is in faithfully reproducing the Next.js behavior, not in the switch.

the runbook

VIIThe step-by-step migration (assess → build → cut over → optimize)

Here is the end-to-end sequence a partner runs, mapped to the AWS MAP phases (Assess → Mobilize → Migrate). For a typical Next.js app this is a 2–6 week project — most of it parallelizable, none of it touching production until the final DNS flip.

  • 1 — Assess (days 1–4) — Inventory the app: Next.js version, App vs Pages Router, which routes are SSR/SSG/ISR, edge middleware, image optimization usage, API routes, env vars, and the current Vercel bill broken down by bandwidth/functions/ISR/images. Choose the target (Amplify vs OpenNext/SST vs Fargate vs static) and model the before/after cost. Under MAP this Assess/TCO phase is typically free.
  • 2 — Build the landing zone — Stand up the AWS account structure, CloudFront, S3 buckets, IAM roles, ECR (if Fargate), and Secrets Manager / Parameter Store. (Reuses the AWS Landing Zone and AWS DevOps foundations in the DevOps cluster.)
  • 3 — Deploy the app to AWS — For Amplify: connect the repo and configure build settings. For OpenNext/SST: write the SST config and deploy the Lambda + CloudFront + S3 + DynamoDB + SQS stack. For Fargate: write the Dockerfile (output: standalone), push to ECR, deploy the ECS service behind an ALB + CloudFront.
  • 4 — Wire the Next.js specifics — Confirm SSR, ISR/on-demand revalidation, edge middleware (CloudFront Functions / Lambda@Edge), and the image optimization Lambda all behave as on Vercel. Migrate env vars into Secrets Manager / Parameter Store, getting NEXT_PUBLIC_* into the build environment.
  • 5 — Rebuild the pipeline + previews — Stand up CodePipeline/CodeBuild or keep GitHub Actions; reproduce preview deployments (Amplify previews, or per-PR SST stages / per-branch distributions).
  • 6 — Smoke-test against a temp hostname — Deploy behind a temporary domain and run the full test suite + manual smoke tests: every route, SSR/ISR behavior, middleware/auth, image optimization, API routes, and previews. Production still on Vercel — no public impact.
  • 7 — Cut over (DNS) — Lower TTL ahead of time, repoint the domain from Vercel to CloudFront/Amplify, run both in parallel during propagation, verify, and keep Vercel warm as rollback. Target window: 0–5 minutes of any visible disruption.
  • 8 — Optimize + decommission — Tune the CloudFront cache policy, set Lambda memory/provisioned concurrency where latency matters (or a Compute Savings Plan for Fargate), confirm CloudWatch alarms. Keep Vercel as rollback for a short window, then cancel the plan — that cancellation is when the savings become real.
what bites teams

VIIINext.js-on-AWS gotchas: the quirks that turn a clean migration messy

Most Vercel→AWS migrations that go sideways do so for a small, repeatable set of Next.js-specific reasons. None are dealbreakers; all are cheaper to know than to discover at cutover.

  • Next.js version vs Amplify support — If you picked Amplify, your exact Next.js version and feature set (App Router, streaming, advanced middleware) must be on Amplify's supported matrix — Vercel ships Next.js features day-one and other hosts can lag. Verify in Assess; if you're on the bleeding edge, OpenNext (which you control) is often the safer target.
  • ISR needs a real cache backend — ISR and revalidateTag()/revalidatePath() "just work" on Vercel; on AWS they need a cache store (OpenNext: S3 + DynamoDB + SQS; Fargate: a shared cache handler). Skip this and pages either never revalidate or each Lambda/task regenerates independently. This is the #1 surprise for hand-rolled migrations — use OpenNext or Amplify.
  • Edge middleware limits differ — Vercel's edge runtime is permissive; CloudFront Functions has a constrained JS runtime and Lambda@Edge has size/timeout limits and no VPC access at the edge. Heavy middleware may need to move to the origin Lambda instead of the edge. Audit what your middleware actually does before assuming it ports 1:1.
  • NEXT_PUBLIC_* are baked at build time — Public env vars are inlined into the client bundle at build, so they must exist in the build environment (CodeBuild/Amplify/Actions), not just at runtime. Server-only secrets resolve at runtime from Secrets Manager. Mixing these up either leaks a secret into the public bundle or ships an undefined public var.
  • Cold starts on latency-critical routes — Lambda (OpenNext) scales to zero, which means cold starts on infrequently-hit routes. For latency-critical paths, set provisioned concurrency — or choose Fargate, where the always-on Node server has no cold start. Don't discover this on a checkout page.
  • Streaming / WebSockets / long connections — Long-lived connections (SSE, WebSockets) and React streaming work best on a long-running server (Fargate) rather than per-request Lambda. If your app leans on streaming or realtime, factor that into the target choice rather than forcing it onto Lambda@Edge.
  • Forgetting to decommission Vercel — Savings aren't real until the Vercel plan is cancelled. Keep it warm as rollback for a defined short window — then actually turn it off. Paying both bills "just in case" for months erases a chunk of year-one savings.
feature-by-feature

Vercel feature → AWS approach (target + effort)

The definitive lookup: every Vercel primitive, how you reproduce it on AWS, which target handles it, and the engineering effort. "Trivial/Low" rows are config or generated for you; "Medium/High" rows are the real work — and the work a partner does for you. (Amplify and OpenNext generate most of the medium-effort rows automatically.)

Vercel featureAWS approachWho generates itEffort
Global edge CDNAmazon CloudFrontAmplify / OpenNext / manualTrivial
Static assetsAmazon S3 (behind CloudFront)Amplify / OpenNextTrivial
Static export (output: export)S3 + CloudFront only — no serverDirect deployLow
SSR / Server ComponentsLambda (OpenNext/Amplify) or Node on FargateOpenNext / AmplifyMedium
API routes / Route HandlersAWS Lambda (or in the Fargate Node server)OpenNext / AmplifyMedium
Serverless FunctionsAWS Lambda + CloudFrontOpenNext / AmplifyMedium
Edge Functions / MiddlewareCloudFront Functions (light) / Lambda@Edge (heavy)OpenNextMedium–High
ISR / on-demand revalidationS3 + DynamoDB + SQS (OpenNext); shared cache on FargateOpenNext / AmplifyHigh
Image Optimization (next/image)Dedicated image Lambda, cached in S3/CloudFrontOpenNext / AmplifyMedium
Preview deployments (per PR)Amplify previews, or per-PR SST stage / per-branch CFAmplify (built-in) / SSTLow–Medium
Environment variables / secretsSecrets Manager + SSM Parameter StorePartner scripts the migrationLow
Build pipelineCodePipeline + CodeBuild, or keep GitHub ActionsPartner / your CIMedium
Custom domains + auto TLSRoute 53 + ACM (free certificates)Manual (one-time)Low
Analytics / Web VitalsCloudWatch RUM + CloudFront logs (or keep a SaaS)Partner / your choiceLow
Effort and cost direction are representative for 2026 and depend on whether you choose Amplify (managed) or OpenNext/SST (self-owned). The high-effort rows — ISR, edge middleware, the SSR/Lambda packaging — are exactly what OpenNext/Amplify generate and what a MAP-funded partner wires and validates end-to-end so the behavior matches Vercel.
want this run for you — and funded?
Get matched with an AWS partner who runs your Vercel→AWS (Next.js) migration (often MAP-funded)
Start in 3 minutes →
a recent match

A Vercel→AWS migration CloudRoute routed — anonymized

inquiry · seed/series-a b2c next.js app, Toronto
Consumer-facing Next.js (App Router) app — high-traffic SSR + ISR product pages, edge middleware for auth and geo-routing, heavy next/image usage. On Vercel Enterprise at ~$2,400/month and climbing with traffic; backend (Postgres, queue) already on AWS, so every front-end request was paying cross-cloud egress to reach AWS data.

Situation: The Vercel bill had become the second-largest infra line item, driven by bandwidth and function invocations on the SSR/ISR pages plus image optimization, and it scaled linearly with a growing user base ahead of a raise. The four-engineer team wanted to consolidate the front end into their existing AWS account (kill the cross-cloud egress, unify the bill and the SOC 2 surface) but had no serverless/CloudFront experience and couldn't lose Vercel's preview-deploy workflow or risk breaking ISR.

What CloudRoute did: Routed within 24 hours to an AWS Advanced-tier partner with a documented Next.js / OpenNext track record, who ran the MAP Assess phase (free) and filed the work as a MAP engagement. Target: OpenNext on Lambda + CloudFront + S3, with ISR backed by S3 + DynamoDB + an SQS revalidation queue, edge middleware split between CloudFront Functions (auth-cookie + geo) and Lambda@Edge, the image API on a dedicated cached Lambda, env vars moved into Secrets Manager + Parameter Store, and per-PR preview stages via SST with GitHub Actions driving deploys. Provisioned concurrency was set on the two latency-critical routes.

Outcome: Cutover was a Tuesday-morning DNS flip with no measurable downtime — the OpenNext stack was validated against a temp hostname and both endpoints ran in parallel through propagation. Steady-state AWS cost (CloudFront + Lambda + S3 + DynamoDB + SQS, including the image API) landed at ~$430/month versus ~$2,400 on Vercel — an ~82% cut — plus the cross-cloud egress to the backend disappeared. Project ran ~4 weeks; preview deploys preserved via SST stages. Because the workload qualified for MAP, AWS funded the assessment and credited the migration cost — out-of-pocket migration cost was effectively $0, and CloudRoute's commission was paid by the partner from MAP funding.

project length: ~4 weeks · cutover downtime: ~0 min (DNS) · monthly spend: $2,400 → $430 (−82%) · migration cost to customer: ~$0 (MAP-funded)

faq

Common questions

Can I run Next.js on AWS with the same features as Vercel?
Yes. There are two faithful paths. AWS Amplify Hosting is a managed product with first-class Next.js support — SSR, ISR/SSG, API routes, image optimization, git-push deploys, and per-PR preview branches — the closest managed equivalent to Vercel. OpenNext (deployed via SST) compiles your Next.js build onto the same AWS primitives Vercel uses under the hood: Lambda for the server, CloudFront as the CDN, S3 for static assets, S3 + DynamoDB + SQS for ISR, and a Lambda for image optimization. Both reproduce SSR, ISR/on-demand revalidation, edge middleware, and image optimization — the features port; the work is wiring them, which Amplify or OpenNext does for you.
Which AWS target should I choose for my Next.js app?
It depends on the app. Fully static (output: export) → S3 + CloudFront, cheapest and simplest. A dynamic Next.js app where you want a managed, low-ops experience close to Vercel → AWS Amplify Hosting. The full feature set self-owned with maximum control over cost and caching → OpenNext/SST on Lambda + CloudFront. Always-on latency (no cold starts), long-lived connections (WebSockets/streaming), or you already run other services on ECS → Next.js in standalone mode on Fargate. A migration partner picks the target in the Assess phase based on your routes, ISR usage, and traffic shape.
How much will I actually save moving off Vercel?
Representative high-traffic apps cut their monthly bill by 50–80%. An app running $350–$2,000+/month on Vercel Pro/Enterprise (bandwidth + function invocations + ISR + image optimization) commonly lands at $80–$500/month on AWS at the same traffic, because you pay AWS list/committed price for CloudFront egress, Lambda compute, and S3 rather than Vercel's convenience margin. If your backend is already on AWS, you also eliminate the cross-cloud egress between your front end and your data. The savings scale with traffic — the busier the app, the larger the gap.
How much downtime is there at cutover?
Usually 0–5 minutes — effectively just DNS propagation. A Next.js front end is stateless (durable state lives in your database, which typically isn't moving), so the cutover is a DNS repoint from Vercel to CloudFront/Amplify between two stacks serving the same backend, not a data migration. You lower the DNS TTL ahead of time, run both endpoints in parallel during propagation, verify, and keep Vercel warm as instant rollback. If the database is also moving, that cutover (via DMS/continuous replication) sets the window, not the front end.
What about ISR, edge middleware, and the image optimization API?
These are the Next.js-specific pieces and they map to AWS primitives. ISR and on-demand revalidation use a cache store — OpenNext implements it with S3 + DynamoDB + an SQS revalidation queue; Amplify manages it internally; on Fargate you use a shared cache handler. Edge middleware splits by weight: lightweight logic runs as a CloudFront Function, heavier middleware as Lambda@Edge. The Image Optimization API (next/image) becomes a dedicated Lambda that caches results in S3/CloudFront. OpenNext and Amplify generate all three for you — the strongest reason to use one of them rather than hand-rolling the stack.
Do I lose Vercel's preview deployments?
No. On AWS Amplify, per-pull-request preview deployments are built in and behave like Vercel previews, with per-branch environment variables in the console. On the self-owned targets (OpenNext/SST or Fargate) you reproduce previews with per-PR SST stages or per-branch CloudFront distributions, driven by CodePipeline/CodeBuild or your existing GitHub Actions. Amplify is the path of least disruption if the preview workflow is the main thing keeping you on Vercel; the self-owned route is a little more configuration but fully under your control with no per-preview platform cost.
What does AWS MAP funding mean for the cost of the migration?
The AWS Migration Acceleration Program (MAP) is how the migration itself can cost little to nothing. For qualifying migrations — generally those with a meaningful projected AWS spend afterward — AWS funds the Assess phase (TCO/readiness, typically free) and credits a large share of the migration/modernization cost, paying the partner through MAP rather than you. A Vercel→AWS move usually consolidates the front end into an existing AWS estate, which strengthens the post-migration spend case. When a workload doesn't qualify, CloudRoute still routes you to a vetted partner who runs the migration at a fixed scope; the 50–80% ongoing savings typically pay that back fast.
Can I roll back if the cutover goes wrong?
Yes, and it's one of the cleanest rollbacks in the migration cluster. Because the front end is stateless and you keep the Vercel project live until you're confident, rolling back is simply repointing DNS back to Vercel. Lower the DNS TTL to ~60 seconds the day before so both the switch and the rollback are near-instant. Most teams keep Vercel warm for a few days to a couple of weeks, watch the metrics, then cancel the plan — at which point the savings become real.

Move off Vercel — onto AWS, run by a partner, often funded by AWS.

CloudRoute routes you to a vetted AWS partner who plans and runs the whole Vercel→AWS migration — the right target (Amplify, OpenNext/SST, Fargate, or static), the Next.js wiring (SSR, ISR, edge middleware, image optimization), preview deploys, and the near-zero-downtime DNS cutover. Qualifying migrations are MAP-funded, so you capture the 50–80% ongoing savings without paying the usual migration bill.

matched within< 24h
typical cost cut50–80%
migration cost (MAP)$0–low
Vercel to AWS — Next.js migration architecture & cost (2026) · CloudRoute