This episode covers production-grade observability: distributed tracing with OpenTelemetry, centralized logging and correlation IDs, monitoring metrics and alerts, plus incident response and troubleshooting practices in production.

In production, applications run without direct developer supervision. Observability is the ability to understand what's happening inside the system — through traces, logs, and metrics. Episode 22 covers production-grade observability for NestJS.
You'll learn to trace requests across all services, centralize logs, monitor metrics, and handle incidents.
When a request travels across many services, it's hard to track where time is wasted. Distributed tracing gives each request a unique id that follows it through every service, so the complete request path is visible in one dashboard.
OpenTelemetry is an observability standard supported by many vendors. Install the packages:
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-trace-otlp-httpimport { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();Auto-instrumentation captures traces for HTTP, databases, and libraries automatically — without changing business code. Just run the application with npm run start:dev and every request is recorded.
In a microservices architecture (episode 14), traces connect all services. OpenTelemetry propagates trace context through headers like traceparent, so a single request can be traced from the gateway down to the deepest service.
A correlation ID connects all logs belonging to one request. Create an interceptor that assigns a unique id:
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common";
import { Observable } from "rxjs";
import { randomUUID } from "crypto";
@Injectable()
export class CorrelationIdInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
const request = context.switchToHttp().getRequest();
const correlationId = request.headers["x-correlation-id"] ?? randomUUID();
request.headers["x-correlation-id"] = correlationId;
return next.handle();
}
}Every request gets an x-correlation-id that travels through all its logs — making it easy to trace one request from start to finish.
In distributed environments, logs are scattered across many instances. Centralized logging collects them in one place — for example ELK, Loki, or CloudWatch. With JSON output from Pino (episode 9) and correlation IDs, logs can be searched by request, service, or error level.
Metrics are numbers measured continuously — request rate, error rate, latency. Expose metrics using @willsoto/nestjs-prometheus (introduced in episode 9):
import { Injectable } from "@nestjs/common";
import { InjectMetric, makeCounterProvider } from "@willsoto/nestjs-prometheus";
@Injectable()
export class MetricsService {
constructor(
@InjectMetric("http_requests_total")
private readonly httpRequests: Counter,
) {}
countRequest(): void {
this.httpRequests.inc();
}
}Metrics are useless without alerts. Prometheus Alertmanager or cloud tools like CloudWatch Alarms trigger notifications when a metric crosses a threshold — for example an error rate above 1 percent or a spike in P95 latency. Alerts must be actionable: they should contain context and a link to the dashboard.
When an alert fires, follow a playbook: identify the impact, isolate the cause, apply a mitigation (which can be a rollback from episode 21), then do a postmortem. The goal isn't to find who's at fault, but to prevent recurrence.
The combination of the three observability pillars resolves almost every incident:
Start with traces to find the path, then logs for details, and metrics to confirm the time range of the event.
Episode 22 refines your application's observability: distributed tracing with OpenTelemetry, centralized logging with correlation IDs, monitoring metrics and alerts, plus incident response and troubleshooting.
Key takeaways:
In the final episode 23 we'll discuss stable modern features and future trends — the latest stable NestJS features, the Fastify GraphQL microservices and WebSockets ecosystem, backend development trends in Node.js and TypeScript, and strategies for keeping your skills relevant in the future.