Next.js 16 makes Turbopack the default bundler for production builds. It replaces webpack entirely. To migrate, you upgrade to React 19 and Node.js 20, convert sync request APIs to async ones, rewrite custom webpack config under the new turbopack key, and test third-party packages that hook into webpack internals. Most standard Next.js apps can finish the upgrade in under a week.

Key takeaways

  • Turbopack is now the default bundler for both dev and production builds in Next.js 16. React 19 plus Node.js 20 are the new minimum requirements.
  • Any webpack key in next.config.js must move to the new turbopack config format. Some webpack plugins have no direct match yet.
  • Sync access to cookies(), headers(), params, and searchParams is fully removed. Every request API is async only now.
  • Turbopack's stricter module resolution and finer tree shaking usually produce smaller client bundles and faster incremental builds. The size of the gain depends on project structure and cache state.
  • Teams with heavy custom webpack plugin use, or dependencies still stuck on React 18, should weigh the migration cost before upgrading.

Updated 15 August 2026: sources added, experience claims checked against our project record, summary added.

Next.js 16 Turbopack Production Builds: What Changed and How to Migrate

Why Next.js 16 Is a Big Deal

Next.js 16 is not just a version bump. It's the biggest change to the build system since the framework moved from the Pages Router to the App Router. The main change is simple: Turbopack replaces webpack as the default bundler for both dev and production builds.

Next.js 16 also ships with other changes covered in the official upgrade guide:

  • React 19 as the minimum supported version. React 18 support is gone.
  • Better streaming and partial prerendering.
  • New caching defaults built to fix feedback about the Next.js 15 caching model.
  • Async request APIs fully enforced. cookies(), headers(), and params are all async now, with no old sync support.
  • Node.js 20 as the minimum requirement. Node 18 support is gone.

For agencies doing Next.js development, a release like this touches nearly every part of a build pipeline. Bumping the version number alone will not get you through it.

What Actually Changed with Turbopack in Production

Let's get specific. During Next.js 14 and 15, Turbopack was available for next dev behind the --turbo flag, while production builds still used webpack. Next.js 15.3 added an experimental --turbopack flag for next build. By the time Next.js 16 shipped, Turbopack had become the default for both. The Turbopack API reference covers the full rollout timeline.

Here is what's really different about how Turbopack handles production builds compared to webpack.

Incremental Compilation Architecture

Webpack processes the whole dependency graph on every build. Turbopack uses a function-level caching system built on its Rust engine, so later builds only recompile what changed. The first build on a machine may not feel much faster, but later builds usually do.

Tree Shaking Improvements

Turbopack's tree shaking works at a finer level than webpack's. In production Next.js builds, this usually makes client bundles smaller with no code changes. The biggest gains often come from barrel file handling, since Turbopack is better at cutting unused re-exports from index files.

Module Resolution

Turbopack resolves modules differently: faster, but stricter. Import paths that webpack silently allowed, like missing file extensions or case issues that only show up on Linux, tend to become hard errors under Turbopack. Cleaning these up before you migrate cuts down on build failures on day one.

Code Splitting Strategy

The chunk-splitting method is new. Turbopack makes more, smaller chunks by default. This usually helps load times for modern browsers on HTTP/2, though it can raise the total number of requests per page.

SWC Is Now Mandatory

Any leftover Babel config stops working. Turbopack only uses SWC for transformation. Next.js was already heading this way, but Next.js 16 drops the Babel fallback for good.

Build Performance Benchmarks

Published numbers for any bundler swap depend heavily on project size, route count, and how much of a build can come from cache. Treat single numbers you see online as a rough guide, not a promise for your own codebase. The table below shows the direction of change most teams should expect. The Turbopack documentation covers the caching design behind it.

