Skip to main content

Next.js AWS Deployment

Introduction

Deploying a Next.js application to AWS gives you powerful infrastructure capabilities while maintaining control over your application's hosting environment. Amazon Web Services (AWS) provides a vast array of services that can be used to host and scale your Next.js applications from small projects to enterprise-level applications.

In this guide, we'll walk through the process of deploying a Next.js application to AWS using several different approaches, starting with simpler options and moving towards more advanced configurations. By the end, you'll understand how to choose the right AWS deployment strategy for your specific needs.

Prerequisites

Before we begin, make sure you have:

  • A working Next.js application
  • Node.js and npm installed on your machine
  • An AWS account
  • AWS CLI installed and configured with your credentials
  • Basic understanding of cloud deployment concepts

Deployment Options on AWS

There are several ways to deploy a Next.js application on AWS:

  1. AWS Amplify - Simplest approach, good for beginners
  2. Amazon S3 + CloudFront - For static exports (Next.js export)
  3. AWS Elastic Beanstalk - For server-rendered Next.js apps
  4. AWS EC2 - For complete control and custom configurations
  5. AWS ECS/EKS with Docker - For containerized deployments
  6. AWS Lambda + API Gateway - For serverless deployments

Let's explore these options in detail.

Option 1: Deploying with AWS Amplify

AWS Amplify is the simplest way to deploy a Next.js application on AWS, especially if you're a beginner.

Step 1: Prepare your Next.js Application

Ensure your Next.js application is working locally and pushed to a Git repository (GitHub, GitLab, or Bitbucket).

Step 2: Set Up AWS Amplify

  1. Log in to your AWS Management Console
  2. Navigate to AWS Amplify service
  3. Click "New app" and select "Host web app"
  4. Choose your repository provider and connect your repository

Step 3: Configure Build Settings

Amplify will auto-detect that you're using Next.js, but you may need to modify the build settings:

yaml
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*

Step 4: Deploy Your Application

Click "Save and deploy" and Amplify will handle the rest! Your application will be built and deployed to a global CDN with an auto-generated domain.

Output: After a successful deployment, you'll receive a URL like: https://main.d123abcdef.amplifyapp.com

Adding Custom Domains

You can easily add your own custom domain through the Amplify Console:

  1. Navigate to "Domain management" in your app's dashboard
  2. Click "Add domain"
  3. Follow the steps to configure and verify your domain

Option 2: S3 + CloudFront for Static Exports

If your Next.js application can be exported as static files, this option provides cost-effective hosting with global CDN benefits.

Step 1: Export Your Next.js Application

Update your next.config.js file to enable static exports:

javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
// Optional: Disable image optimization since it's not supported in export mode
images: {
unoptimized: true,
},
}

module.exports = nextConfig

Then build and export your application:

bash
npm run build

This will generate a static export in the out directory.

Step 2: Create an S3 Bucket

  1. Navigate to S3 in the AWS Console
  2. Click "Create bucket"
  3. Name your bucket (e.g., my-nextjs-app)
  4. Configure bucket settings (public access, etc.)
  5. Complete the bucket creation

Step 3: Upload Your Static Files

Upload the contents of the out directory to your S3 bucket:

bash
aws s3 sync out/ s3://my-nextjs-app

Step 4: Configure S3 for Static Website Hosting

  1. Go to your bucket properties
  2. Enable "Static website hosting"
  3. Set "Index document" to index.html
  4. Set "Error document" to 404.html

Step 5: Create a CloudFront Distribution

  1. Navigate to CloudFront in the AWS Console
  2. Click "Create Distribution"
  3. Set the Origin Domain to your S3 bucket's website endpoint
  4. Configure cache settings and other options
  5. Enable HTTPS

Output: After deployment, your site will be available at a CloudFront domain like: https://d1234abcdef.cloudfront.net

Option 3: AWS Elastic Beanstalk Deployment

