#Next.js#Turbopack#Build Optimization#React#CI

Faster Builds with Next.js 16.3: Turbopack Persistent Cache and the Rust React Compiler

webhani·

Next.js 16.3 ships a Turbopack persistent build cache, in-session memory eviction, and a Rust port of the React Compiler. None of these are flashy new APIs — they target build time and dev-server memory, the parts that add up day after day. This post walks through the settings and where each one earns its place.

Turbopack's filesystem cache

Turbopack is an incremental bundler written in Rust that parallelizes work across cores and caches results down to the function level. From Next.js 16 onward, that cache can be persisted to the filesystem. The behavior splits between development and production builds:

  • experimental.turbopackFileSystemCacheForDev: for the dev server. Enabled by default.
  • experimental.turbopackFileSystemCacheForBuild: for production builds. Currently opt-in.

Previously Turbopack's cache lived only in-process, so restarting the dev server meant recomputing everything. The filesystem cache lets a restart — or a series of builds — reuse prior results, which makes the second and later startups noticeably faster.

Since the production build cache is opt-in, enable it explicitly in next.config.

// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    // Enable the filesystem cache for production builds (currently opt-in).
    turbopackFileSystemCacheForBuild: true,
  },
};
 
export default nextConfig;

Keep in mind these are experimental flags. Before adopting in production, verify the build artifacts behave as expected in a staging environment, and have a rollback path ready in case cache-related inconsistencies show up.

Memory eviction for long dev sessions

Because Turbopack caches at the function level, memory usage tends to climb the longer you develop. The memory eviction in 16.3 reclaims memory the compiler is holding during long-running dev sessions.

In practice, leaving the dev server up all day is common. What used to be handled by "it's feeling sluggish, let me restart" is now eased by eviction. You'll feel it most on large codebases and projects with a high module count.

The Rust React Compiler

The React Compiler automatically optimizes component re-renders, which lets you drop manual useMemo / useCallback in many places. In 16.3, a Rust port of that compiler is integrated into Turbopack.

The point isn't a behavior change — it's speed. Replacing the previously JavaScript-based compiler work with Rust lowers the compiler's share of the overall build pipeline. Since Turbopack itself is written in Rust, running on the same runtime is an added benefit.

Enabling it follows the same idea as the existing React Compiler — turn it on in next.config.

// next.config.mjs
const nextConfig = {
  // Enable the React Compiler. 16.3 uses the Rust port.
  reactCompiler: true,
};
 
export default nextConfig;

If you're introducing the React Compiler for the first time, existing code that violates the Rules of React (side effects during render, for example) may not get optimized, or may behave unexpectedly. Enable it gradually and use the ESLint plugin to surface violations first — that makes the migration smoother.

Wiring it into CI

These improvements pay off in CI even more than locally. To benefit from the persistent cache in CI, you need to preserve the cache directory between builds. On GitHub Actions, that means including Next.js's cache directory in actions/cache.

# Excerpt from a workflow (conceptual)
- name: Restore build cache
  uses: actions/cache@v4
  with:
    # Target the Next.js / Turbopack cache.
    path: |
      .next/cache
    key: nextjs-${{ hashFiles('package-lock.json') }}-${{ github.sha }}
    restore-keys: |
      nextjs-${{ hashFiles('package-lock.json') }}-

The critical part here is cache-key design. Make sure the cache updates reliably when dependencies or source change: keep a fallback via restore-keys, and include a changing value like the commit SHA in the exact-match key. A stale cache reused as-is leads to build inconsistencies that are hard to trace.

Where to start

You don't need to enable everything at once. We recommend this order:

  1. Start with the dev-time filesystem cache and memory eviction. Much of it is on by default, so the risk is low and the developer-experience win is obvious.
  2. Then the persistent cache in CI. Shorter build times translate directly into team-wide productivity. Validate the cache key carefully.
  3. The React Compiler last — introduce it gradually after checking your Rules of React compliance.

Anything that depends on experimental flags may change behavior across Next.js versions. Verify the behavior at adoption time, and make checking the release notes on upgrade part of your process.

Takeaways

The centerpiece of Next.js 16.3 isn't a new way to write code — it's making the build and dev underpinnings faster and lighter. Faster rebuilds from the filesystem cache, steadier long sessions from memory eviction, and lower overhead from the Rust React Compiler all shave time that accumulates in daily work. Start with the low-risk dev settings and expand into CI cache design from there.

At webhani, we help teams with Next.js frontend development and with optimizing build pipelines and CI. If your builds are slow or your CI is a bottleneck, get in touch.