//Technology

Deploy a Dynamic Next.js App to Vercel with Edge Middleware Caching

Deploy a dynamic Next.js app to Vercel with custom Edge Middleware for smart caching, covering setup, middleware, deployment, performance tuning.

7 min read
Deploy a Dynamic Next.js App to Vercel with Edge Middleware Caching

Next.js is a popular framework for building modern, dynamic web applications. Pairing it with Vercel provides seamless deployments, automatic scaling, and built‑in edge capabilities. This guide walks through deploying a dynamic Next.js app to Vercel and adding a custom Edge Middleware layer to manage response caching at the edge.

1. Prepare Your Next.js Project

Before deploying, ensure your local development environment is set up. The installation steps below cover Debian/Ubuntu (using apt) and AlmaLinux/Rocky/RHEL (using dnf). If you are using Windows, use PowerShell or WSL with the respective Linux commands.

Install Node.js and npm

Use the NodeSource script to add the official repository and install the latest LTS version of Node.js.

# Debian/Ubuntu
sudo apt update
sudo apt install -y curl
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# AlmaLinux/Rocky/RHEL
sudo dnf install -y curl
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs

Verify the installation by checking the versions:

node -v
npm -v

Create a New Next.js App

npx create-next-app@latest my-dynamic-app
cd my-dynamic-app

The starter template includes a pages directory (or the app directory if you opt‑in to the App Router). This tutorial uses the Pages Router, which integrates well with edge middleware.

Test Locally

npm run dev

Open http://localhost:3000 in your browser to confirm the default page loads. Once verified, your project is ready for deployment.

2. Add Dynamic Routes and API Endpoints

Dynamic content, such as product pages, user profiles, or real‑time dashboards, is central to many applications. We will create a dynamic route that fetches data from a public API and a simple API route that returns JSON.

Dynamic Page: pages/products/[id].js

import { useRouter } from 'next/router';
import useSWR from 'swr';

const fetcher = (url) => fetch(url).then((res) => res.json());

export default function Product() {
  const { query } = useRouter();
  const { data, error } = useSWR(
    query.id ? `https://fakestoreapi.com/products/${query.id}` : null,
    fetcher
  );

  if (error) return <p>Failed to load product.</p>;
  if (!data) return <p>Loading…</p>;

  return (
    <div>
      <h1>{data.title}</h1>
      <img src={data.image} alt={data.title} width={200} />
      <p>{data.description}</p>
      <p><strong>${data.price}</strong></p>
    </div>
  );
}

This page uses useSWR for client‑side data fetching. The route parameter [id] makes the page dynamic.

API Route: pages/api/health.js

export default function handler(req, res) {
  res.status(200).json({ status: 'ok', timestamp: Date.now() });
}

Vercel treats paths under /api as serverless functions. This endpoint is useful for health checks and will be referenced when configuring edge caching.

3. Configure Edge Middleware for Smart Caching

Vercel Edge Middleware runs at the CDN edge, before a request reaches your Next.js server. You can use it to determine which responses should be cached, for how long, and under what conditions.

Create the Middleware File

Create a middleware.js file at the project root (or inside the /middleware directory if using the new layout). The file must export a middleware function.

import { NextResponse } from 'next/server';

export function middleware(request) {
  const url = request.nextUrl.clone();

  // Bypass caching for API routes and auth pages
  if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/login')) {
    return NextResponse.next();
  }

  // Cache HTML pages for 10 seconds, JSON for 60 seconds
  const response = NextResponse.next();

  if (url.pathname.endsWith('.json')) {
    response.headers.set('Cache-Control', 'public, max-age=60, stale-while-revalidate=30');
  } else {
    response.headers.set('Cache-Control', 'public, max-age=10, stale-while-revalidate=20');
  }

  // Add a custom header for debugging
  response.headers.set('X-Edge-Middleware', 'active');

  return response;
}

// Apply middleware to all routes except static assets
export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};

Key parts of this configuration:

  • matcher: Defines which paths the middleware should run on. It excludes Next.js internal static folders.
  • Cache-Control: Sets HTTP caching directives that Vercel’s edge network respects. stale-while-revalidate allows serving stale content while a fresh version is fetched in the background.
  • Bypass logic: API routes and authentication pages are typically not cacheable, so they are passed through unchanged.

Test Middleware Locally

Next.js 13+ supports running middleware in development mode. Start the dev server and inspect response headers using your browser’s developer tools or curl:

curl -I https://localhost:3000/products/1

