Skip to main content
The @sentry/node package provides error tracking and performance monitoring for Node.js applications using OpenTelemetry for automatic instrumentation.

Prerequisites

  • Node.js 18 or newer
  • A Sentry account and project DSN

Installation

1

Install the Package

Install @sentry/node using your preferred package manager:
npm install @sentry/node
Current Version: 10.42.0
2

Create Instrumentation File

Create a file named instrument.js (or instrument.mjs for ESM) that initializes Sentry. This file must be imported before any other modules:
// instrument.js
const Sentry = require('@sentry/node');

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing
  tracesSampleRate: 1.0,
});
You must call Sentry.init() before requiring/importing any other modules. This ensures that Sentry can automatically instrument all modules in your application.
3

Import Instrumentation in Your Application

Import the instrumentation file as the first import in your application:
// app.js
// Import this first!
require('./instrument');

// Now import other modules
const express = require('express');
const http = require('http');

// Your application code
const app = express();
// ...
4

ESM: Use --import Flag (Recommended)

For ESM applications, use Node.js’s --import flag to ensure Sentry loads before your application:
# Node.js 18.19.0 and newer
node --import ./instrument.mjs app.mjs
Or set it via environment variable:
NODE_OPTIONS="--import ./instrument.mjs" npm run start
Using --import ensures that Sentry is initialized before any application code runs, providing the most complete instrumentation.
5

Verify Installation

Test that Sentry is working:
import * as Sentry from '@sentry/node';

// This will create an error and send it to Sentry
Sentry.captureException(new Error('Test error'));

// Flush events before the application exits
await Sentry.flush(2000);
Check your Sentry dashboard to see the error.

Automatic Instrumentation

The Node.js SDK uses OpenTelemetry to automatically instrument popular frameworks and libraries:
  • HTTP/HTTPS: http, https, node-fetch, undici
  • Databases: PostgreSQL, MySQL, MySQL2, MongoDB, Mongoose, Redis, Prisma
  • Frameworks: Express, Fastify, Koa, Hapi, Connect, NestJS
  • GraphQL: GraphQL server instrumentation
  • Message Queues: Kafka, AMQP
  • Other: Knex, Tedious, Generic Pool, Dataloader
All automatic instrumentation happens when you call Sentry.init() before importing other modules. No additional configuration is required.

Framework Integrations

Express

import express from 'express';
import * as Sentry from '@sentry/node';

const app = express();

// Request handler must be the first middleware
app.use(Sentry.expressIntegration());

// Your routes
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// Error handler must be before any other error middleware
app.use(Sentry.expressErrorHandler());

// Optional fallthrough error handler
app.use((err, req, res, next) => {
  res.statusCode = 500;
  res.end('Internal Server Error');
});

app.listen(3000);

Fastify

import Fastify from 'fastify';
import * as Sentry from '@sentry/node';

const fastify = Fastify();

// Register Sentry plugin
await fastify.register(Sentry.fastifyIntegration());

// Set up error handler
await Sentry.setupFastifyErrorHandler(fastify);

fastify.get('/', async (request, reply) => {
  return { hello: 'world' };
});

fastify.listen({ port: 3000 });

Koa

import Koa from 'koa';
import * as Sentry from '@sentry/node';

const app = new Koa();

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  integrations: [Sentry.koaIntegration()],
});

app.use(Sentry.setupKoaErrorHandler(app));

app.use(async (ctx) => {
  ctx.body = 'Hello World';
});

app.listen(3000);

Hapi

import Hapi from '@hapi/hapi';
import * as Sentry from '@sentry/node';

const server = Hapi.server({
  port: 3000,
});

// Register Sentry plugin
await server.register(Sentry.hapiIntegration());
await Sentry.setupHapiErrorHandler(server);

server.route({
  method: 'GET',
  path: '/',
  handler: (request, h) => {
    return 'Hello World!';
  },
});

await server.start();

Database Integrations

Prisma

import { PrismaClient } from '@prisma/client';
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  integrations: [Sentry.prismaIntegration()],
});

const prisma = new PrismaClient();

MongoDB

import { MongoClient } from 'mongodb';
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  integrations: [Sentry.mongoIntegration()],
});

// MongoDB will be automatically instrumented
const client = new MongoClient(url);