Metric Typical Turbopack Impact vs Webpack
Cold build time Faster, more noticeable as route count grows
Warm/cached build time Substantially faster, due to function-level caching
Bundle size Slightly smaller on average, from finer-grained tree shaking
Build memory usage Lower, reducing OOM risk on constrained CI runners
Chunk count Higher, with more numerous smaller chunks

For content-heavy sites built on a headless CMS with thousands of static pages, cached incremental builds usually show the biggest gain, since Turbopack skips reprocessing routes that haven't changed. Lower peak memory use during builds also cuts the risk of out-of-memory failures on tight CI runners, a common problem with webpack on larger projects.

Next.js 16 Turbopack Production Builds: What Changed and How to Migrate - architecture

Breaking Changes You Need to Know

Here is a running list of what tends to break during a Turbopack migration. The Next.js 16 upgrade guide covers most of these, but a few catch teams off guard.

1. Custom Webpack Configuration

This is the big one. If you have a webpack key in your next.config.js, it no longer works. Turbopack has its own config API under a turbopack key in the Next.js config, and not everything maps one to one.

// next.config.js -- BEFORE (Next.js 15 with webpack)
module.exports = {
  webpack: (config) => {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });
    return config;
  },
};
// next.config.js -- AFTER (Next.js 16 with Turbopack)
module.exports = {
  turbopack: {
    rules: {
      '*.svg': {
        loaders: ['@svgr/webpack'],
        as: '*.js',
      },
    },
  },
};

2. Synchronous Request APIs Removed

Next.js 15 marked sync access to cookies(), headers(), params, and searchParams as deprecated. Next.js 16 removes them for good. If you ignored those warnings, expect build failures.

// BEFORE -- this crashes in Next.js 16
export default function Page({ params }) {
  const { slug } = params;
  return <div>{slug}</div>;
}

// AFTER
export default async function Page({ params }) {
  const { slug } = await params;
  return <div>{slug}</div>;
}

This kind of change can touch many components in bigger codebases. The official Next.js codemod, covered below, handles much of the mechanical rewrite.

3. React 18 No Longer Supported

Next.js 16 requires React 19. Dependencies pinned to React 18 need an update first. Most well-kept libraries added React 19 support well before Next.js 16 shipped, though a few small packages lagged behind.

4. Node.js 18 Dropped

The minimum is now Node.js 20. Update Docker images, CI configs, and .nvmrc files to match.

5. next/image Changes

The onLoadingComplete prop, deprecated since Next.js 14, is fully removed in the next/image API. Use onLoad instead. The image optimization pipeline also uses a new library under the hood, so cached optimized images regenerate on first request after you upgrade.

Our Migration Process Step by Step

A practical migration keeps the React and Next.js upgrades apart from each other. This makes debugging much easier than doing both at once.

Step 1: Audit Dependencies

Before touching Next.js, check every dependency for React 19 and Node.js 20 support:

npx npm-check-updates --target latest --filter '/react|next/'

Pay close attention to your CMS SDK, auth library, and any UI component library, since these often pin specific React versions.

Step 2: Update Node.js

Update .nvmrc to the current Node.js 20 LTS release, update Dockerfiles, and check CI runners are on a matching version. Simple, but easy to forget.

Step 3: Upgrade React First

npm install react@19 react-dom@19 @types/react@19 @types/react-dom@19

Run the full test suite here, before touching Next.js. React 19 has its own breaking changes (forwardRef is no longer needed in most cases, ref is now a normal prop, and the use() hook is stable). Fixing those issues on their own avoids debugging React and Next.js problems at the same time.

Step 4: Run the Next.js Codemod

Next.js offers an upgrade codemod that handles much of the mechanical work:

npx @next/codemod@latest upgrade

It automates a large share of the async API changes, though it can struggle with complex server component patterns and still needs a manual check afterward.

Step 5: Upgrade Next.js

npm install next@16

Step 6: Migrate next.config.js

This step often takes the longest for codebases with heavy webpack customization. The next section covers common translations.

Step 7: Fix Build Errors Iteratively

