Integration · Node.js

Node.js monitoring and APM

Load @opentelemetry/auto-instrumentations-node and Obseria shows traces, event loop delay, V8 heap and garbage collection for every Node.js service, linked to logs and infrastructure.
Obseria apps and capabilities: observability, APM, infrastructure and integrations
Obseria home dashboard with service health, open problems, SLO compliance and ingestion
Obseria trace explorer with span list and span attributes
Overview

Why monitor Node.js with Obseria

One require flag

The OpenTelemetry auto-instrumentations package covers HTTP, Express, Fastify, NestJS, gRPC, database drivers and AWS SDK calls via NODE_OPTIONS.

Event loop visibility

Event loop delay and utilization reveal blocking code that CPU charts alone cannot show.

Async traces that stay connected

Context propagation across promises and async/await keeps every downstream call in the right trace.

Coverage

Node.js frameworks and libraries Obseria monitors

  • Express, Fastify, Koa and Hapi. Routes and middleware appear as spans with route templates and status codes.
  • NestJS. Controllers and providers are traced through the underlying HTTP framework instrumentation.
  • HTTP, fetch and gRPC clients. Outbound calls propagate W3C trace context to services in any language.
  • PostgreSQL, MySQL, MongoDB and Redis drivers. Queries and commands become client spans with duration and target.
  • Kafka and AMQP clients. kafkajs and amqplib producers and consumers carry trace context across queues.
  • Logging libraries. Pino, Winston and Bunyan logs are enriched with trace and span IDs.
At a glance

The Node.js signals that matter

Obseria collects these values automatically and shows them in ready-made dashboards and alerts.

Response speed

Shows how quickly your Node.js services answer users, the most direct measure of how your product feels.

  • http.server.request.duration

Dependency speed

Tells you how long your application waits for other services and partners, revealing slow external dependencies.

  • http.client.request.duration

Application responsiveness

Reveals when the application is too busy to react promptly, causing every user request to wait in line.

  • nodejs.eventloop.delay.p99
  • nodejs.eventloop.delay.max
  • nodejs.eventloop.utilization

Memory health

Shows how much memory the application uses, how close it is to its limit and how long cleanups take.

  • v8js.memory.heap.used
  • v8js.memory.heap.limit
  • v8js.gc.duration
Show all 8 metrics in detail
MetricUnitWhat it tells you
http.server.request.durationsLatency of inbound HTTP requests per route and status code.
http.client.request.durationsLatency of outbound HTTP calls, to spot slow dependencies.
nodejs.eventloop.delay.p99s99th percentile event loop delay; high values mean blocking code.
nodejs.eventloop.delay.maxsLongest observed event loop delay in the interval.
nodejs.eventloop.utilization1Share of time the event loop was busy; near 1 means saturation.
v8js.memory.heap.usedByV8 heap in use per heap space; steady growth suggests a leak.
v8js.memory.heap.limitByHeap size limit, to compute utilization against --max-old-space-size.
v8js.gc.durationsGarbage collection duration by type (minor, major, incremental).
Setup

Set up Node.js monitoring in minutes

  1. Step 1

    Install the package

    Add @opentelemetry/api and @opentelemetry/auto-instrumentations-node to your project, or let the Obseria Agent handle Kubernetes workloads.

  2. Step 2

    Configure via environment

    Set OTEL_SERVICE_NAME, the Obseria OTLP endpoint, your token and the exporters as environment variables.

  3. Step 3

    Start with --require

    Register the instrumentation through NODE_OPTIONS before your app code loads, then start Node.js as usual.

Example configuration · BASH
npm install --save @opentelemetry/api @opentelemetry/auto-instrumentations-node

export OTEL_SERVICE_NAME="storefront-api"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=production"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="${OBSERIA_OTLP_ENDPOINT}"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20${OBSERIA_TOKEN}"
export OTEL_NODE_RESOURCE_DETECTORS="env,host,os,container"
export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"

node server.js

Out of the box

Dashboards, alerts and SLOs that are ready the moment data arrives.

  • Node.js runtime: event loop, heap, GC
  • Service health with RED metrics per route
  • Alert on event loop delay p99
  • Alert on heap usage near limit
  • Slowest outbound dependencies
Guide

Node.js monitoring: what matters

Why Node.js monitoring is different

