APM (application performance monitoring)
Production monitoring that shows which endpoint, function, or query is eating the time, not just that the app got slow.
See it
What it is
APM instruments your running server, usually with an agent or an OpenTelemetry SDK that wraps the HTTP framework, the ORM, the cache client, and outbound calls. What you get back is a per-endpoint breakdown (throughput, error rate, latency percentiles) plus a trace waterfall showing that GET /orders spends 40ms in your code and 900ms in one N+1 query. Datadog APM, New Relic, Sentry, Elastic APM, and Grafana Tempo all sell a version of this.
Reach for it when you know something is slow but not where. Auto-instrumentation gets you most of the way for free, then you add manual spans around your own hot paths and business operations. The 'A' is doing work in the name: APM watches your code, RUM watches the browser, uptime monitoring watches from outside. Most real incidents need at least two of the three to explain themselves.
Gotchas: agents are not free. They add startup time, memory, and a few percent of CPU, and full-fidelity tracing on a busy service costs serious money, so you will end up sampling. Traces of the average request are close to useless, so configure tail-based sampling and keep the slow and failing requests instead of a random 1%. Also watch your span names: putting an ID in the route label turns one endpoint into a million distinct ones and blows up the bill.
Ask AI for it
Add application performance monitoring to this backend service using OpenTelemetry. Install auto-instrumentation for the HTTP framework, the database driver or ORM, the cache client, and outbound HTTP, then add manual spans around the two or three slowest business operations. Set service name, environment, and release version as resource attributes, propagate traceparent headers to downstream services, and export over OTLP to a collector. Use tail-based sampling: keep 100% of traces that error or exceed 1s and 5% of the rest, and use parameterized route templates (/users/:id) as span names so cardinality stays bounded. Then build a per-endpoint view with throughput, error rate, and p50/p95/p99 latency that drills into the trace waterfall.