AWS Amplify Hosting for Next.js: Setup and CI/CD
On this page
AWS Amplify Hosting is one of the fastest ways to get a Next.js application into production without provisioning servers, wrangling CloudFront distributions by hand, or writing your own deployment pipeline. It sits on top of AWS's managed infrastructure and gives you Git-based deployments, atomic releases, preview environments, and a global CDN out of the box. This guide walks through a real-world setup and shows how the CI/CD pipeline actually works.
Why Amplify Hosting for Next.js
Next.js is deceptively complex to host well. A modern app mixes static pages, server-rendered routes, API routes, image optimization, middleware, and increasingly React Server Components. If you self-host, you end up managing a Node server, a CDN, cache invalidation, and build orchestration yourself.
Amplify Hosting understands the Next.js build output natively. It detects whether a route is static or server-rendered and provisions the appropriate backing infrastructure — Lambda functions for SSR and API routes, S3 plus CloudFront for static assets. It supports the App Router, the Pages Router, ISR (Incremental Static Regeneration), and middleware. For most teams, this means you get near-Vercel ergonomics while staying inside your AWS account and billing.
The trade-offs worth knowing up front: Amplify pins support to specific Next.js major versions, so bleeding-edge releases may lag by a few weeks. Cold starts on SSR routes exist because they run on Lambda. And debugging build failures sometimes means reading CloudWatch logs rather than a polished dashboard. None of these are dealbreakers, but they shape how you plan a project.
Connecting Your Repository
The primary Amplify workflow is Git-driven. In the Amplify console, choose Host a web app and connect your provider — GitHub, GitLab, Bitbucket, or AWS CodeCommit. For GitHub, Amplify uses a GitHub App for scoped, revocable access rather than a broad personal token, which is the safer default.
Once connected, select the repository and the branch you want to deploy. The branch you pick becomes the trigger for your production environment. Every push to that branch kicks off a new build and deployment automatically — that is the core of the CI/CD loop.
Amplify auto-detects Next.js and proposes a build specification. You can accept it, but understanding and committing that spec to your repo is the better practice, since it makes builds reproducible and reviewable.
The Build Specification
Amplify builds are driven by an amplify.yml file. Keeping it in version control (rather than only in the console) means your build config travels with your code and is subject to code review. A typical Next.js build spec looks like this:
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
- .next/cache/**/*
A few things matter here. Use npm ci instead of npm install for deterministic installs based on your lockfile. Caching .next/cache dramatically speeds up subsequent builds because Next.js reuses compilation artifacts. And baseDirectory: .next tells Amplify where the build output lives — for a standard Next.js app this is correct, and Amplify's platform handles the SSR routing from there.
If you use a monorepo, set the AMPLIFY_MONOREPO_APP_ROOT environment variable and adjust the appRoot in your build settings so Amplify builds the correct package.
Environment Variables and Secrets
Next.js has two classes of environment variables: build-time and runtime. Variables prefixed with NEXT_PUBLIC_ are inlined into the client bundle at build time, so they must be present during the build phase. Server-only secrets (database URLs, API keys) are read at runtime by your SSR functions.
In Amplify, set environment variables in the console under Environment variables, or scope them per branch so staging and production differ. For genuinely sensitive values, use Secrets (backed by AWS Systems Manager Parameter Store) rather than plain environment variables. This keeps them out of build logs and out of your client bundle.
A common mistake: expecting a runtime secret to be available at build time, or accidentally prefixing a secret with NEXT_PUBLIC_ and shipping it to the browser. Audit your variable names carefully — anything with that prefix is public.
How CI/CD Actually Works
Once wired up, the pipeline is straightforward but powerful:
- Push to a connected branch. Amplify receives a webhook from your Git provider.
- Provision. Amplify spins up a build container.
- Build. It runs your
preBuildandbuildphases fromamplify.yml. - Deploy. Artifacts are pushed to CDN and SSR resources; the release is atomic, so users never see a half-deployed state.
- Verify. The new version goes live behind the Amplify domain (or your custom domain).
The atomic deployment model is a genuine advantage. If a build fails, your live site is untouched — there is no partial rollout. And because each deploy is versioned, you can roll back to a previous build from the console with one click.
Pull Request Previews
Enable Preview builds to get an ephemeral deployment for every pull request. Each PR gets its own URL, letting reviewers and QA test changes in a production-like environment before merging. The preview is torn down when the PR closes. This is one of the highest-value features for teams — it shifts testing left and catches SSR or environment-specific bugs that never appear in local npm run dev.
Branch-Based Environments
A clean pattern is to map long-lived branches to environments: main to production, develop to staging. Each branch is a separate Amplify app environment with its own variables, its own domain subpath, and its own build history. Merging develop into main promotes tested code to production automatically.
Custom Domains and HTTPS
Under Domain management, connect a domain you own. If your DNS is in Route 53, Amplify configures records automatically. For external DNS providers, you add the CNAME records Amplify provides. TLS certificates are issued and renewed automatically through AWS Certificate Manager — you never manage certificate rotation manually. Propagation usually completes within an hour.
Performance and Cost Considerations
Static assets are served from CloudFront's global edge network, so they are fast everywhere. SSR routes run on Lambda, which introduces occasional cold starts; keeping your server bundles lean and avoiding heavy top-level imports helps. Use ISR where possible so pages are cached and regenerated on a schedule rather than rendered on every request.
Cost scales with build minutes, data transfer, SSR request volume, and storage. For low-to-moderate traffic apps, Amplify is inexpensive. Watch for two cost traps: extremely frequent builds (throttle noisy branches) and high SSR volume that could be served statically instead. Profile which routes truly need SSR before shipping.
Troubleshooting Common Issues
Build succeeds locally but fails on Amplify. Almost always a Node version mismatch or a missing environment variable. Pin your Node version with a .nvmrc or the _LIVE_UPDATES build image setting, and confirm all NEXT_PUBLIC_ variables exist in the build environment.
SSR routes return 500s. Check CloudWatch logs for the underlying Lambda. A missing runtime secret is the usual culprit.
Slow builds. Confirm your cache paths include .next/cache and node_modules. Without caching, every build recompiles from scratch.
Unsupported Next.js version. Check Amplify's supported version matrix before upgrading Next.js majors in production.
FAQ
Is Amplify Hosting the same as AWS Amplify (the framework)? No. Amplify Hosting is the deployment and CI/CD product. The Amplify framework and libraries (for auth, data, storage) are separate — you can use Hosting without ever touching the client libraries.
Does Amplify support the Next.js App Router and Server Components? Yes. Amplify supports both the App Router and Pages Router, including Server Components, middleware, and ISR, on supported Next.js versions.
Can I deploy without connecting a Git repository? Yes, via manual deploys or the Amplify CLI, but you lose the automatic CI/CD triggers. Git-based deployment is the recommended path.
How do rollbacks work? Every deployment is versioned. From the console you can redeploy any previous successful build, and the switch is atomic.
How is this different from Vercel? Vercel is purpose-built for Next.js with tighter version support and a more polished DX. Amplify keeps everything inside your AWS account, integrates with IAM and other AWS services, and can be preferable for teams standardizing on AWS. The core workflow — Git push to deploy — is similar.
Can I run a monorepo?
Yes. Set the app root and the AMPLIFY_MONOREPO_APP_ROOT variable so Amplify builds the correct workspace.
Wrapping Up
AWS Amplify Hosting gives Next.js teams a production-grade CI/CD pipeline with almost no infrastructure work: connect a repo, commit an amplify.yml, configure environment variables, and every push ships automatically with atomic releases and preview environments. Start with a single branch, add PR previews once your team is comfortable, and lean on branch-based environments as the project grows. The result is a deployment workflow that stays inside AWS while feeling nearly as frictionless as any specialized Next.js host.