Module A-13·25 min read

ELU as a first-class metric, clinic.js toolchain, V8 CPU profiles, core dump analysis, and distributed tracing across Kafka-connected services.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module 12 — Production Observability, Performance Profiling & Flame Graphs

What this module covers: A blockchain indexer at 50,000 events/second produces hundreds of thousands of function calls per second. When performance degrades, the cause is buried in microseconds — one function accounting for 40% of CPU, one allocation pattern triggering GC every 200ms, one async chain adding 15ms of hidden latency per request. Structured logs, Prometheus metrics, and distributed traces tell you that something is wrong. V8 CPU profiles, flame graphs, and the clinic.js toolchain tell you exactly where and why. This module covers the complete production diagnostic stack for Node.js systems under high-throughput stress.


The Three Pillars: Logs, Metrics, Traces

Every production Node.js service needs all three. They answer different questions:

  • Logs: what happened? (event-level detail)
  • Metrics: how is the system behaving over time? (aggregate measurements)
  • Traces: how does a single request flow through the system? (distributed causality)

Pino: The Fastest Structured Logger

javascript

Why Pino over Winston at high throughput: Pino's speed has nothing to do with offloading serialization to a worker thread — every logger.info() call still serializes synchronously on the main thread, same as Winston. The difference is how it serializes: Pino precompiles a serialization function per log shape ahead of time and writes the JSON string directly, avoiding the generic, reflection-heavy JSON.stringify() path that Winston goes through on every call. What genuinely can move off the main thread is the transport — the step that takes an already-serialized line and does something with it (pretty-printing via pino-pretty, writing to a file, shipping to a log aggregator over the network). pino.transport() runs that in a worker_threads worker so a slow write never blocks the event loop, but the log-line serialization itself is synchronous by design, not deferred. At 50K events/second where each event emits 2–3 log entries — 100K log statements/sec — that synchronous-serialization gap between Pino's precompiled path and Winston's JSON.stringify() path is what compounds into a measurable CPU difference at scale.

Prometheus Metrics with prom-client

javascript

Key metrics for a blockchain indexer:

MetricTypeAlert Condition
nodejs_event_loop_utilizationGauge> 0.85
nodejs_gc_duration_seconds (P99)Histogram> 50ms
transactions_ingested_total rateCounterDrop > 20%
transaction_processing_duration_seconds P99Histogram> 100ms
db_pool_utilization_ratioGauge> 0.9
nodejs_heap_used_bytesGauge> 80% of max

OpenTelemetry: Distributed Traces

javascript

With distributed tracing, a single block processing request shows its full latency breakdown across: HTTP receive → parse → signature verification (worker thread) → database write → Kafka publish. You can see exactly which step is slow without guessing.

Production story: Auto-instrumenting HTTP, pg, and Kafka via getNodeAutoInstrumentations() at 100% sampling looked harmless in staging. Turned on against the full 50K TPS ingestion pipeline, it overwhelmed the Jaeger collector within minutes — every single transaction was generating a full multi-span trace, and the collector wasn't sized to ingest that volume. The fix was tail-based sampling: buffer each trace briefly and only persist it if the request errored or exceeded 500ms. Fast, successful transactions — the overwhelming majority — are sampled out before they ever reach storage, while every failure and every slow outlier is kept. Sampling on the outcome (tail-based) instead of a fixed percentage decided up front (head-based) is what made tracing viable at this throughput.

Propagating Trace Context Across Kafka

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.