Back to Blog

Implementing maintenance mode in Next.js apps

When managing a Next.js project, it's essential to have a strategy in place for times when the site needs to go into maintenance mode. Here are some options for effectively implementing such a mode.

Implementing maintenance mode in Next.js apps

When managing a Next.js project, it's essential to have a strategy in place for times when the site needs to go into maintenance mode. This ensures that users are not faced with a broken or insecure site during updates or fixes. This article discusses how to implement such a mode effectively, with an emphasis on minimizing disruption and maintaining a professional user experience during these pauses in service.

Next-maintenance-mode is a middleware specially designed for Next.js applications, enabling to toggle maintenance mode on and off easily. When activated, it redirects users to a designated maintenance page, while still keeping essential parts of the site operational. Its compatibility with configuration providers such as Upstash and Edge Config allows for flexible and dynamic maintenance state management.

Provider Reads (free plan)
Vercel/Edge-Config 50k/month
Upstash/Redis ~ 300k/month (10k/day)

Our solution also includes an optional caching feature to help save bandwidth. It uses LRU cache under the hood. While it may not be the best solution it still helps to reduce bandwidth usage. Due to edge functions nature, the LRU cache might occasionally reset, but it's nothing to worry about. If this happens, the status is automatically checked in the provider and updated. This won't affect passed middleware's functions - they are not cached.

1import { withMaintenanceMode } from 'next-maintenance-mode'
3const middlewareOptions = {
4  provider: 'upstash' | 'edge-config', // Required
5  maintenancePageSlug: '/maintenance', // Optional
6  key: 'your_key_here', // Optional
7  cacheTime: 'number', //Optional - defined in ms for e.g. 60000 = one minute
11  {
12    beforeCheck: NextMiddleware, // function which will be executed before checking the maintenance mode (if an instance of NextResponse is returned, checking maintenance mode status & afterCheck is skipped) 
13    afterCheck: NextMiddleware, // function which will be executed after checking the maintenance mode (only if maintenance mode status is set to false)
14  },
15  'your_connection_string_here',
16  middlewareOptions,

You can also easily access the req parameter in passed middleware functions, this allows for seamless integration with for e.g. next-auth.

1import { NextFetchEvent, NextRequest, NextResponse } from "next/server";
2import { withMaintenanceMode } from "next-maintenance-mode";
3import { getToken } from "next-auth/jwt";
5async function firstMiddleware(req: NextRequest, _next: NextFetchEvent) {
7  const token = await getToken({ req });
8  if (!token) {
9    return NextResponse.rewrite(new URL("/sign-in", req.nextUrl));
10  }
11  if (token.role === "admin") {
12    return; //If you want you can disable checking maintenance mode for users with an admin role
13  }
16async function secondMiddleware(req: NextRequest, _next: NextFetchEvent) {
17  console.log("secondMiddleware");
20export default withMaintenanceMode(
21  { beforeCheck: firstMiddleware, afterCheck: secondMiddleware },
23  {
24    provider: process.env.MAINTENANCE_MODE_PROVIDER as any,
25    maintenancePageSlug: process.env.MAINTENANCE_MODE_PAGE_SLUG,
26    key: process.env.MAINTENANCE_MODE_KEY,
27  }
31export const config = {
32  matcher: ["/((?!api/auth|_next/static|_next/image|favicon.ico).*)"],

By splitting functions to execute either before or after checking maintenance status you can for e.g. allow users with admin rights to access the page while every other user will be presented with the maintenance mode page.

Apart from that you can also use updateMaintenanceModeStatus function which allows you to toggle the maintenance mode from the server side for e.g. route handler. It means that you can easily create an admin panel where it’d be possible to toggle the mode. Or if any critical error occurs for e.g. if a test fails you can toggle it automatically.

Try it out yourself!

🛠️ Next.js Maintenance Mode

Vercel has created a template that uses edge config (global datastore). It’s an easy-to-implement and simple solution. It uses Next.js middleware, evaluating each request to see if the maintenance mode is activated. Simple, right? However, there’s a catch. If you exceed 50,000 reads per month,  it can become expensive. For websites that have a significant volume of traffic, the number of reads can quickly add up, leading to unexpected costs.

Using conditional rendering for a maintenance mode in Next.js involves displaying a <MaintenancePage/> component instead of the usual application content when an environment variable indicates maintenance is active. This can be quickly implemented by checking the environment variable in the _app.js file and rendering the maintenance page accordingly.

Here's a more detailed look at how this could be structured within your _app.js file:

1function MyApp({ Component, pageProps }) {
2  if (process.env.MAINTENANCE_MODE === 'true') {
3    // Render the maintenance page instead of the regular component
4    return <MaintenancePage />;
5  }
7  // Otherwise, render the normal component
8  return <Component {...pageProps} />;

However, this method doesn't restrict access to API routes, which remain functional and might cause inconsistent behavior if accessed directly during maintenance. Additionally, if the build process relies on live data (used for e.g. in middleware file) that's unavailable during maintenance, it could lead to build failures.

To address these drawbacks, developers might need to implement additional checks or fallbacks for API routes and ensure that the build process can handle unavailable data, either through error handling or by using cached data. This can make the logic more complex and hard to maintain.

Using Vercel deployment, an effective strategy for displaying a maintenance page might be to create a separate branch named, for example, “maintenance-page”. This method avoids the need to change anything in the database, providing a seamless way to switch to a maintenance view when required. Within Vercel, you can use the “promote to production” function, enabling the selected branch to replace the existing production deployment. This approach ensures that the construction and deployment of the project continue uninterrupted, even if there’s a failure in the backend. However in this case there are several major issues:

  • Third-Party Dependency: Relies on Vercel's uptime, with no control during their outages.
  • Time Delays: Switching to maintenance mode is not instant due to build times.
  • Rollback Complexity: Returning to the main site requires another build, adding downtime.

To summarize, when dealing with backend issues or security vulnerabilities in Next.js projects, it's important to have an effective maintenance mode strategy. The options considered include using middleware for global datastore checks, conditional rendering, creating a separate branch for maintenance, and utilizing the next-maintenance-mode library. Each has its considerations, such as potential costs, exposure of API routes, build-time dependencies, and downtime for deployment.

The next-maintenance-mode library stands out by offering an easily integrated, cost-effective solution that ensures the frontend can display a maintenance page while selectively allowing access to certain users, like admins, without significant performance drawbacks or unexpected expenses.

🛠️ Next.js Maintenance Mode

Contact us today...

to discuss your web development project and discover how our team can help you achieve your goals.

Tell us about your project

Empower your vision, partner with us today

Author photo
Jakub Czapski
Founding Partner at Blazity
To best serve you, let's get to know your requirements first. Tell us about your project, and we'll arrange a free consultation call to discuss how we can help.

Trusted by:

Trusted by logoTrusted by logoTrusted by logoTrusted by logo
Do you need an NDA first?