PostgreSQL

import pg from 'pg';
import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  integrations: [Sentry.postgresIntegration()],
});

const client = new pg.Client();
await client.connect();

Usage

Capturing Errors

import * as Sentry from '@sentry/node';

try {
  someFunctionThatMightFail();
} catch (error) {
  Sentry.captureException(error);
}

Capturing Messages

import * as Sentry from '@sentry/node';

Sentry.captureMessage('Something went wrong!', 'warning');

Setting Context

import * as Sentry from '@sentry/node';

// Set user
Sentry.setUser({ 
  id: '123',
  email: '[email protected]' 
});

// Set tags
Sentry.setTag('service', 'api');
Sentry.setTag('environment', 'production');

// Set extra context
Sentry.setExtra('requestId', req.id);
Sentry.setContext('server', {
  hostname: os.hostname(),
  pid: process.pid,
});

Custom Spans

Create custom performance spans:
import * as Sentry from '@sentry/node';

const result = await Sentry.startSpan(
  {
    name: 'expensive-operation',
    op: 'function',
  },
  async () => {
    // Your expensive operation
    return await doSomethingExpensive();
  }
);

Cron Monitoring

Monitor scheduled jobs:
import * as Sentry from '@sentry/node';

const checkInId = Sentry.captureCheckIn({
  monitorSlug: 'daily-backup',
  status: 'in_progress',
});

try {
  await performBackup();
  
  Sentry.captureCheckIn({
    checkInId,
    monitorSlug: 'daily-backup',
    status: 'ok',
  });
} catch (error) {
  Sentry.captureCheckIn({
    checkInId,
    monitorSlug: 'daily-backup',
    status: 'error',
  });
}
Or use the withMonitor helper:
import * as Sentry from '@sentry/node';

const result = await Sentry.withMonitor(
  'daily-backup',
  async () => {
    return await performBackup();
  }
);

Advanced Configuration

Environment and Release

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  environment: process.env.NODE_ENV,
  release: process.env.RELEASE_VERSION,
});

Sampling

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  // Traces sampling
  tracesSampleRate: 0.2, // 20% of transactions
  
  // Or use dynamic sampling
  tracesSampler: (samplingContext) => {
    // Sample based on the context
    if (samplingContext.transactionContext.name.includes('/health')) {
      return 0; // Don't trace health checks
    }
    return 0.5; // 50% for everything else
  },
});

Filtering Events

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  beforeSend(event, hint) {
    // Don't send errors from specific modules
    if (event.exception?.values?.[0]?.stacktrace?.frames?.some(
      frame => frame.filename?.includes('node_modules')
    )) {
      return null;
    }
    return event;
  },
});

Integrations

import * as Sentry from '@sentry/node';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  integrations: [
    // HTTP instrumentation
    Sentry.httpIntegration(),
    
    // Database integrations
    Sentry.prismaIntegration(),
    Sentry.mongoIntegration(),
    Sentry.postgresIntegration(),
    
    // Framework integrations  
    Sentry.expressIntegration(),
    
    // Console integration
    Sentry.captureConsoleIntegration({
      levels: ['error'],
    }),
  ],
});

Troubleshooting

Missing Traces

If you’re not seeing traces:
  1. Ensure Sentry.init() is called before importing other modules
  2. Check that tracesSampleRate is set to a value greater than 0
  3. For ESM, use the --import flag

Duplicate Errors

If you’re seeing duplicate errors, make sure you’re not:
  • Calling Sentry.init() multiple times
  • Manually capturing errors that are automatically captured
  • Using multiple error handlers that both report to Sentry

Source Maps

For TypeScript or transpiled code:
  1. Enable source maps in your tsconfig.json:
    {
      "compilerOptions": {
        "sourceMap": true
      }
    }
    
  2. Use Sentry.rewriteFramesIntegration() to map stack traces:
    Sentry.init({
      dsn: 'YOUR_DSN_HERE',
      integrations: [
        Sentry.rewriteFramesIntegration({
          root: process.cwd(),
        }),
      ],
    });
    
Remember to flush events before your application exits, especially in serverless environments:
await Sentry.flush(2000);
process.exit();

Next Steps

Build docs developers (and LLMs) love