Running Next.js behind AWS CloudFront
How to fix Next.js showing JSON instead of HTML when using AWS CloudFront by configuring cache policies.
Contrary to what many people say, Next.js is very easy to deploy in standalone mode with Docker. It supports everything out of the box, and there are mostly no issues. When issues do arise, it's not because Next.js uses any weird hacks, but because the industry doesn't always follow the defined standards that Next.js bases its features on.
For example, you cannot have true ISR when deploying Next.js on Cloudflare, because they haven't managed to move forward from their technical debt for at least 5 years now.
Another issue you might have faced is Next.js displaying strange JSON props instead of a real page when deployed on CDNs other than Vercel. I've encountered this problem on AWS CloudFront, Cloudflare CDN, and the Automattic VIP Platform.
The core of the problem (and the solution) is very simple. Next.js uses something called RSC (React Server Components). These components are executed on the server and need to communicate with the client. They do that by sending an HTTP request on the same path as the page where they’re used. So, you might see situations like this:
GET /homepage
GET /homepage?rsc=1apsd
The first request is a normal one that returns your .html
page content. The second request is for RSC communication. Because these requests share the same URL, most CDNs cannot tell them apart by default. As a result, it might happen that the request with ?rsc=1asda
gets cached first. If that happens, your page might display "weird JSON snippets" instead of a standard page. It could work fine during soft navigation, but a reload might cause the issue to appear. It may even show up as a sort of heisenbug, because the CDN has to propagate changes to many servers around the world (or several continents). This can lead to half of your users seeing the website working properly while the other half sees JSON output.
To fix this, you have to tell your CDN to respect the Vary
header. Next.js returns the Vary
header with properties like:
RSC, Next-Router-Prefetch, Next-Router-State-Tree, Next-URL
These basically tell a CDN which headers should be used as part of the cache key. CloudFront strips all of them unless you create a custom Cache Policy with these headers.
This is enough to fix the issue. You just apply the changes and wait until the cache invalidates and propagates across all CDN nodes.
If for some reason you don't want to do that, an alternative approach would be to add the ?rsc
query parameter to your cache policy or cache key.
Published on January 13, 2025 • 3 min read