Back to Blog Home

Contents

Share

Share on Twitter
Share on Bluesky
Share on HackerNews
Share on LinkedIn

Less code, faster builds, same telemetry: Turbopack support for the Next.js SDK

Sergiy Dybskiy image

Sergiy Dybskiy -

Less code, faster builds, same telemetry: Turbopack support for the Next.js SDK

Less code, faster builds, same telemetry: Turbopack support for the Next.js SDK

TL;DR - Turbopack became the default in Next.js, so we reworked our SDK to stop depending on bundlers. The result is less code, faster builds, and the same telemetry. This blog explains how we got there.

You know the feeling when you spend years building tooling that supports something and all of a sudden that something becomes deprecated and you have to rethink your full approach?

And no, this isn’t a post about Ralph Wiggum, the recursive agent practice that we all as a community decided was okay to name that way and roll with it.

This is about Next.js rolling out Turbopack, deprecating Webpack (as of Next.js v16 Turbopack is the default) and us rethinking our telemetry approach in the SDK.

What we were doing before

When you ran next build, our Webpack loader intercepted every page, API route, middleware, and server component. It would:

  1. Parse your file to determine its type

  2. Bundle it with a Sentry wrapper template using Rollup

  3. Replace your original code with the instrumented version

This worked. It also required maintaining six different wrapper templates, a 360-line webpack loader, and roughly 1,667 lines of instrumentation code. Every new Next.js feature — server components, route handlers, the App Router — meant writing another template and hoping Webpack's internals hadn't changed since last time we looked.

Click to Copy
// The old serverComponentWrapperTemplate.ts (simplified)
import * as serverComponentModule from '__SENTRY_WRAPPING_TARGET_FILE__';
import * as Sentry from '@sentry/nextjs';

const serverComponent = serverComponentModule.default;

export default new Proxy(serverComponent, {
  apply: (originalFunction, thisArg, args) => {
    return Sentry.wrapServerComponentWithSentry(originalFunction, {
      componentRoute: '__ROUTE__',
      // ... extract headers, trace context, etc.
    }).apply(thisArg, args);
  },
});

We were building a parallel universe where every file had a Sentry-wrapped doppelgänger. It's the kind of architecture that works until it doesn't, and when it doesn't, good luck figuring out which layer broke.

What we do now

Next.js has built-in OpenTelemetry instrumentation. It emits spans for every request, middleware execution, and render operation — complete with route information. Instead of wrapping your code, we listen.

Click to Copy
// The new approach (simplified)
client?.on('spanStart', span => {
  const spanAttributes = spanToJSON(span).data;

  if (spanAttributes?.[ATTR_NEXT_ROUTE]) {
    const route = spanAttributes[ATTR_NEXT_ROUTE];
    rootSpan.updateName(route);
    rootSpan.setAttribute(ATTR_HTTP_ROUTE, route);
  }
});

The snippet above is the clean version. In reality, we overwrite the standard Next.js OTel config with Sentry-specific parts (span processors, context manager, etc.) and customize our HTTP integration to disable incoming Next.js-generated spans so we can enrich them ourselves. Still simpler than six Rollup templates.

The Turbopack-specific code is about 164 lines. That's a 10x reduction from the Webpack approach, and most of those lines are config handling, not instrumentation logic.

What this actually means for your builds

Charly, an engineer on our Next.js SDK team, ran a test against the Sentry Changelog repo to see the difference:

The SDK no longer runs Rollup on every file in your application during compilation. If you've ever wondered why next build was taking a while, some of that was us. (Sorry.)

The SDK automatically detects whether you're using Turbopack or Webpack and adjusts. If you're on Next.js 15.4.1 or later, Turbopack just works. The tracing data you see in Sentry looks the same — route handlers, middleware, server components, data fetching. All still there.

What changes

Some Webpack configuration options no longer apply when using Turbopack:

Click to Copy
// These are no-ops with Turbopack
module.exports = withSentryConfig(nextConfig, {
  webpack: {
    autoInstrumentServerFunctions: true,  // Now handled via OTel
    autoInstrumentMiddleware: true,       // Now handled via OTel
    excludeServerRoutes: ['/api/health'], // No build-time wrapping to exclude from
  },
});

If you were excluding specific routes from instrumentation, you'll need to filter them via Sentry's beforeSendTransaction hook instead. The SDK relies on Next.js's OpenTelemetry instrumentation, so there's no build-time wrapping to opt out of.

Server Actions still require manual instrumentation:

Click to Copy
'use server';
import { withServerActionInstrumentation } from '@sentry/nextjs';

export async function submitForm(data: FormData) {
  return withServerActionInstrumentation('submitForm', async () => {
    // Your action code
  });
}

Server Actions don't emit OTel spans we can hook into. We're watching Next.js development here — if they expose the telemetry, we'll add automatic instrumentation.

Why this matters beyond our codebase

Instead of every APM vendor maintaining their own build plugins, loaders, and bundler integrations, frameworks are adopting OpenTelemetry as a standard telemetry interface. Next.js emits spans. We consume them. The framework handles the "how," we handle the "where it goes."

This is where framework instrumentation is heading. We just got there by deleting code instead of writing more of it.

Requirements

  • Next.js 15.4.1+ for Turbopack production builds

  • Next.js 15.6+ for native Debug IDs (improves source map resolution)

  • No changes to your instrumentation.ts or instrumentation-client.ts files

Next.js 16 makes Turbopack the default bundler and the SDK is ready for it.

The 15-month journey from "Turbopack: unsupported" to "Turbopack: default" involved 19 PRs, a complete architectural rethink, and the realization that the best way to support a new bundler was to stop depending on bundlers altogether.  That approach now powers our Next.js SDK.

Syntax.fm logo

Listen to the Syntax Podcast

Of course we sponsor a developer podcast. Check it out on your favorite listening platform.

Listen To Syntax
© 2026 • Sentry is a registered Trademark of Functional Software, Inc.