Deploying Next.js at the Edge with CloudFront
Deploying a Next.js Next.js — React framework for production nextjs.org ↗
application to
Vercel Vercel — frontend deployment platform vercel.com ↗
is effortless, but some teams need to keep their infrastructure within AWS — for compliance, for cost control, or for integration with existing VPC resources. The good news is that
Next.js Next.js — React framework for production nextjs.org ↗
runs well on AWS when you architect the deployment correctly. The key is separating static assets from dynamic rendering and using
CloudFront Amazon CloudFront — global content delivery network aws.amazon.com/cloudfront ↗
to serve each from the right origin.
Static assets — JavaScript bundles, images, fonts, and pre-rendered HTML — belong in S3 Amazon S3 — scalable object storage aws.amazon.com/s3 ↗
. Configure your
Next.js Next.js — React framework for production nextjs.org ↗
build to output static files to a directory that syncs to an S3 bucket. Then create a CloudFront distribution with the S3 bucket as the origin for the
/_next/static/* path pattern. Set a long cache TTL (one year is standard, since Next.js hashes filenames) and enable Brotli compression. This setup serves your static assets from edge locations worldwide with sub-50ms latency, without any traffic reaching your application server.
Dynamic routes — server-rendered pages, API routes, and ISR (Incremental Static Regeneration) responses — need a compute origin. You can run the Next.js Next.js — React framework for production nextjs.org ↗
server on ECS, Lambda, or EC2 behind an ALB, and configure
CloudFront Amazon CloudFront — global content delivery network aws.amazon.com/cloudfront ↗
to route all non-static paths to that origin. For ISR, the trick is cache behavior configuration: set the CloudFront TTL to match your revalidation period, and use
stale-while-revalidate headers so users always get a fast cached response while the origin regenerates the page in the background. When the page is regenerated, invalidate the specific CloudFront path to push the fresh version to the edge.
The TypeScript TypeScript — typed superset of JavaScript typescriptlang.org ↗
build pipeline ties everything together. Your CI job runs
next build, uploads the static output directory to S3, deploys the server bundle to your compute layer, and triggers a targeted CloudFront invalidation for any paths that changed. Using TypeScript TypeScript — typed superset of JavaScript typescriptlang.org ↗
throughout — in your application code, your infrastructure-as-code (
AWS CDK AWS CDK — define cloud infrastructure using programming languages aws.amazon.com/cdk ↗
or
Pulumi Pulumi — infrastructure as code using real programming languages pulumi.com ↗
), and your deployment scripts — gives you a single language across the entire stack. Type errors in your CDK constructs are caught at compile time, before they become misconfigured CloudFront behaviors in production.
One area that deserves attention is image optimization. The Next.js Next.js — React framework for production nextjs.org ↗
Image component relies on an optimization endpoint that resizes and converts images on the fly. On
Vercel Vercel — frontend deployment platform vercel.com ↗
, this runs on their edge network. On AWS, you need to either run the Next.js image optimizer on your compute origin (which works but adds load) or use a dedicated image processing service like Lambda@Edge or CloudFront Functions with an S3 origin. The Lambda@Edge approach handles the resize at the CDN layer, caches the result, and keeps your application server focused on rendering
React React — library for building user interfaces react.dev ↗
components rather than transcoding JPEGs.