Why You Need Sentry in Your Next.js Application
Production bugs are inevitable. The difference between a team that fixes issues in minutes and one that takes days often comes down to one thing: error tracking. If you are building with Next.js, integrating Sentry gives you real-time visibility into errors happening on both the client and server, complete with stack traces, breadcrumbs, and contextual data.
In this hands-on tutorial, we will walk through a complete Sentry Next.js setup from scratch. By the end, you will have full error monitoring across client-side rendering, server-side rendering, API routes, and edge functions, plus custom error boundaries and alert rules so your team never misses a critical issue.
Prerequisites
Before we start, make sure you have the following ready:
- A Next.js project (version 13.2 or higher; this guide uses Next.js 15+)
- Node.js 18 or later
- A Sentry account (free tier works fine)
- A Sentry project created and your DSN (Data Source Name) available

Step 1: Install the Sentry Next.js SDK
The fastest way to get started is by using the official Sentry wizard. Open your terminal in the root of your Next.js project and run:
npx @sentry/wizard@latest -i nextjs
The wizard will automatically:
- Install the
@sentry/nextjspackage - Create the required configuration files
- Set up source map uploads
- Optionally add example error buttons for testing
If you prefer a manual installation, run:
npm install @sentry/nextjs
or with Yarn:
yarn add @sentry/nextjs
Step 2: Configure Sentry
After installation, you need three configuration files in the root of your project. If the wizard created them, review and customize them. If you installed manually, create them now.
sentry.client.config.ts
This file initializes Sentry on the client side (browser).
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.replayIntegration(),
Sentry.browserTracingIntegration(),
],
environment: process.env.NODE_ENV,
});
sentry.server.config.ts
This file initializes Sentry on the server side (Node.js runtime).
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
});
sentry.edge.config.ts
If you use Next.js edge functions or middleware, create this file as well:
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
});
Summary of Configuration Files
| File | Purpose | Runtime |
|---|---|---|
| sentry.client.config.ts | Browser-side error and performance tracking | Browser |
| sentry.server.config.ts | Server-side error tracking (SSR, API routes) | Node.js |
| sentry.edge.config.ts | Edge runtime tracking (middleware, edge API) | Edge |
Step 3: Update next.config.js
Wrap your existing Next.js configuration with the withSentryConfig function. This is essential for source map uploads and proper build-time instrumentation.
import { withSentryConfig } from "@sentry/nextjs";
const nextConfig = {
// your existing Next.js config
};
export default withSentryConfig(nextConfig, {
org: "your-sentry-org",
project: "your-sentry-project",
silent: !process.env.CI,
widenClientFileUpload: true,
tunnelRoute: "/monitoring",
disableLogger: true,
automaticVercelMonitors: true,
});
Key Options Explained
- widenClientFileUpload: Uploads a broader set of client-side source files for better stack traces.
- tunnelRoute: Routes Sentry data through your own domain, which helps avoid ad blockers. More on this below.
- silent: Suppresses build logs outside of CI environments.
- disableLogger: Removes Sentry logger statements from your production bundle to reduce size.
Step 4: Set Up Environment Variables
Add the following to your .env.local file (and your deployment platform’s environment settings):
NEXT_PUBLIC_SENTRY_DSN=https://[email protected]/0
SENTRY_DSN=https://[email protected]/0
SENTRY_ORG=your-org-slug
SENTRY_PROJECT=your-project-slug
SENTRY_AUTH_TOKEN=your-auth-token
To generate your SENTRY_AUTH_TOKEN:
- Go to Settings > Auth Tokens in your Sentry dashboard
- Click Create New Token
- Select at minimum the
project:releasesandorg:readscopes - Copy the token and store it securely
Step 5: Configure Source Maps
Source maps are what turn minified production stack traces into readable code with exact file names and line numbers. Without them, debugging production errors is painful.
If you used withSentryConfig as shown above, source maps are automatically uploaded during your build process. To verify this is working:
- Run a production build:
npm run build - Check the build output for Sentry source map upload messages
- In the Sentry dashboard, go to Settings > Source Maps and confirm the artifacts are present
Important: Make sure your SENTRY_AUTH_TOKEN is available in your CI/CD environment. Without it, source maps will not upload.
Hiding Source Maps from Users
You probably do not want to expose your source maps publicly. Add this to your next.config.js:
const nextConfig = {
productionBrowserSourceMaps: false,
};
Sentry will still receive the source maps, but they will not be served to end users.
Step 6: Add Custom Error Boundaries
Next.js provides built-in error handling with the App Router’s error.tsx files. Sentry integrates with these seamlessly, but you should create a global error boundary to catch unhandled errors and report them properly.
Global Error Page (App Router)
Create or update app/global-error.tsx:
"use client";
import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
);
}
Route-Level Error Boundary
For more granular handling, add an error.tsx file inside any route segment:
"use client";
import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<div>
<p>An error occurred in this section.</p>
<button onClick={() => reset()}>Retry</button>
</div>
);
}
Capturing Errors Manually
In some cases, you want to report errors without crashing the UI. Use Sentry.captureException in try/catch blocks:
import * as Sentry from "@sentry/nextjs";
async function fetchData() {
try {
const res = await fetch("/api/data");
if (!res.ok) throw new Error("Failed to fetch data");
return await res.json();
} catch (error) {
Sentry.captureException(error);
return null;
}
}
Step 7: Track Server-Side and API Route Errors
One of the biggest advantages of the Sentry Next.js SDK is that it automatically instruments server-side rendering and API routes. However, you can enhance tracking by adding custom context.
API Route Example (App Router)
import { NextResponse } from "next/server";
import * as Sentry from "@sentry/nextjs";
export async function GET() {
try {
// your logic here
const data = await getDataFromDatabase();
return NextResponse.json(data);
} catch (error) {
Sentry.captureException(error, {
tags: { section: "api", route: "/api/data" },
});
return NextResponse.json(
{ error: "Internal Server Error" },
{ status: 500 }
);
}
}
Server Components
Errors in React Server Components are also captured automatically. For additional context, you can wrap logic with Sentry spans:
import * as Sentry from "@sentry/nextjs";
export default async function Page() {
return await Sentry.withServerActionInstrumentation(
"loadDashboardData",
async () => {
const data = await fetchDashboardData();
return <Dashboard data={data} />;
}
);
}
Step 8: Set Up the Sentry Tunnel (Bypass Ad Blockers)
Many ad blockers and browser privacy extensions block requests to Sentry’s ingestion endpoints. The tunnel route solves this by proxying Sentry events through your own domain.
If you added tunnelRoute: "/monitoring" in your withSentryConfig options, this is already active. All Sentry events will be sent to yourdomain.com/monitoring instead of directly to sentry.io, making them invisible to ad blockers.
No additional server code is needed. The SDK handles everything.
Step 9: Configure Alerts in Sentry
Catching errors is only half the battle. You need to know about them immediately. Here is how to set up alerts in the Sentry dashboard.
Creating an Alert Rule
- Navigate to Alerts > Create Alert in your Sentry project
- Choose Issues as the alert type
- Set conditions, for example:
- When a new issue is created
- When an issue is seen more than 10 times in 1 hour
- When an issue affects more than 5% of sessions
- Choose your notification channel: email, Slack, Microsoft Teams, PagerDuty, or webhooks
- Save the alert rule
Recommended Alert Configuration
| Alert Type | Trigger | Best For |
|---|---|---|
| New Issue | First occurrence of an error | Catching regressions immediately after deploys |
| Frequency | Error count exceeds threshold | Detecting spikes in recurring issues |
| Crash Rate | Session crash rate rises above X% | Monitoring overall app stability |
| Performance | Transaction duration exceeds threshold | Spotting slow pages or API endpoints |
Step 10: Verify Your Setup
Time to make sure everything works. Add a test button to any page in your application:
"use client";
export default function TestSentry() {
return (
<button
onClick={() => {
throw new Error("Sentry test error - client side");
}}
>
Trigger Test Error
</button>
);
}
- Click the button in your browser
- Open your Sentry dashboard
- You should see the error appear within seconds, complete with a stack trace pointing to your original source code
For server-side testing, create a test API route:
import { NextResponse } from "next/server";
export async function GET() {
throw new Error("Sentry test error - server side");
return NextResponse.json({ ok: true });
}
Visit the route in your browser and confirm the error shows up in Sentry with server-side context.
Troubleshooting Common Issues
Here are the problems developers run into most often with Sentry Next.js setup, and how to fix them:
Errors Not Appearing in Sentry
- Double-check your DSN is correct and the environment variable is loaded
- Make sure
Sentry.init()is called before any other code runs - Check browser dev tools for blocked network requests (ad blockers)
- Verify the tunnel route is configured if you suspect blocking
Source Maps Not Working
- Confirm
SENTRY_AUTH_TOKENis set in your build environment - Run
npm run buildand look for upload confirmation in the output - In Sentry, go to Settings > Source Maps and check that artifacts exist for the correct release
Build Errors After Adding Sentry
- Ensure you are using a compatible version of
@sentry/nextjsfor your Next.js version - If you are on Next.js 15 or later, use
@sentry/nextjsversion 8.x or higher - Check for conflicts with other Webpack plugins or custom configurations
Performance Impact Concerns
- Adjust
tracesSampleRateto a lower value (e.g., 0.2) in production to reduce overhead - Set
replaysSessionSampleRateto 0.1 or lower unless you specifically need session replays
Best Practices for Production
Once your Sentry Next.js setup is complete, follow these practices to get the most value:
- Tag errors with context: Add user IDs, feature flags, or route information using
Sentry.setTag()andSentry.setUser() - Use releases: Associate errors with specific deployments so you can track regressions per release
- Set up Slack or Teams integration: Get instant notifications for critical errors without checking the dashboard
- Review errors weekly: Triage and resolve issues regularly to keep your error feed manageable
- Customize fingerprinting: Group related errors together to avoid noise from the same underlying bug
- Use
beforeSend: Filter out known non-actionable errors before they count against your quota
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
beforeSend(event) {
// Filter out specific errors
if (event.exception?.values?.[0]?.value?.includes("ResizeObserver")) {
return null;
}
return event;
},
});
Conclusion
Setting up Sentry in a Next.js application gives your team a significant advantage when it comes to finding and fixing production issues. With client-side tracking, server-side instrumentation, source map integration, custom error boundaries, and alert rules all in place, you will catch problems before your users even report them.
The entire setup takes about 15 to 30 minutes, and the payoff is immediate. The next time something breaks in production, you will have the full error context, the exact line of code, and a timeline of events leading up to the failure.
At Box Software, we integrate Sentry into every Next.js project we build. If you need help setting up error tracking or improving the reliability of your web application, get in touch with our team.
Frequently Asked Questions
Is Sentry free to use with Next.js?
Yes. Sentry offers a free Developer plan that includes error tracking, performance monitoring, and session replays with generous monthly quotas. It is more than enough for small to medium projects. Paid plans are available for higher volumes and additional features.
What is the minimum Next.js version required for Sentry?
The @sentry/nextjs SDK currently requires Next.js 13.2 or higher. For the best experience with the App Router and Server Components, we recommend using Next.js 14 or 15.
Does Sentry slow down my Next.js application?
The performance impact is minimal. Sentry adds a small amount of JavaScript to your client bundle and runs asynchronously. You can further reduce overhead by lowering the tracesSampleRate and replaysSessionSampleRate in production.
Can I use Sentry with the Next.js Pages Router?
Absolutely. The @sentry/nextjs SDK supports both the App Router and the Pages Router. For the Pages Router, you would use the _error.tsx file for your custom error boundary instead of global-error.tsx.
How do I set up Sentry for Next.js on Vercel?
Add your SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_PROJECT, and NEXT_PUBLIC_SENTRY_DSN as environment variables in your Vercel project settings. The rest of the configuration stays the same. If you enabled automaticVercelMonitors in withSentryConfig, Sentry will also track your Vercel cron jobs.
What is a Sentry tunnel and do I need one?
A Sentry tunnel routes error data through your own domain instead of sending it directly to sentry.io. This prevents ad blockers from intercepting the requests. If your application has end users who might use ad blockers, enabling the tunnel is strongly recommended.
