Fixing Next.js Refresh Issue in Serverless CloudFront Deployment

February 27, 2025

posted by Vaithiyanathan K

Fixing Next.js Refresh Issue in Serverless CloudFront Deployment

Introduction:

When deploying our company website using Next.js with AWS CloudFront and S3, we encountered an issue: refreshing a page redirected users to the homepage instead of loading the correct content. This problem stemmed from how CloudFront handles routing in a static site deployment. In this blog, we'll explain why this happens and how we fixed it using an Edge Lambda function.  

The Issue: 

We used a CloudFormation template to set up: 

  • S3 for hosting 

  • AWS CodePipeline & CodeBuild for CI/CD 

  • CloudFront for CDN 

  • GitHub as the source repository 

Everything worked fine—deployments were successful, and the site loaded correctly. However, a page refresh caused an unexpected behavior: 

Problem: 

When a user refreshed a page (e.g., ‘/contacts’), the UI redirected them to the homepage (where index.html was served), but the URL remained unchanged (still ‘/contacts’). 

Why the Issue Happens 

In a serverless setup using AWS CloudFront and S3, CloudFront serves static files directly from S3. Next.js relies on client-side routing, meaning it dynamically updates the URL without requesting a new page from the server. However, when a user refreshes a page (e.g., /contacts), CloudFront attempts to retrieve /contacts from S3, but this file doesn’t exist. As a fallback, it serves index.html while keeping the URL unchanged, causing the homepage to load instead of the expected content. 

The Solution :

To fix this, we needed to ensure that the correct HTML file was loaded for each route. This was achieved using an Edge Lambda function in CloudFront. 

Edge Lambda Code 

AWS Lambda@Edge function: 

export const handler = async (event) => { 
    var request = event.Records[0].cf.request; 
    var uri = request.uri;      
    if (uri.endsWith('/')) { 
        request.uri += `.html`; 
    } else if (!uri.includes('.')) { 
        request.uri += `.html`; 
    }   
    return request; 
}; 

Steps to Implement :

  1. Create a Lambda function. 

  2. Deploy the Lambda function with the above code in us-east-1 (required for Lambda@Edge). 

  3. Update IAM Policies to grant the required permissions: 

  • AWSLambdaBasicExecutionRole – Provides logging and execution capabilities. 

  • CloudFrontFullAccess – Allows interaction with CloudFront. 

Next.js refresh issue - Lambda IAM roles
Publishing Lambda and Deploying to Lambda@Edge :

After providing the necessary permissions, follow these steps to deploy it successfully: 

  1. Publish a new version of the Lambda function. 

  2. Inside the Lambda Actions, select "Deploy to Lambda@Edge." 

  3. Follow the setup process to complete the deployment. 

Next.js refresh issue - Lambda edge deployment

Make Sure to Verify CloudFront Behavior 

Before verifying the results, ensure that the CloudFront behavior settings include the Lambda@Edge function.  To ensure the solution works: 

Next.js refresh issue - cloudfront behaviour check

To ensure the solution works: 

  • Refresh a page (e.g., /contacts) and confirm that it loads correctly instead of redirecting to the homepage. 

Result :

After applying this to Edge Lambda, the refresh issue was resolved! Now, users can refresh the page, and the correct content loads without redirecting to the home page. 

Conclusion :

If you face a similar issue with a Next.js app on CloudFront, this method ensures that refreshes behave correctly by mapping URLs to the correct HTML files. By following these steps and ensuring the correct permissions, you can successfully fix the refresh issue in your serverless deployment.