Header image by Max Bender on Unsplash
Next.js is one of the most popular frontend (meta) frameworks in 2023 and for good reason. However it has a dark side that nobody talks about, yet it can bite you in the back when you try to scale a Next based project. Let me show you the worst parts of Next.js so you can prepare for them in advance. To be upfront, most of these should be rare cases.
If you host Next.js yourself and do multi-instance scaling, ISR won't be your best friend. Each instance will have its own cache for the generated pages. If your load-balancer is not using sticky sessions, that means trouble. Depending on the status of the regeneration process on each node, the visitor can be served both stale and up-to-date content during the same sessions. That's bad, like really bad from the user experience point of view. Here's a flow diagram to demonstrate it:
The on-demand ISR can help in minimizing this risk, but can't fully eliminate it while also complicating both your codebase and your operational processes quite a lot. That's far from ideal.
There are four solutions to this problem.
- First is to avoid it completely by replacing ISR with SSR. Not a what you would prefer, right?
- Second is using Vercel to host your project or any similar platforms and let them scale your application. Not an option either?
- Then enter Next Boost a community library to boost your backend rendering performance by orders of magnitude.
- Set up additional infrastructure around your Next.js instances. (more on this later)
Next Boost works as a cache in front of SSR-ed pages, like a custom implementation of ISR but here you can configure where to store the results and their redis-cache option is ideal to be used with a cluster of Next.js servers. It will be a single-source-of-pages for all the nodes.
Sadly, this solution is not without downsides either. It complicates your tech stack and adds a new operational and maintenance cost factor. More importantly, the maintainer doesn't seem to be very active, so you might need to fork and customize the package if its current capabilities doesn't suit your project.
Back to Option 4:
The Reddit community was kind enough to raise my attention to these. Thanks everyone and especially for beny27, dbbk and porcupineapplepieces!
You can implement a similar solution to Next Boost on your own. The main idea is to add some kind of caching in front of your Next servers like an AWS S3 bucket and configure a load balancer to look up the responses there first or by setting up a CDN. Both of these examples need ISR switched off and using SSR instead.
⬆️⬆️⬆️ If you need to scale custom Next.js servers these are the things you should keep in mind.
If you work on a large-scale project, chances are you run multiple applications from the same top-level domain and you need to support i18n. Well, that's a hard situation for Next.js!
The culprit is the router, Dhanraj Padmashali @psygik wrote about it in detail here. To sum it up, it's currently
not possible hacky to run multiple Next.js apps under the same domain if their url paths contain a language code prefix. For example:
site.com/en/app or in general:
The community created some workarounds to escape this limitation, but you need to be mindful to either monkey patch the
next/router or add an app wide middleware to rewrite the URL or use even more drastic measures.
Dhanraj also points out that if your whole application lives under a path of a larger site, e.g.:
site.com/cool-apps/next-app that gets internally proxied to another URL and the app uses dynamic route parameters for SSR'd pages eg:
/next-app/users/beastmaster64 it will die on the internal
_next/data requests for the
json page data because that folder doesn't respect the
assetPrefix nor the
basePath values. Yes, complicated, but not uncommon. There's a workaround in the linked article, but it's again, rather hacky and needs a custom server.
⬆️⬆️⬆️ Keep these in mind while planning your architecture.
This is a technical detail which can only become a show-stopper in very few cases, nonetheless, it might affect you. The built-in, file-based router cannot provide "real" client-side dynamic navigation. If your application really needs that, then take a look at this guide showing how to integrate
react-router with Next.js. If that still doesn't meet your needs (main drawback: lack of initial SSR) than it's sadly time to say goodbye to this framework.
But what do I mean by the router not supporting SPA navigation? Next.js either creates the pre-built HTML for a page (SSG) or uses server-side rendering to deliver it. The second option can use dynamic runtime path parameters, while the first works only with known paths even if those are fetched dynamically during the build step. This way you can't deliver "truly" SPA style, dynamic, client-side transitions, only if you use query parameters instead of the URL path, like this:
/product-category/shoes/1 => ONLY SSG OR SSR
/product-category?category=shoes&page=1 => YOU IMPLEMENT CSR
If you are interested in a real life example where this can really make a difference, check out this article from SingleStore about why they moved away from Next.js, specifically the Dynamic Routing part.
Some developers and companies might be unaware of the fact that every Next.js project sends live statistics to Vercel, a private company unless you opt-out of the collection. This is questionable, especially in case of an open source project. If you are interested in what exactly is collected and how to disable it Florian wrote and insightful post about it on Medium.
Do you want to learn more less-known facts and behind-the-scenes about Next.js?
Then check out my complete Full Context Next.js Review which goes into waaay more detail. It's long (the table of contents help), by now is a bit outdated as it's about v.12 but I'm sure there's a lot you would find interesting, relevant and useful.
I also post similarly insightful articles on my Substack page and newsletter.
Top comments (0)