Observe vs other APMs
The best APM for a NestJS app depends on your stack: how Observe compares with Sentry, Datadog, New Relic, Elastic APM and OpenTelemetry, and when each fits better.
There's no single best APM for every NestJS application. The right one depends on how much of your system is Nest, what you already run, and what you need to see besides the application itself. This page shows how NestJS Observe compares with Sentry, Datadog, New Relic, Elastic APM and OpenTelemetry, when each of them is the better pick, and how Observe runs beside them.
For a setup-by-setup walkthrough of each tool in a Nest app, see Choosing an APM in the NestJS documentation.
The short answer
- NestJS Observe for the NestJS services in your system, whether that's all of your backend or part of it: traces in your own vocabulary (
OrdersService.create, notexpress.middleware) without running anything, joined through OpenTelemetry to the traces of services written in other languages. - Sentry if errors across a web or mobile frontend and a backend are the main concern.
- Datadog or New Relic if you want one platform for several languages and real infrastructure, and have the people to run it.
- Elastic APM if you already run the Elastic Stack, or the data has to stay on infrastructure you control.
- OpenTelemetry for the services that aren't Nest, or if you want one vendor-neutral standard across every service, Nest ones included.
These aren't exclusive. Observe works on its own, or beside the OpenTelemetry or platform APM you already have - see Using Observe beside another tool.
What Observe sees that a generic agent doesn't
APM agents patch libraries as they load - the HTTP server, the router, the database driver - so they see a Nest application from the outside: a route, then the queries under it. Observe is attached through the instrument option of NestFactory.create(), and Nest hands it every provider it creates. Each method call on a controller, service, repository, guard, interceptor or pipe becomes a span named the way you named it, so PricingService.quote is in the trace without anybody adding it.
Queue consumers, @Cron() handlers, GraphQL resolvers and WebSocket gateways are recorded as what they are, and a BullMQ or Bull job shares a trace with the request that enqueued it. Queries through pg, mysql2, mssql and mongodb - so TypeORM, Drizzle, MikroORM, Mongoose and Prisma's pg and SQL Server adapters - and outbound HTTP calls show up under the method that made them. See Traces & spans for what a waterfall looks like.
Setup is one command in your project, npx @nestjs/observe link, or the three edits in SDK → Quick start. There's no preload flag and nothing to run besides your app.
Observe and Sentry
Sentry is an error tracker first, with performance tracing built in. Its official @sentry/nestjs SDK is set up with an instrumentation file imported before anything else in main.ts, SentryModule.forRoot(), and SentryGlobalFilter. It creates spans for Nest's request pipeline - middleware, guards, pipes, interceptors, filters and route handlers - on top of HTTP and the common database drivers. Your service layer is yours to instrument. Sentry can also be self-hosted.
Pick Sentry when errors are the main concern, especially across a frontend and a backend. Pick Observe when the question you keep asking is which of your own classes is slow, or what a job did after the request that enqueued it. Observe records errors too, with a few lines of your source code around each in-app frame - see Traces & spans → Errors, with source code.
Observe and Datadog or New Relic
Datadog and New Relic are full platforms: APM, infrastructure, logs and browser monitoring across many languages.
- Datadog's tracer,
dd-trace, is preloaded with--require dd-trace/init(or--import dd-trace/initialize.mjsfor ES modules) and sends traces to a Datadog Agent you run next to your app. NestJS isn't among the web frameworks it lists, so you see Express or Fastify, outbound calls and a wide range of drivers, and BullMQ (5.66 and up). A community package,nestjs-ddtrace, can wrap your providers in spans. - New Relic's agent is preloaded with
-r newrelicand reports straight to New Relic.@nestjs/coreis on its list of instrumented modules (version 10 and up), which names transactions after your Nest routes. Your providers aren't spans unless you add them. The current agent needs Node.js 22.16 or later.
Pick a platform when you have more than one language and real infrastructure to watch next to the application. If you already run one, keep it for that, and add Observe for the Nest application layer: with the SDK's openTelemetry and otlp options, the Nest service joins the platform's traces and exports its spans to it over OTLP, down to its provider methods.
Observe and Elastic APM
The Elastic APM Node.js agent sends traces to an APM Server and on into Elasticsearch, where Kibana shows them. NestJS isn't in its list of supported frameworks: it instruments Express or Fastify underneath, so transactions are named after the route, and it records queries through pg, mysql2, mongodb and ioredis. Its ES module support is described in its own docs as experimental and covers a subset of modules, and Elastic now also suggests EDOT, its OpenTelemetry distribution.
Pick Elastic when you already run the Elastic Stack, or when the data has to stay on infrastructure you control. Observe is hosted only.
Observe and OpenTelemetry
OpenTelemetry is the vendor-neutral standard: instrument once, send to any backend that speaks OTLP. Its Nest instrumentation, @opentelemetry/instrumentation-nestjs-core, adds three kinds of span on NestJS 11 and earlier - application creation, the request context named Controller.method, and the route handler - and nothing for the providers underneath. Its current release (0.71.0) supports @nestjs/core below 12, so on NestJS 12 it adds no Nest spans at all.
Observe doesn't replace it. With the openTelemetry option, a Nest service running the SDK reads and sends W3C traceparent and joins the traces your other services share; with otlp (from @nestjs/observe 0.3.23), it also exports its spans to your OpenTelemetry backend. Observe doesn't ingest OTLP, so the other services' spans stay in that backend. See SDK → Running beside OpenTelemetry, and OpenTelemetry in the NestJS documentation for what each records.
Side by side
| NestJS Observe | Sentry | Datadog | New Relic | Elastic APM | |
|---|---|---|---|---|---|
| Setup | npx @nestjs/observe link, or one module and one option |
Instrument file imported first, module, filter | --require dd-trace/init, plus a Datadog Agent |
-r newrelic and a license key |
-r elastic-apm-node/start.js, plus APM Server and Elasticsearch |
| Recognises Nest itself | Built for it | Pipeline spans (guards, pipes, interceptors, filters, handlers) | Not listed | @nestjs/core 10+ listed |
Not listed |
| Your own providers as spans, automatically | Yes | No | Community package (nestjs-ddtrace) |
No | No |
| BullMQ jobs | Yes, linked to the enqueuing request | Check for your setup | Supported (5.66+) | Not listed | Not listed |
| Something to run besides the app | Nothing | Nothing (or self-host) | Datadog Agent | Nothing | APM Server, Elasticsearch, Kibana (or Elastic Cloud) |
| Self-hostable | No | Yes | No | No | Yes |
| Languages | NestJS; other languages share its traces via OpenTelemetry | Many | Many | Many | Many |
| Infrastructure monitoring | No | No | Yes | Yes | Yes |
Where Observe is the wrong pick
- Every service's spans in one product. Observe instruments NestJS services only, and doesn't ingest OTLP. Services in other languages share its traces through OpenTelemetry, so the whole trace is in your OpenTelemetry backend, with Observe's spans exported into it, while Observe shows the Nest services' part. If you need every service in a single product, that's a platform APM.
- Self-hosting. Observe is hosted only, on AWS in us-east-1 - see Security & data.
- Infrastructure. Observe reports each Node.js process's CPU, memory, event loop and garbage collection on its Profiler, not hosts, containers or the database server.
- Frontends. There's no browser or mobile SDK.
- Older stacks. The SDK needs
@nestjs/core11.1.4 or later and Node.js 20.19 or later, with Express or Fastify.
Pricing
Observe meters Observability Events: one per request, job run, error, log entry or trace span. Free includes 300k events a month with 3 days of retention, Pro is $29 a month for 25M events and 30 days, and Scale is $99 a month for 200M events and 90 days - see Billing & usage for what each plan includes and how overage works.
We don't quote the other tools' prices: per-host, per-seat, per-gigabyte and per-event models don't convert cleanly, and they change. Price your own traffic on each before you decide.
Using Observe beside another tool
- Beside OpenTelemetry: set
openTelemetryto join the traces your other services share, andotlpto export Observe's spans into the same backend. See SDK → Running beside OpenTelemetry. - Beside Datadog or New Relic: keep the platform for infrastructure and your other services, turn on
openTelemetry, and pointotlpat the platform's OTLP endpoint so the Nest service's provider spans land in its traces too. - Beside Sentry: keep Sentry on the frontend and add Observe to the Nest backend.
If you'd rather look before you install anything, the live demo is the whole dashboard over a busy service's data, with no signup.