This guide explains how to set up Tusk Drift in your Next.js application.
Wrap your Next.js configuration with the withTuskDrift function in your next.config.js or next.config.ts file:
// next.config.js
const { withTuskDrift } = require("@use-tusk/drift-node-sdk/next");
module.exports = withTuskDrift({
// Your Next.js config
});// next.config.mjs
import { withTuskDrift } from "@use-tusk/drift-node-sdk/next";
export default withTuskDrift({
// Your Next.js config
});// next.config.js
const { withTuskDrift } = require("@use-tusk/drift-node-sdk/next");
module.exports = withTuskDrift(
{
// Your Next.js config
},
{
// Tusk Drift options
debug: true, // Enable debug logging
},
);// next.config.mjs
import { withTuskDrift } from "@use-tusk/drift-node-sdk/next";
export default withTuskDrift(
{
// Your Next.js config
},
{
// Tusk Drift options
debug: true, // Enable debug logging
},
);The withTuskDrift wrapper automatically:
- ✅ Enables the Next.js instrumentation hook (for Next.js < 15.0.0-rc.1)
- ✅ Configures webpack externals for proper module interception
- ✅ Detects your Next.js version and adjusts configuration accordingly
- ✅ Preserves your existing Next.js configuration
| Option | Type | Default | Description |
|---|---|---|---|
debug |
boolean |
false |
Enable debug logging to see what Tusk Drift is configuring during build. |
disableInstrumentationHook |
boolean |
false |
Disable automatic setting of experimental.instrumentationHook. Not recommended, will break Tusk Drift's Next.js integration. |
suppressWarnings |
boolean |
false |
Suppress all warnings from Tusk Drift's Next.js integration. |
Create an instrumentation.ts (or .js) file at the root of your Next.js project (or inside the src folder if using one):
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
const { TuskDrift } = await import("@use-tusk/drift-node-sdk");
TuskDrift.initialize({
apiKey: process.env.TUSK_API_KEY,
env: process.env.NODE_ENV,
logLevel: "debug",
});
// Mark app as ready immediately
TuskDrift.markAppAsReady();
}
}More context on setting up instrumentations for Next.js apps can be found here.
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
Required if using Tusk Cloud | Your Tusk Drift API key from the dashboard. |
env |
string |
process.env.NODE_ENV |
The environment name (e.g., 'dev', 'staging', 'production'). |
logLevel |
'silent' | 'error' | 'warn' | 'info' | 'debug' |
'info' |
The logging level for the Tusk Drift SDK. |
samplingRate |
number |
1.0 |
Override the base sampling rate (0.0 - 1.0) for recording. Takes precedence over TUSK_RECORDING_SAMPLING_RATE and config file base-rate settings. Does not change recording.sampling.mode. |
Update your package.json scripts:
{
"scripts": {
"dev": "next dev",
"dev:record": "TUSK_DRIFT_MODE=RECORD next dev"
}
}Sampling controls what percentage of inbound requests are recorded in RECORD mode.
Tusk Drift supports two sampling modes in .tusk/config.yaml:
fixed: record requests at a constant base rate.adaptive: start from a base rate and automatically shed load when queue pressure, export failures, export timeouts, event loop lag, or memory pressure indicate the SDK should back off. In severe conditions the SDK can temporarily pause recording entirely.
Sampling configuration is resolved in two layers:
- Base rate precedence (highest to lowest):
TuskDrift.initialize({ samplingRate: ... })TUSK_RECORDING_SAMPLING_RATE- legacy alias
TUSK_SAMPLING_RATE .tusk/config.yamlrecording.sampling.base_rate.tusk/config.yamllegacyrecording.sampling_rate- default base rate
1.0
- Mode and minimum rate:
recording.sampling.modecomes from.tusk/config.yamland defaults tofixedrecording.sampling.min_rateis only used inadaptivemode and defaults to0.001when omitted
Note: Requests before
TuskDrift.markAppAsReady()are always recorded. Sampling applies to normal inbound traffic after startup.
Set the base sampling rate directly in your initialization code:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
const { TuskDrift } = await import("@use-tusk/drift-node-sdk");
TuskDrift.initialize({
apiKey: process.env.TUSK_API_KEY,
env: process.env.NODE_ENV,
samplingRate: 0.1, // 10% of requests
});
TuskDrift.markAppAsReady();
}
}Set the TUSK_RECORDING_SAMPLING_RATE environment variable to override the base sampling rate:
# Development - record everything
TUSK_RECORDING_SAMPLING_RATE=1.0 npm run dev
# Production - sample 10% of requests
TUSK_RECORDING_SAMPLING_RATE=0.1 npm startTUSK_SAMPLING_RATE is still supported as a backward-compatible alias, but new setups should prefer TUSK_RECORDING_SAMPLING_RATE.
Use the nested recording.sampling config to choose fixed vs adaptive mode and set the base/minimum rates.
# ... existing configuration ...
recording:
sampling:
mode: fixed
base_rate: 0.1
export_spans: true
enable_env_var_recording: trueAdaptive sampling example:
# ... existing configuration ...
recording:
sampling:
mode: adaptive
base_rate: 0.25
min_rate: 0.01
export_spans: trueLegacy config still supported:
recording:
sampling_rate: 0.1| Option | Type | Default | Description |
|---|---|---|---|
sampling.mode |
"fixed" | "adaptive" |
"fixed" |
Selects constant sampling or adaptive load shedding. |
sampling.base_rate |
number |
1.0 |
The base sampling rate (0.0 - 1.0). This is the preferred config key and can be overridden by TUSK_RECORDING_SAMPLING_RATE or the samplingRate init parameter. |
sampling.min_rate |
number |
0.001 in adaptive mode |
The minimum steady-state sampling rate for adaptive mode. In critical conditions the SDK can still temporarily pause recording. |
sampling_rate |
number |
None |
Legacy fallback for the base sampling rate. Still supported for backward compatibility, but recording.sampling.base_rate is preferred. |
export_spans |
boolean |
false |
Whether to export spans to the Tusk backend. If false, spans are only saved locally in .tusk/traces. |
enable_env_var_recording |
boolean |
false |
Whether to record and replay environment variables. Recommended for accurate replay behavior if your app's logic depends on environment variables. |
If your packages aren't being instrumented:
-
Check file location: Ensure
instrumentation.tsis at the project root (same level asnext.config.js), not in theapporpagesdirectory. -
Check runtime guard: Make sure you have the
NEXT_RUNTIME === 'nodejs'check in yourregister()function. -
Enable debug logging: Set
debug: truein yourwithTuskDriftoptions to see what's being configured.