Skip to content
C Codeloom
Next.js

Next.js Static Export vs Server: Picking the Right Output

Compare Next.js static export and server runtime modes. Understand when each shines, how features differ, and how to choose without painting yourself into a corner.

·4 min read · By Codeloom
Intermediate 9 min read

What you'll learn

  • The capability differences between output modes
  • How hosting cost scales for each
  • Which features force you to use a server
  • How to hybrid-render with ISR
  • Migrating between modes without rewriting

Prerequisites

  • Familiar with HTTP and JS
  • Some Next.js experience

What and Why

Next.js can produce two very different kinds of output. A static export (output: 'export') writes plain HTML, CSS, and JS files that any static host can serve. A server build keeps a Node.js process running to handle requests, render pages, and execute server actions. The choice has long-lasting consequences for cost, capabilities, and complexity.

This article gives you a clear decision framework so you do not pick wrong and have to migrate later under pressure.

Mental Model

Treat the two modes as different products that share a syntax. A static export is a deployment artifact; a server build is an application. Static is cheap, fast, and limited. Server is flexible, dynamic, and operationally heavier.

Most non-trivial apps end up server-rendered, but plenty of marketing sites, docs, and dashboards behind a login do beautifully as static exports.

Hands-on Example

Let us look at the same project under both modes.

Static export:
Browser -> CDN -> /about/index.html  (no compute)

Server build:
Browser -> CDN -> Node.js -> render React -> HTML
                        |
                        +-> DB / API / cookies
                        
ISR (hybrid):
Browser -> CDN -> cached HTML (until revalidate window)
                        |
                        +-> background regeneration
Request paths for static vs server output

Enable static export with one line:

// next.config.js
module.exports = { output: "export", images: { unoptimized: true } };

Run next build and you get an out/ directory you can ship to any static host: S3, Cloudflare Pages, GitHub Pages, even a USB stick.

The same project as a server build keeps output unset and is deployed to a Node-capable platform. Server features now work:

// app/dashboard/page.tsx
import { cookies } from "next/headers";

export default async function Dashboard() {
  const token = cookies().get("session")?.value;
  const data = await fetch("https://api.example.com/me", {
    headers: { Authorization: `Bearer ${token}` },
    cache: "no-store",
  }).then((r) => r.json());
  return <h1>Hello, {data.name}</h1>;
}

That page cannot exist in a static export. There is no server to read cookies, no server to call APIs with secrets, no server to render per request.

Feature comparison cheat sheet:

FeatureStatic exportServer build
getStaticProps / RSC fetchYesYes
cookies(), headers()NoYes
Server ActionsNoYes
API routesNoYes
ISR (revalidate)NoYes
Image optimizationNoYes
MiddlewareNoYes
Hosting cost~freeper-request

Common Pitfalls

  • Adopting static export and then needing one cookie-aware page. You either move to server or split into two deployments, both painful.
  • Assuming static is always faster. With a warm CDN, server-rendered ISR pages serve from the edge just as fast.
  • Forgetting that next/image needs the optimizer. In static mode you must set unoptimized: true and lose responsive variants.
  • Using dynamic = 'force-dynamic' in a static export project. Build fails with a confusing error about no compatible output.
  • Mixing client-side data fetching with claims of “static site”. The HTML is static, but the page is only useful once JS loads and hits an API, which is its own server.

Practical Tips

  • Default to a server build for product apps. The flexibility is worth the operational cost on day one.
  • Use static export for docs, landing pages, and tools that genuinely have no per-user state.
  • If cost matters, look at ISR before static export. You get most of the speed and keep the capabilities.
  • For static exports, host on a CDN that supports clean URLs and custom 404s. Otherwise you fight the platform.
  • Run next build in CI for both modes if you switch frequently. Some bugs only show up in one.
  • Keep server code (route handlers, Server Actions) in clearly named folders so it is obvious what breaks under static export.

Wrap-up

Static export and server builds are two different deployment targets that share a developer experience. Static is cheap and simple but capped in capability. Server is powerful but adds operational surface. The right choice depends less on personal preference and more on whether your pages depend on the current request. If they do, pick server. If they truly do not, enjoy the simplicity of a static export. And if you are unsure, server with ISR is a forgiving middle ground that scales in both directions.