Node.js runs JavaScript on a single main thread with an event loop. That model handles thousands of concurrent connections efficiently as long as no callback blocks the loop. One slow JSON parse, a synchronous crypto call or a large regular expression delays every other request on the same process. Node.js monitoring therefore needs more than CPU and memory charts: it has to show event loop health next to request traces.

The second challenge is asynchronous context. A single request fans out into promises, callbacks and timers. OpenTelemetry uses AsyncLocalStorage to keep the active span across these boundaries, so outbound HTTP calls and database queries land in the right trace. The package @opentelemetry/auto-instrumentations-node bundles instrumentations for the most common libraries and makes Node.js APM a matter of one flag.

Signals that matter for Node.js performance monitoring

  • Event loop delay: nodejs.eventloop.delay.p99 and nodejs.eventloop.delay.max measure how late timers fire. Values above a few milliseconds mean something blocks the loop.
  • Event loop utilization: nodejs.eventloop.utilization shows how busy the loop is. Close to 1, the process cannot take more work, even if host CPU looks fine.
  • V8 heap: v8js.memory.heap.used per heap space against v8js.memory.heap.limit. Hitting the limit ends with a fatal out-of-memory crash.
  • Garbage collection: v8js.gc.duration by type. Major collections pause JavaScript execution.
  • Requests and dependencies: http.server.request.duration and http.client.request.duration give latency, throughput and errors per route and per downstream service.

Common Node.js problems and how to detect them

Blocking the event loop

Synchronous file access, heavy JSON serialization or CPU-bound loops stall every concurrent request. The pattern is clear: event loop delay spikes, latency rises for all routes at once, and CPU on one core is pegged. CPU profiles show the exact function responsible.

Memory leaks

Closures that capture large objects, growing in-memory caches and listeners that are never removed keep the heap growing until the process crashes and restarts. Track heap used over days and correlate restarts with heap limit events.

Unhandled promise rejections

Rejected promises without a handler can terminate the process or silently drop work. Error tracking groups these exceptions by stack trace so you see new error types right after a deployment.

Slow or saturated dependencies

Connection pools for PostgreSQL or Redis that are too small make requests wait. Client spans show both the waiting time and the query duration, so you know whether to tune the pool or the query.

Crash loops in containers

When a Node.js process runs out of heap or throws an uncaught exception, the orchestrator restarts it. Short-lived pods hide the error unless logs and traces are shipped before the process exits. Restart counts from Kubernetes next to heap usage and error spans reveal the pattern.

Best practices for Node.js APM

  1. Load the instrumentation before any other module, ideally with --require or --import through NODE_OPTIONS.
  2. Disable instrumentations you do not need, for example file system spans, to reduce noise and overhead.
  3. Alert on event loop delay p99 and heap utilization, not only on response time.
  4. Set --max-old-space-size explicitly in containers so the heap limit matches the memory limit.
  5. Inject trace IDs into Pino or Winston logs to jump from a log line to the full trace.

How Obseria helps with Node.js monitoring

Obseria ingests the OpenTelemetry output of your Node.js services over OTLP, so instrumentation stays vendor-neutral and portable. The Obseria Agent adds host and container context and runs as a DaemonSet on Kubernetes. TopoGraph maps each service to its databases, caches, queues and callers. Continuous profiling with under 1% overhead points to the function that blocks the event loop. When latency rises after a release, Obseria Intelligence correlates the deployment, event loop delay and a slow dependency and presents the root cause with its chain of evidence. Dashboards, alerts and SLOs are included at no extra cost.

Node.js monitoring FAQ

No. Registering @opentelemetry/auto-instrumentations-node through NODE_OPTIONS instruments supported libraries automatically. Custom spans with the OpenTelemetry API are optional.

Yes, with current Node.js versions. ESM instrumentation requires the loader hook provided by OpenTelemetry; the documentation of the OpenTelemetry JavaScript project describes the required --import setup.

Express, Fastify, Koa, Hapi, NestJS and many database, messaging and cloud SDK clients are covered by the official instrumentation packages.

The runtime instrumentation included in the auto-instrumentations package reports event loop delay and utilization plus V8 heap and GC metrics. Obseria shows them on the Node.js runtime dashboard.

Yes. Use the OpenTelemetry Lambda layer for Node.js; traces and metrics flow to Obseria over OTLP alongside CloudWatch metrics from the agentless AWS integration.

Start monitoring Node.js today

Connect Node.js in minutes with OpenTelemetry or the Obseria Agent. Free for 14 days.