For server-rendered Next.js applications, Elastic Beanstalk provides a managed environment that's easier than configuring EC2 directly.

Step 1: Prepare Your Application

Create a .ebignore file to specify which files to exclude from deployment:

node_modules
.next
npm-debug.log

Step 2: Add a Start Script

Make sure your package.json has the correct start script:

json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start -p $PORT"
}
}

Step 3: Add Application Configuration

Create a file named Procfile in your project root:

web: npm start

Step 4: Install Elastic Beanstalk CLI and Deploy

bash
# Install EB CLI
pip install awsebcli

# Initialize EB application
eb init

# Create an environment and deploy
eb create my-nextjs-environment

Follow the prompts to configure your environment. Once deployed, you can access your application using the provided URL.

Output: After deployment, you'll receive a URL like: http://my-nextjs-environment.eba-abcd1234.us-east-1.elasticbeanstalk.com

Option 4: AWS EC2 Deployment

For complete control over your hosting environment, you can deploy to EC2 directly.

Step 1: Launch an EC2 Instance

  1. Navigate to EC2 in the AWS Console
  2. Launch a new instance (Amazon Linux 2 recommended)
  3. Configure security groups to allow HTTP (port 80) and HTTPS (port 443)
  4. Create or select a key pair for SSH access
  5. Launch the instance

Step 2: Install Dependencies

SSH into your instance and install required dependencies:

bash
# Update system packages
sudo yum update -y

# Install Node.js
curl -sL https://rpm.nodesource.com/setup_16.x | sudo bash -
sudo yum install -y nodejs

# Install PM2 globally for process management
sudo npm install -g pm2

Step 3: Deploy Your Application

Clone your repository or upload your application to the EC2 instance:

bash
# Clone your repository
git clone https://github.com/yourusername/your-nextjs-app.git

# Navigate to your application directory
cd your-nextjs-app

# Install dependencies
npm install

# Build the application
npm run build

Step 4: Run Your Application with PM2

bash
# Start the application using PM2
pm2 start npm --name "next-app" -- start

# Make PM2 start on system boot
pm2 startup
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ec2-user --hp /home/ec2-user
pm2 save

Step 5: Set Up Nginx as a Reverse Proxy

bash
# Install Nginx
sudo yum install -y nginx

# Configure Nginx
sudo nano /etc/nginx/conf.d/nextjs.conf

Add the following configuration:

