Cloud & Infrastructure · Observability
Error Tracking in 2026: What Sentry Catches That Your Logs Don't
Logs tell you what happened. Error tracking tells you what broke, in what context, for which users. Here's how to set up Sentry properly and avoid the alert fatigue that makes it useless.
Anurag Verma
6 min read
Sponsored
Your logs tell you that something happened. An error tracking system tells you what broke, where in the code, who it affected, how many times, and what the user was doing when it happened. They’re not the same thing, and running one without the other leaves gaps.
Sentry is the most widely deployed error tracking platform for web applications. This is a practical setup guide — what to instrument, what to skip, and how to avoid the noise that makes most teams stop looking at their error dashboard within a month.
The Setup
For a Next.js app:
npm install @sentry/nextjs
npx @sentry/wizard@latest -i nextjs
The wizard creates sentry.client.config.ts, sentry.server.config.ts, and sentry.edge.config.ts. It also wraps your next.config.js. For new projects, run the wizard. For existing projects, be careful about the config merge — check what it writes before committing.
Minimal client config:
// sentry.client.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 0.1, // 10% of transactions for performance monitoring
replaysSessionSampleRate: 0.05, // 5% of sessions recorded
replaysOnErrorSampleRate: 1.0, // 100% of sessions that contain an error
integrations: [
Sentry.replayIntegration({
maskAllText: true, // mask PII in session replays
blockAllMedia: false,
}),
],
});
The tracesSampleRate deserves attention. At high traffic, 100% tracing generates significant data volume and cost. 10% is a reasonable default for most apps. If you care more about detecting latency regressions than individual traces, 5% is fine. If you’re debugging a specific slow path, bump it to 100% temporarily and bring it back down.
Source Maps
Without source maps, your stack traces show minified production code. Line 1, column 47832 doesn’t help anyone debug.
Sentry uploads source maps during the build via the Next.js plugin:
// next.config.ts
import { withSentryConfig } from "@sentry/nextjs";
export default withSentryConfig(nextConfig, {
org: "your-org",
project: "your-project",
silent: true,
widenClientFileUpload: true,
hideSourceMaps: true, // don't serve maps to the browser
disableLogger: true,
});
Set SENTRY_AUTH_TOKEN in your CI environment. Maps upload automatically during next build. They’re stored on Sentry’s servers for symbolicating stack traces, not exposed in your deployed bundle.
Capturing the Right Errors
Sentry automatically captures unhandled exceptions and unhandled promise rejections. What it doesn’t do automatically: capture handled errors you decide to track, add user context, or distinguish between “expected and recoverable” and “something is wrong.”
For explicit error capture with context:
import * as Sentry from "@sentry/nextjs";
async function createPayment(userId: string, amount: number) {
try {
const result = await stripe.charges.create({ amount, currency: "usd" });
return result;
} catch (error) {
Sentry.captureException(error, {
extra: {
userId,
amount,
stripeVersion: stripe.VERSION,
},
tags: {
feature: "payments",
severity: "high",
},
});
throw error; // re-throw so the caller handles it
}
}
Adding user context globally so every error includes who it affected:
// In your auth middleware or session setup
Sentry.setUser({
id: session.userId,
email: session.email,
});
For React error boundaries:
import * as Sentry from "@sentry/nextjs";
export function ComponentWithBoundary({ children }: { children: React.ReactNode }) {
return (
<Sentry.ErrorBoundary
fallback={<div>Something went wrong. We've been notified.</div>}
beforeCapture={(scope) => {
scope.setTag("component", "ComponentWithBoundary");
}}
>
{children}
</Sentry.ErrorBoundary>
);
}
Avoiding Alert Fatigue
The reason most teams stop checking their error dashboards: they alert on every error and get buried in noise from expected, unactionable events — bot traffic, crawlers hitting 404s, users typing invalid URLs, browser extensions throwing errors on your pages.
Filter them out at the source:
Sentry.init({
// ...
beforeSend(event, hint) {
const error = hint.originalException;
if (error instanceof Error) {
// Known browser noise — not your bugs
if (error.message.includes("ResizeObserver loop limit exceeded")) return null;
if (error.message.includes("Non-Error promise rejection")) return null;
if (error.message.includes("Loading chunk")) return null;
}
// Skip crawler traffic
const ua = event.request?.headers?.["user-agent"] ?? "";
if (ua.includes("Googlebot") || ua.includes("bingbot")) return null;
return event;
},
});
At the alert level, create separate rules for different error rates. A 5% error rate on your payment flow deserves an immediate page. A 0.1% rate on your search page can wait for the morning standup.
Use Sentry’s issue grouping rules to collapse variants of the same underlying error into one issue. Without this, a spike in one error type produces dozens of separate issues with slightly different messages, all pointing to the same root cause.
Performance Monitoring
Sentry’s performance tab shows slowest transactions, P75 and P99 latency, and throughput. For Next.js, it automatically instruments page loads, API routes, and database queries for supported ORMs.
For manual spans around code you care about:
async function fetchUserData(userId: string) {
return Sentry.startSpan(
{ name: "fetchUserData", op: "db.query" },
async () => {
return db.query.users.findFirst({
where: eq(users.id, userId),
});
}
);
}
The span shows up in transaction traces, making it straightforward to see if a specific function is responsible for latency spikes — and exactly how often it’s called per request.
What Sentry Won’t Do
Error tracking is not a replacement for structured logging. Sentry captures exceptions and their context; it doesn’t capture “this request processed 47 items at 12:03:21.” For event-level logs, you need a log aggregation tool (Axiom, Datadog Logs, Loki, or CloudWatch depending on your stack).
It’s also not an uptime monitor. A server crash produces no Sentry errors if no requests are reaching the server to throw one. Pair Sentry with a basic uptime monitor (Checkly, UptimeRobot, or a simple health check pinger) so you catch the “site is down” case separately from the “site is up but throwing errors” case.
The combination that covers most applications up to mid-scale: Sentry for error tracking and session context, a log aggregator for structured events, and an uptime monitor for availability. You don’t need all three immediately, but you’ll want all three before you’re responsible for a production system that has real users depending on it.
Cost
Sentry’s free tier covers 5,000 errors per month, enough to validate the setup and get comfortable with the interface. After that, the Starter plan at $26/month covers 50,000 errors and 100,000 performance transactions, which works for most early-stage products. The Team plan at $80/month per project adds alerting rules and longer data retention.
If self-hosting is preferred, GlitchTip is an open source Sentry-compatible alternative. It accepts the same SDKs and supports most Sentry features. It requires operational overhead (you’re running the service), but eliminates usage-based billing and keeps error data in your own infrastructure.
Sponsored
More from this category
More from Cloud & Infrastructure
Cloudflare R2 vs AWS S3 in 2026: The Storage Decision for Developer Teams
Vendor Lock-in in 2026: What It Actually Costs and When to Stop Worrying About It
ClickHouse in 2026: Analytical Queries on Billions of Rows Without the Pain
Sponsored
Discussion
Join the conversation.
Comments are powered by GitHub Discussions. Sign in with your GitHub account to leave a comment.
Sponsored