In production, errors happen silently. A user hits a bug, gets frustrated, and leaves, and you never find out unless you have error tracking in place. Sentry is the industry standard tool for capturing, grouping, and alerting on runtimeWhat is runtime?The environment that runs your code after it's written. Some languages need a runtime installed on the machine; others (like Go) bake it into the binary. errors across your entire stack.
Think of Sentry like a flight recorder for your app. When something crashes, it captures everything: the stack traceWhat is stack trace?A list of function calls recorded at the moment an error occurs, showing exactly which functions were active and in what order., the browser version, the user's actions leading up to the error, and even the state of your variables. Without it, debugging production issues feels like investigating a plane crash with no black box.
Setting up Sentry
Installation and initialization
Install the Sentry SDKWhat is sdk?A pre-built library from a service provider that wraps their API into convenient functions you call in your code instead of writing raw HTTP requests. for your environment. For a Node.js backend:
npm install @sentry/node @sentry/tracingFor a React frontend:
npm install @sentry/react @sentry/tracingInitialize Sentry as early as possible in your app, before any other imports if you can manage it. The dsn is the only required field, but you should always set environment dynamically:
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
release: process.env.GIT_COMMIT_SHA,
tracesSampleRate: 0.1, // Trace 10% of requests in production
});Capturing errors manually
Sentry captures unhandled exceptions automatically, but you can also report errors explicitly when you catch and recover from them:
try {
await processPayment(order);
} catch (err) {
Sentry.captureException(err, {
tags: { section: 'checkout' },
extra: { orderId: order.id, amount: order.total },
});
// Show a user-friendly error, but still report to Sentry
showErrorMessage('Payment failed. Please try again.');
}This is especially valuable when you catch an error intentionally, Sentry won't see it unless you tell it.
Enriching errors with context
Identifying users
Raw error reports are hard to act on. Knowing who experienced the error lets you reach out directly and understand impact:
// Call this after a user logs in
Sentry.setUser({
id: user.id,
email: user.email,
username: user.username,
});
// Clear on logout to avoid leaking identity
Sentry.setUser(null);Adding breadcrumbs
Breadcrumbs are automatic for most browser events (clicks, navigation, XHR requests), but you can add custom ones for important business events:
Sentry.addBreadcrumb({
category: 'checkout',
message: 'User applied discount code',
level: 'info',
data: { code: 'SAVE20', valid: true },
});When an error fires, you'll see exactly what the user did in the minutes before the crash. This is often more useful than the stack traceWhat is stack trace?A list of function calls recorded at the moment an error occurs, showing exactly which functions were active and in what order. itself.
Source maps for readable stack traces
Minified production code produces stack traces that look like a.b(c,d), completely useless. Source maps translate those back to your original TypeScript with real function names and line numbers.
Upload source maps as part of your build process:
# Using the Sentry CLI
npx @sentry/cli releases files "$RELEASE" upload-sourcemaps ./dist \
--url-prefix '~/'Or automate it with the Vite/webpack plugin:
// vite.config.ts
import { sentryVitePlugin } from '@sentry/vite-plugin';
export default {
plugins: [
sentryVitePlugin({
org: 'your-org',
project: 'your-project',
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
build: {
sourcemap: true, // Required - generate source maps
},
};Alerts and noise management
Setting up alert rules
Raw error volume is a poor signal. Configure Sentry alerts based on conditions that actually matter:
| Alert type | When to use | Example threshold |
|---|---|---|
| New issue | First time an error appears | Always alert |
| Regression | Error returns after being resolved | Always alert |
| Error spike | Volume increases sharply | 100% increase in 1 hour |
| High volume | Error affects many users | >50 users affected |
Ignoring expected errors
Not every error deserves your attention. Filter out noise with beforeSend:
Sentry.init({
dsn: process.env.SENTRY_DSN,
beforeSend(event, hint) {
const error = hint.originalException as Error;
// Ignore network errors that are out of your control
if (error?.message?.includes('Network request failed')) {
return null; // Drop the event
}
return event; // Send everything else
},
});Quick reference
| Concept | What it does | When to configure |
|---|---|---|
dsn | Identifies your Sentry project | Required, from environment variable |
environment | Tags errors by env | Set from NODE_ENV |
release | Tags errors by deploy | Set from git SHA or version |
tracesSampleRate | Controls performance tracing volume | 0.1–0.3 in production |
beforeSend | Filter/modify events before sending | To drop noise |
setUser() | Attach user identity to errors | After login |
captureException() | Manually report a caught error | In catch blocks |