nginx
server {
listen 80;
server_name your-domain.com www.your-domain.com;

location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

Restart Nginx:

bash
sudo systemctl restart nginx

Output: Your Next.js application will be accessible at your EC2 instance's public IP or domain name if configured.

Option 5: Containerized Deployment with AWS ECS

For a containerized approach, you can use Docker with Amazon ECS (Elastic Container Service).

Step 1: Create a Dockerfile

In your project root, create a Dockerfile:

dockerfile
# Base on Node.js Alpine
FROM node:16-alpine AS builder

# Set working directory
WORKDIR /app

# Copy package files and install dependencies
COPY package*.json ./
RUN npm ci

# Copy app files
COPY . .

# Build application
RUN npm run build

# Production image
FROM node:16-alpine AS runner
WORKDIR /app

ENV NODE_ENV production

# Copy necessary files from builder
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

# Expose port and define start command
EXPOSE 3000
CMD ["npm", "start"]

Step 2: Build and Test Your Container Locally

bash
# Build your Docker image
docker build -t my-nextjs-app .

# Test it locally
docker run -p 3000:3000 my-nextjs-app

Step 3: Push to Amazon ECR

bash
# Create a repository in ECR
aws ecr create-repository --repository-name my-nextjs-app --region us-east-1

# Log in to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin your-account-id.dkr.ecr.us-east-1.amazonaws.com

# Tag your image
docker tag my-nextjs-app:latest your-account-id.dkr.ecr.us-east-1.amazonaws.com/my-nextjs-app:latest

# Push to ECR
docker push your-account-id.dkr.ecr.us-east-1.amazonaws.com/my-nextjs-app:latest

Step 4: Create ECS Cluster and Service

You can use the AWS Console to:

  1. Create an ECS cluster
  2. Create a task definition that references your ECR image
  3. Create a service that runs your task

Alternatively, you can use AWS CLI or infrastructure as code tools like AWS CDK, Terraform, or CloudFormation.

Option 6: Serverless Deployment

For serverless deployments, you can use the Serverless Framework or AWS CDK with Lambda functions.

Using Serverless Framework with Next.js

First, install the required packages:

bash
npm install --save-dev serverless serverless-nextjs-plugin

Create a serverless.yml file:

yaml
service: my-nextjs-app

provider:
name: aws
runtime: nodejs16.x
region: us-east-1

plugins:
- serverless-nextjs-plugin

custom:
serverless-nextjs:
routes:
- src: '/_next/static/(?<file>.*)'
dest: '/_next/static/$file'
- src: '/api/(?<path>.*)'
dest: '/api/$path'
- src: '/(?<page>.*)'
dest: '/$page'

Deploy your application:

bash
serverless deploy

Output: After deployment, your application will be available at an API Gateway URL like: https://abc123def.execute-api.us-east-1.amazonaws.com/dev

Continuous Integration and Deployment (CI/CD)

For automated deployments, you can set up CI/CD pipelines using:

  1. AWS CodePipeline - Fully managed CI/CD service from AWS
  2. GitHub Actions - Integrate with your GitHub repository
  3. GitLab CI/CD - If you're using GitLab for source control

Here's a simple GitHub Actions workflow for deploying to AWS Amplify:

yaml
name: Deploy to AWS Amplify
on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1

- name: Deploy to Amplify
run: |
aws amplify start-job --app-id ${{ secrets.AMPLIFY_APP_ID }} --branch-name main --job-type RELEASE

Performance Optimization

To optimize your Next.js application on AWS:

  1. Use CloudFront for global content delivery
  2. Enable caching for static assets
  3. Implement AWS WAF for security and traffic management
  4. Set up CloudWatch for monitoring and alerts
  5. Use Route 53 for DNS management and routing policies

Cost Considerations

When deploying on AWS, be mindful of costs:

  • S3 + CloudFront - Most cost-effective for static sites
  • Amplify - Simple pricing based on build minutes and storage
  • Elastic Beanstalk/EC2 - Pay for compute hours and storage
  • ECS/EKS - Additional orchestration costs
  • Serverless - Pay per request, can be very cost-effective for variable traffic

Troubleshooting Common Issues

  1. Build Failures: Check your build settings and ensure all dependencies are correctly installed.
  2. Routing Problems: Verify your Next.js routing configuration works with the chosen deployment method.
  3. Environment Variables: Ensure all required environment variables are properly configured in AWS.
  4. SSL/HTTPS Issues: Check certificate configuration when setting up custom domains.

Summary

In this guide, we've explored multiple ways to deploy a Next.js application to AWS, from simple options like AWS Amplify to more advanced containerized and serverless deployments. Each approach has its own advantages:

  • AWS Amplify - Easiest for beginners, great for quick deployments
  • S3 + CloudFront - Ideal for static exports, cost-effective
  • Elastic Beanstalk - Good balance of control and managed services
  • EC2 - Maximum control over your environment
  • ECS/EKS - Great for containerized workflows
  • Serverless - Excellent for variable traffic patterns

Choose the deployment strategy that best fits your application's needs, team expertise, and budget constraints.

Additional Resources

Exercises

  1. Deploy a basic Next.js application to AWS Amplify and configure a custom domain.
  2. Create a static export of a Next.js app and deploy it to S3 with CloudFront.
  3. Set up a CI/CD pipeline using GitHub Actions to automate deployment to your chosen AWS service.
  4. Implement a serverless Next.js application using AWS Lambda and API Gateway.
  5. Create a Docker container for your Next.js application and deploy it to AWS ECS.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)