Setting Up Instrumentation in Next.js – Monitoring, Runtime Awareness, and Managing Side Effects

nextjs-instrumentation-monitoring-otel-runtime-side-effects

InstrumentationOpenTelemetryNEXT_RUNTIME

~2 min read • Updated Dec 13, 2025

Introduction


Instrumentation is the process of embedding monitoring and logging logic into your application. In Next.js, this enables you to track performance, debug production issues, and integrate with observability tools like OpenTelemetry.


Project Convention


To set up instrumentation, create a file named instrumentation.ts or instrumentation.js in the root of your project. If you're using a src folder, place it inside src alongside pages and app.

Export a register function from this file. It will be called once when a new Next.js server instance starts.


Example: Using OpenTelemetry


import { registerOTel } from '@vercel/otel'

export function register() {
  registerOTel('next-app')
}

This enables OpenTelemetry for your Next.js app with the name next-app.


Important Notes


  • The instrumentation file must be outside the app and pages directories
  • If you use the pageExtensions config option, update the filename accordingly

Importing Files with Side Effects


Sometimes you need to import a file for its side effects, such as setting global variables. We recommend importing these files inside the register function:

export async function register() {
  await import('package-with-side-effect')
}

This keeps all side effects localized and avoids unintended global imports.


Importing Runtime-Specific Code


Next.js calls register in all environments. To avoid runtime errors, conditionally import code based on the current runtime:

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('./instrumentation-node')
  }

  if (process.env.NEXT_RUNTIME === 'edge') {
    await import('./instrumentation-edge')
  }
}

This ensures that only compatible code is loaded in each runtime.


Conclusion


Instrumentation in Next.js provides a clean and extensible way to integrate monitoring tools. By using a centralized register function, managing side effects, and respecting runtime boundaries, you can build a robust observability layer for your application.


Written & researched by Dr. Shahin Siami