Look for the Cache-Control and X-Edge-Middleware headers. If they appear, the middleware is wired correctly.

4. Set Up Vercel Project and Deploy

Deploying to Vercel is straightforward due to its Git integration. The steps below are identical regardless of the operating system used locally.

Push Code to a Git Repository

git init
git add .
git commit -m "Initial commit with middleware"
git branch -M main
git remote add origin https://github.com/your-username/your-repo.git
git push -u origin main

Replace the URL with your actual repository location. Vercel supports GitHub, GitLab, and Bitbucket.

Create a Vercel Account and Import the Project

  1. Visit vercel.com/signup to create an account or log in.
  2. Click New Project and select the repository you just pushed.
  3. Vercel automatically detects the Next.js framework and suggests the correct build settings (npm install and npm run build).
  4. Keep the default “Production Branch” as main unless you prefer a different workflow.
  5. Click Deploy. Vercel will clone the repo, install dependencies, build the app, and provision the CDN edge network.

Verify the Deployment

After the build finishes, Vercel provides a preview URL (e.g., https://my-dynamic-app.vercel.app). Open it in a browser and navigate to a dynamic product page, such as /products/2. Use the network tab to confirm the custom headers from the middleware are present.

Configure Environment Variables (Optional)

If your app requires secrets (API keys, database URLs, etc.), add them in the Vercel dashboard under Project Settings → Environment Variables. Assign them to Production or Preview based on the stage.

5. Fine‑Tune Caching Strategy

Edge middleware offers flexibility, but you may need to adjust caching rules as your application grows.

Cache by Query Parameters

If the same page URL returns different data based on query strings (e.g., /search?q=shoes), modify the middleware to include the query string in the cache key:

const url = request.nextUrl.clone();
const cacheKey = `${url.pathname}?${url.searchParams.toString()}`;
response.headers.set('Cache-Control', 'public, max-age=30, stale-while-revalidate=15');
response.headers.set('Vercel-Cache-Tag', cacheKey);

Vercel respects the Vercel-Cache-Tag header for edge‑level cache segregation.

Invalidate Cache on Content Updates

When product data updates, you can programmatically purge the edge cache using Vercel’s API:

curl -X POST https://api.vercel.com/v9/now/deployments/{deploymentId}/purge \
  -H "Authorization: Bearer YOUR_VERCEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paths":["/products/1","/products/2"]}'

Replace {deploymentId} and the token with values from your Vercel dashboard. This ensures users see the latest content without waiting for the max-age to expire.

Combine with Incremental Static Regeneration (ISR)

If some pages can be statically generated but need periodic updates, use Next.js ISR (revalidate in getStaticProps) alongside edge caching. The edge layer serves cached HTML quickly, while ISR regenerates the page in the background after the specified interval.

6. Monitor Performance and Debug Edge Behavior

Vercel provides built‑in analytics and logs to help you understand how edge caching impacts latency.

  • Analytics Dashboard: Displays request counts, cache hit ratios, and geographic distribution.
  • Edge Function Logs: In the Vercel UI, go to Functions → Edge Middleware to view logs for each request. Add console.log statements in middleware.js for deeper insight.
  • Real‑User Monitoring (RUM): Integrate a lightweight RUM script (e.g., Vercel’s @vercel/analytics) to capture actual page load times from browsers.

Regularly reviewing these metrics helps you adjust max-age values, add or remove cache tags, and maintain an optimal balance between freshness and speed for your audience.

Conclusion

Deploying a dynamic Next.js application to Vercel is fast, and adding custom Edge Middleware provides fine‑grained control over caching at the CDN edge. In this guide, we:

  • Set up a Next.js project with dynamic routes and API endpoints.
  • Implemented middleware to distinguish between HTML and JSON responses, apply appropriate Cache-Control headers, and skip caching for sensitive routes.
  • Deployed the app to Vercel using Git integration.
  • Explored advanced caching tweaks, including query‑parameter‑based keys, programmatic purging, and ISR synergy.
  • Highlighted monitoring tools to keep performance in check.

With these steps, your application can serve dynamic content quickly to users across India and beyond, while still delivering fresh data when it matters most.

next.jsverceledge middlewaredynamic routingcaching strategyserverless functionsnode.jsweb performance

Try it on your own server

Follow along on a Cloud VPS with full root access, or read the step-by-step knowledge base guides.

Guides: VPS for WordPress · Node.js hosting · VPS or dedicated server · Paying by UPI