Run next build and fix errors one at a time. Turbopack's error messages tend to be clearer than webpack's, with more exact file paths and suggested fixes.

Step 8: Visual Regression Testing

Playwright-based visual regression suites catch rendering changes caused by a bundler switch. Common issues include CSS ordering differences (Turbopack processes CSS imports in a slightly different order than webpack) and dynamic imports that stop splitting code correctly.

Step 9: Performance Validation

Compare Lighthouse scores and Core Web Vitals before and after the migration to confirm there's no drop in real-world performance.

Webpack Config Translations

This section is for teams with custom webpack configs. Here's how common patterns translate to Turbopack.

Custom Loaders

// Turbopack equivalent for custom loaders
module.exports = {
  turbopack: {
    rules: {
      '*.md': {
        loaders: ['raw-loader'],
        as: '*.js',
      },
      '*.graphql': {
        loaders: ['graphql-tag/loader'],
        as: '*.js',
      },
    },
  },
};

Module Aliases

// Resolve aliases work similarly
module.exports = {
  turbopack: {
    resolveAlias: {
      'old-package': 'new-package',
      // You can also point to local files
      '@legacy/utils': './src/utils/legacy.ts',
    },
  },
};

What Doesn't Translate

Some webpack plugins have no Turbopack match yet:

  • webpack.DefinePlugin. Use env in next.config.js or plain environment variables.
  • BundleAnalyzerPlugin. The @next/bundle-analyzer package works with Turbopack, but the output format has changed.
  • Custom chunk splitting via splitChunks. Turbopack handles this on its own and doesn't offer the same level of control. The defaults work fine for most projects.
  • webpack.IgnorePlugin. Use resolveAlias to point imports to empty modules.

Handling Third-Party Packages

A few package types often cause trouble during migration:

@sentry/nextjs needs a recent major version for Turbopack support, since older versions hooked into webpack internals directly. Check the package changelog before you upgrade Next.js.

next-intl usually works fine after an update to the latest version. The plugin API fits Turbopack cleanly.

@vanilla-extract/next-plugin lacked a Turbopack match for a while after Turbopack became the default bundler. Teams that rely on it should wait for an updated release or look at alternatives like CSS Modules.

Barrel file packages, any package exporting hundreds of components from one index file, icon libraries especially, get tree-shaken much harder under Turbopack. This is usually a good thing, but a dynamically referenced icon can sometimes get dropped when using string-based lookups. Switching to direct imports fixes it and is better practice regardless of bundler.

CSS and Tailwind Considerations

If you use Tailwind CSS, the migration is mostly smooth, and Tailwind v4 works well with Turbopack. A few things need a closer look.

CSS Import Ordering

Turbopack processes CSS imports in a set order that differs from webpack's. If your specificity depends on import order (it shouldn't, but it often does in practice), visual changes can show up. A common symptom: a global CSS reset overriding a component-level CSS module because import order flipped.

The fix is explicit @layer use in your CSS, which is good practice no matter which bundler you use.

CSS Modules

CSS Modules work the same way under Turbopack. No changes needed. Generated class names look different (shorter), but that's just cosmetic unless you target generated class names in tests.

PostCSS

PostCSS config files still work. Your postcss.config.js continues to work with no changes needed.

Deployment and CI Pipeline Updates

Common deploy targets are Vercel and AWS via OpenNext. Here's what changes on each.

Vercel: Detects Next.js 16 on its own and uses Turbopack, with build cache support working right away. Because Vercel's build infrastructure links closely with Turbopack's caching layer, build times on Vercel usually drop more than in a generic CI setup.

AWS/OpenNext: Needs an OpenNext release that supports Turbopack output. Check the project's release notes before you upgrade. The .next output folder structure has changed, so any post-build scripts that reference specific file paths need an update.

