How do I enable Sentry performance monitoring (tracing) for a Node.js API and set sampling so costs don’t blow up?
Application Observability

How do I enable Sentry performance monitoring (tracing) for a Node.js API and set sampling so costs don’t blow up?

9 min read

Most Node.js teams hit the same wall: you know you need better visibility into slow endpoints and downstream calls, but you don’t want tracing volume to quietly eat your budget. The good news is Sentry’s Node SDK gives you control over how much performance data you send, so you can trace what matters without costs blowing up.

Quick Answer: Sentry performance monitoring for a Node.js API is enabled by installing and initializing the Sentry Node SDK with tracing integrations, then configuring tracesSampleRate or tracesSampler to control how many transactions you send. Start low (for example, 0.1) and use dynamic sampling rules to prioritize critical endpoints or environments.

The Quick Overview

  • What It Is: Sentry’s performance monitoring (tracing) for Node.js captures transactions and spans across your API—requests, DB calls, external services—then links them to errors, logs, and releases so you can see exactly where code is slow or broken.
  • Who It Is For: Backend and full‑stack developers running Node.js APIs (Express, Fastify, NestJS, custom servers) who want code-level performance insight without turning on “trace everything forever.”
  • Core Problem Solved: It connects “this API is slow” to specific lines of code, queries, and deploys, while giving you sampling controls so your telemetry volume—and cost—stays predictable.

How It Works

At a high level, Sentry’s Node SDK instruments your API to send performance events:

  • A transaction = one unit of work (for example, an HTTP request like GET /api/users).
  • A span = an operation within that transaction (for example, a Postgres query, Redis call, or HTTP call to another service).

You initialize Sentry in your Node app with tracing enabled, and the SDK automatically instruments supported frameworks (like Express) and libraries (HTTP, database clients). You then configure sampling:

  • tracesSampleRate for a simple, fixed fraction of transactions.
  • tracesSampler for custom logic (per route, environment, user, or anything else).

That way you can trace enough to debug, but not so much that your quota disappears on low-value traffic.

Here’s the flow:

  1. SDK Setup & Basic Tracing: Install @sentry/node (and optionally @sentry/profiling-node), initialize it with your DSN and tracing options, and wrap your app/server so Sentry can create transactions for incoming requests.
  2. Sampling Strategy: Start with a conservative global tracesSampleRate, then move to tracesSampler once you know which endpoints and environments deserve more or less sampling.
  3. Debugging & Iteration: Use Sentry’s Performance views, Discover queries, and alerts to spot slow endpoints, see spans (DB, HTTP, etc.), correlate with errors and releases, then refine your sampling to prioritize the highest-value traffic.

1. SDK Setup & Basic Tracing for Node.js

Assuming an Express-based API (the same ideas apply to other frameworks):

npm install --save @sentry/node @sentry/profiling-node

Initialize Sentry as early as possible in your app (for example, sentry.js or at the top of app.js):

// sentry.js
const Sentry = require("@sentry/node");
const { ProfilingIntegration } = require("@sentry/profiling-node");

Sentry.init({
  dsn: process.env.SENTRY_DSN,

  // Start with a conservative sample rate; tune later
  tracesSampleRate: 0.1, // 10% of transactions

  // Optional: Profiling (Node 16+)
  integrations: [
    new ProfilingIntegration(),
  ],

  // Tag environment so you can filter (dev/staging/prod)
  environment: process.env.NODE_ENV || "development",

  // Identify releases to tie performance to deployments
  release: process.env.SENTRY_RELEASE, // e.g. "my-api@1.2.3"
});

module.exports = Sentry;

Wire Sentry into your Express app:

// app.js
const express = require("express");
const Sentry = require("./sentry");

const app = express();

// Request handler creates a transaction for each incoming request
app.use(Sentry.Handlers.requestHandler());
// Tracing handler creates spans for supported operations
app.use(Sentry.Handlers.tracingHandler());

app.get("/api/users", async (req, res, next) => {
  try {
    // Your logic here (DB calls, HTTP calls, etc.)
    res.json({ ok: true });
  } catch (err) {
    next(err);
  }
});

// Error handler must come after all routes
app.use(Sentry.Handlers.errorHandler());

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

module.exports = app;

Start your server as usual, and Sentry will begin sending both errors and performance transactions to your project.

2. Sampling Strategy to Control Cost

You control volume with two key options in Sentry.init:

tracesSampleRate (simple)

This is a number between 0.0 and 1.0 representing the fraction of all transactions you want to keep.

Examples:

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 0.05, // 5% of all transactions
});
  • Pros: Simple, predictable, and easy to reason about.
  • Cons: Treats all traffic equally—your health-checks get the same sampling as your checkout endpoint.

For many teams, starting with 0.05–0.2 in production is a safe middle ground.

tracesSampler (fine-grained control)

tracesSampler lets you decide at runtime whether to keep or drop a transaction. It receives a context object and returns a number between 0.0 and 1.0 for that specific transaction.

Basic example:

