Prometheus Metrics: Counters, Gauges and Histograms

A
Author
18 Jul, 2026 1 min read 1.25K views

Prometheus is the most widely used open-source metrics system. Your app exposes current values on a /metrics endpoint, and Prometheus scrapes them every few seconds and stores them as time series.

The metric types

  • Counter - only goes up (resets on restart): requests served, errors, orders placed.
  • Gauge - goes up and down: queue length, active connections, memory in use.
  • Histogram - counts observations in buckets: request durations, payload sizes. Lets you compute percentiles.

Node.js with prom-client

import client from 'prom-client';

client.collectDefaultMetrics(); // CPU, memory, event loop lag, GC

const httpDuration = new client.Histogram({
  name: 'http_request_duration_seconds',
  help: 'HTTP request duration',
  labelNames: ['method', 'route', 'status'],
  buckets: [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
});

const ordersPlaced = new client.Counter({ name: 'orders_placed_total', help: 'Orders placed', labelNames: ['plan'] });

app.use((req, res, next) => {
  const end = httpDuration.startTimer();
  res.on('finish', () => end({ method: req.method, route: req.route?.path ?? 'unknown', status: res.statusCode }));
  next();
});

app.get('/metrics', async (req, res) => {
  res.type(client.register.contentType).send(await client.register.metrics());
});

Useful PromQL

# Requests per second, per route
sum by (route) (rate(http_request_duration_seconds_count[5m]))

# Error ratio
sum(rate(http_request_duration_seconds_count{status=~"5.."}[5m]))
  / sum(rate(http_request_duration_seconds_count[5m]))

# 95th percentile latency
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

Watch your labels

Every unique combination of label values is a separate time series. Labels like user_id, email or a raw URL with IDs (/orders/18342) create millions of series and can take down your metrics system. Use route templates (/orders/:id) and keep label values to small, fixed sets.

Naming conventions

  • Include the unit: _seconds, _bytes.
  • Counters end in _total.
  • Use base units (seconds, not milliseconds).
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.