Docker builds: If you build Next.js in Docker, update your base image to Node 20 or later. Turbopack's cache folder (.next/cache/turbopack) should be part of your Docker layer caching plan with a dedicated COPY or cache-mount layer.

## Optimize Docker layer caching for Turbopack
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
## Cache mount for Turbopack
RUN --mount=type=cache,target=/app/.next/cache \
    npm run build

When You Should Not Migrate Yet

This migration has trade-offs. There are good reasons to stay on Next.js 15 for now:

  • Heavy webpack plugin use: If your build relies on several custom webpack plugins with no Turbopack match, the migration cost may not be worth it yet.
  • Monorepo with shared webpack config: If webpack config is shared across Next.js and non-Next.js projects in a monorepo, splitting that config out is extra work.
  • Stability needs: Point releases after 16.0 usually fix edge-case bugs. Teams that can't handle downtime should wait for one or two patch releases before migrating anything critical.
  • Old dependencies stuck on React 18: If a key dependency hasn't added React 19 support, you're blocked no matter how ready your own code is.

For teams doing headless CMS development, the migration is usually smoother, since CMS-driven sites tend to have simpler build setups.

FAQ

Is Turbopack stable enough for production in Next.js 16?

Yes, Turbopack is stable enough for most production workloads in Next.js 16. It spent years handling dev builds before becoming an experimental production option in Next.js 15.3, then the default in Next.js 16. Teams handling mission-critical traffic should still use the latest patch release rather than 16.0, since early point releases usually fix edge-case bugs.

Can I still use webpack with Next.js 16?

No. Next.js 16 ships with Turbopack as the only supported bundler, so webpack support goes away once you upgrade. Projects that still need webpack should stay on Next.js 15, which keeps getting security patches for a limited time. Check the Next.js releases page for the current end-of-support date.

How much faster is Turbopack compared to webpack for production builds?

There's no single number that fits every project. Cold builds tend to be faster than webpack, and warm or cached builds tend to be much faster, since Turbopack only recompiles changed code. The exact gain depends heavily on project size, route count, and how much of the build can come from cache.

Do I need to rewrite my next.config.js for Turbopack?

If you have custom webpack config in your next.config.js, yes, those blocks need to move into the turbopack config format. If you only use standard Next.js config options (images, redirects, rewrites, environment variables), those work the same. The migration effort matches how much custom webpack config you have.

Will my existing CI/CD pipeline work with Next.js 16?

Mostly yes. The main things to update are the Node.js version (minimum 20), any scripts that reference webpack-specific output files, and any caching setup that targets .next/cache/webpack. Cache .next/cache/turbopack instead. If you deploy to Vercel, this is handled for you.

Does Turbopack support all the same features as webpack in Next.js?

For Next.js-specific features, yes. App Router, Pages Router, API routes, middleware, ISR, SSG, and SSR all work under Turbopack. For custom webpack config, most common patterns have a Turbopack match, but some small plugins and highly custom chunk-splitting setups don't yet. Check the Turbopack documentation for your specific case.

Should I migrate to Next.js 16 or consider alternatives like Astro?

It depends on your use case. Next.js 16 suits highly interactive apps with complex state management, and the Turbopack gains make local dev noticeably faster. Content-heavy sites with little interactivity often do better on Astro, which uses partial hydration to ship less JavaScript by default. We've built production sites on both stacks, including a Next.js migration for SleepDr.com and an Astro rebuild for bdManagedIT, and we pick the framework based on project needs. If you're unsure, reach out to us and we can help you decide.

What's the minimum time needed to migrate a medium-sized Next.js 15 app to 16?

A typical medium-sized migration, roughly 50 to 200 routes with standard dependencies and little custom webpack config, usually takes a few days of focused dev time. That covers dependency updates, async API changes, testing, and deployment checks. Projects with heavy custom webpack config or dependencies still tied to React 18 can take much longer. Our team at Social Animal offers migration services if you'd rather not spend your own sprint on infrastructure work.