Sentry.init({
  dsn: process.env.SENTRY_DSN,

  tracesSampler: (samplingContext) => {
    const { request, transactionContext } = samplingContext;

    const env = process.env.NODE_ENV || "development";

    // 1. Always sample in development (you’re debugging here)
    if (env === "development") {
      return 1.0;
    }

    // 2. Sample more for staging to validate changes before prod
    if (env === "staging") {
      return 0.5; // 50%
    }

    // 3. Production: prioritize critical endpoints
    const name = transactionContext.name || request?.url || "";

    // Higher sample rate for critical paths
    if (name.includes("POST /api/checkout")) {
      return 0.5; // keep 50%
    }

    if (name.includes("GET /api/users")) {
      return 0.2; // keep 20%
    }

    // Downsample routine or noisy endpoints
    if (name.includes("GET /health") || name.includes("/metrics")) {
      return 0.0; // don’t keep these
    }

    // Default for everything else
    return 0.05; // 5%
  },
});

This is where you prevent cost surprises:

  • Always-on insight where it matters: checkout, auth, key APIs get higher sampling.
  • Aggressive downsampling for noisy/low-value traffic: health checks, internal tools, cron endpoints.
  • Environment-aware: full sampling in dev, higher in staging, conservative in prod.

You can evolve this over time based on what you see in Sentry.

3. Debugging & Iteration

Once data starts flowing:

  • Use Performance to see slow transactions, P95/P99 latency, and throughput for your Node.js endpoints.
  • Drill into a transaction to inspect spans: DB queries, external HTTP calls, and middleware, all tied back to your code.
  • Link from a slow transaction to errors, Session Replay (if you’re capturing frontend behavior), and releases, so you can see which deploy introduced the regression.
  • Set alerts so when latency for, say, POST /api/checkout crosses your threshold, your team is notified in Slack or your issue tracker.

When you start seeing patterns (“this endpoint is stable, that one is noisy”), refine your tracesSampler to push your sampling budget towards the problem areas.

Features & Benefits Breakdown

Core FeatureWhat It DoesPrimary Benefit
Node.js TracingCaptures transactions and spans for API requests, DB queries, and HTTP callsShows exactly where your Node.js API is slow or blocking
Configurable SamplingUses tracesSampleRate / tracesSampler to control transaction volumeKeeps performance visibility high while keeping costs in check
Code-Level Context & ReleasesEnriches events with stack traces, environment, and release informationConnects slowdowns to specific commits and deployments

Ideal Use Cases

  • Best for production Node.js APIs: Because it lets you trace real user traffic (not just synthetic benchmarks) and sample heavily on high-value endpoints while aggressively downsampling low-value noise.
  • Best for staging and pre‑prod performance testing: Because you can temporarily crank up sampling to 50–100% to validate new releases, then dial it back once changes hit production.

Limitations & Considerations

  • Sampling is probabilistic: There will always be some requests you don’t see. For rare, critical flows (like payment failures), consider higher sampling or even 100% sampling on those routes.
  • SDK defaults vs. custom spans: Automatic instrumentation covers a lot (Express, Node HTTP, common DB/HTTP libs), but you may want to add custom spans around complex business logic or third-party SDKs to get a complete picture.

Pricing & Plans

You can get started with Sentry’s free tier, which includes a baseline quota of errors and transactions. Performance usage is primarily driven by transaction volume, which you control via sampling (tracesSampleRate / tracesSampler), plus any add-on volumes you configure.

For details, check the pricing page, but in practice:

  • Set an initial global sample rate (for example, 0.05–0.1).

  • Monitor usage and headroom in Sentry.

  • Add a pay‑as‑you‑go budget or reserved volume as you get more confidence in what you need.

  • Developer Plan: Best for individual developers or small teams needing core error and performance monitoring with a limited number of dashboards and straightforward quotas.

  • Team / Business Plans: Best for teams needing higher volumes, longer retention, governance features (like SAML + SCIM on Business+), and more dashboards to track multiple services and environments.

Frequently Asked Questions

Do I need to trace 100% of my Node.js traffic to get useful performance data?

Short Answer: No. In most cases, sampling 5–20% of production traffic is enough to catch regressions and debug issues.

Details: Sentry’s performance views and stats are calculated on the data you send, so as long as your sample is representative, you’ll see accurate trends (P95, P99, throughput, error rates). For very low‑volume or high‑risk endpoints (login, checkout, billing), use tracesSampler to give them a higher sampling rate, while keeping a lower rate for everything else. This keeps your costs predictable without losing critical signal.

How does Sentry performance monitoring affect my Node.js API’s latency?

Short Answer: Sentry is designed to keep overhead low, and performance monitoring should not materially impact request latency for typical usage.

Details: The Node SDK is engineered to batch and send events efficiently and to keep instrumentation lightweight. Most teams run Sentry in production without noticing any user-facing slowdown. If you’re concerned, you can:

  • Start with a lower sample rate in production and measure.
  • Use Sentry’s own tracing data to measure the request handler overhead.
  • Adjust integrations or sampling if you see unexpected overhead.

If you’re building a genuinely latency‑sensitive system (sub‑millisecond paths, for example), you can restrict tracing to less critical endpoints or environments.

Summary

Enabling Sentry performance monitoring for a Node.js API is straightforward: install the Node SDK, initialize it with tracing enabled, and wire it into your framework. The real leverage comes from sampling:

  • Start with a conservative tracesSampleRate in production.
  • Use tracesSampler to prioritize business‑critical endpoints and environments.
  • Watch your transaction volume and refine your rules as you learn where your API actually struggles.

You end up with the tracing data you need—slow endpoints, bad queries, problematic releases—without letting telemetry quietly blow up your budget.

Next Step

Get Started