Skip to main content
RunBook Academy

ObservabilityIII · Metrics FundamentalsMetric types

Counters, Gauges, Histograms, and Summaries

Foundation⏱ ~22 min

What you'll learn

  • Distinguish counter, gauge, histogram, summary
  • Pick the right metric type for a measurement
  • Read the data model `metric_name{label="value"} value`
  • Recognise what each metric type can and cannot answer

Prerequisites

Verified against Prometheus 2.55.x · Alertmanager 0.28.x · node_exporter 1.8.x · blackbox_exporter 0.26.x · Grafana 11.x · Loki 3.x · Tempo current · OpenTelemetry Collector 0.110.x · Grafana Alloy current · Docker Engine 28.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-13

Not yet marked complete on this device.

The Prometheus data model is simple: a numeric time series, identified by name and label set, carrying samples at points in time. The metric type — counter, gauge, histogram, summary — constrains what those samples mean and what query language (PromQL) can do with them.

This lesson introduces the four types with the operational decision: which type fits which measurement.

The data model

metric_name{label1="value1", label2="value2"}  value  timestamp

A unique combination of (metric_name, label1=value1, label2=value2, ...) is a time series. Every sample for that series is a single (value, timestamp) pair. A counter can have thousands of series, each carrying one integer per scrape.

Two example series:

http_requests_total{method=GET, route=/checkout, status=200}  4096
http_requests_total{method="POST",route="/checkout",status="500"}  3

Both series are the same metric name. They are different time series because their labels differ. They are stored independently. They can be aggregated together by PromQL.

Counters

A counter is a value that monotonically increases, except across a process restart where it resets to zero. Counters are optimised for rate() queries.

# An exposed example
http_requests_total{route="/checkout",status="200"}  4096

A raw counter has limited operational meaning — “we have served 4096 requests.” The operational meaning comes from the rate over time (rate()):

rate(http_requests_total{route="/checkout",status="200"}[5m])

That query returns “requests / second over the last 5 minutes,” which is the operational quantity.

Counters fit:

  • Request counts. http_requests_total{status="..."}
  • Bytes received. network_receive_bytes_total
  • Errors. http_requests_total{status="5xx"}

A counter is the right type for any “cumulative” quantity.

Gauges

A gauge is a value that can go up or down. Gauges are optimised for avg(), sum(), min(), max() aggregations.

node_memory_MemAvailable_bytes{instance="web01"}  4.5e9
node_load1{instance="web01"}  0.85

A gauge carries instantaneous state: “memory available is 4.5 GB right now”; “load-1 is 0.85 right now.” The state is sampled at scrape time.

Gauges fit:

  • Resource state. node_memory_MemAvailable_bytes, node_filesystem_avail_bytes, CPU temperature.
  • Queue depth. rabbitmq_queue_messages.
  • Active sessions. nginx_connections_active.

A counter’s value grows over time; a gauge’s value reports the current state.

Histograms

A histogram is a counter with bucket boundaries. It records how many observations fell within each bucket.

http_request_duration_seconds_bucket{le="0.005"}  24054
http_request_duration_seconds_bucket{le="0.01"}  33444
http_request_duration_seconds_bucket{le="0.025"}  100392
http_request_duration_seconds_bucket{le="+Inf"}  144320
http_request_duration_seconds_sum  53423
http_request_duration_seconds_count  144320

The buckets are cumulative: each le&#61;&#34;X&#34; is “the count of observations <= X seconds.” The _count field is the total number of observations. The _sum is the sum of observation values.

Histograms fit:

  • Latency. http_request_duration_seconds_bucket
  • Request size. http_request_size_bytes_bucket
  • Anything aggregate-by-quantile. histogram_quantile()

The histogram has a known operational cost: each bucket adds a time series. A histogram with 12 buckets and 10 labels adds 120 series. A histogram with native histograms (Prometheus 2.50+) compresses the bucket cost and is preferred where supported.

Summaries

A summary is a metric that computes quantiles at the source and exposes them as individual gauge samples.

http_request_duration_seconds{quantile="0.5"}  0.052
http_request_duration_seconds{quantile="0.9"}  0.180
http_request_duration_seconds{quantile="0.99"}  0.834
http_request_duration_seconds_sum  53423
http_request_duration_seconds_count  144320

The quantiles are computed inside the service. Quantiles cannot be aggregated across instances by histogram_quantile() in PromQL because the pre-aggregated quantiles do not preserve the distribution.

Summaries are useful when the application itself wants to report quantiles directly (e.g. a library has built-in quantile support). They are generally less flexible than histograms because you cannot aggregate across instances.

When to pick which

MeasurementTypeWhy
Request count over timecountercumulative
Bytes transmittedcountercumulative
Memory in usegaugeinstantaneous state
Active sessionsgaugeinstantaneous state
Request latencyhistogramaggregatable quantiles
Request sizehistogramaggregatable quantiles
Pre-computed quantilessummarywhen the library emits them

The default choice for a measurement is:

  • “Cumulative over time” → counter
  • “Instantaneous state” → gauge
  • “Distribution of observations” → histogram

A summary is reserved for cases where the source already computes quantiles — most Prometheus client libraries default to histograms because aggregatability is more important than pre-computation.

Reading a metric in PromQL

Three operations cover most PromQL queries against metric data:

  • rate(counter&#91;5m&#93;) — per-second rate over 5 minutes.
  • avg(gauge by (instance)) — average value per instance.
  • histogram_quantile(0.99, sum by (le) (rate(histogram&#91;5m&#93;))) — 99th percentile across instances.

PromQL is covered in production depth in Part XII.

Production guidance

  • Use counters for cumulative measurements; never reset them inside the service.
  • Use gauges for instantaneous state. Avoid aggregating across counters in a way that produces gauge-shaped numbers (use histogram_quantile instead).
  • Default to histograms for distribution-shaped measurements. Drop in native histograms where supported.
  • Use summaries only when the library emits them and you cannot switch to histograms.
  • Use recording rules to precompute repeated queries — particularly histogram quantiles and rate-based metrics.

Verification

You should be able to answer:

  • What are the four Prometheus metric types?
  • What is the data model metric_name&#123;label&#61;&#34;value&#34;&#125; value?
  • When do you pick a counter vs a gauge vs a histogram vs a summary?
  • Why are histograms preferred for latency?

Quiz

Knowledge check · 8 questions

  1. Q1. What is the primary purpose of counters, gauges, histograms, and summaries?

  2. Q2. Which failure mode of counters, gauges, histograms, and summaries is most operationally costly?

  3. Q3. Production verification should run on production hosts.

  4. Q4. First response when counters, gauges, histograms, and summaries misbehaves?

  5. Q5. Name one signal that confirms counters, gauges, histograms, and summaries is healthy.

  6. Q6. Which of these are validation steps?

  7. Q7. Right discipline when changing in production?

  8. Q8. Telemetry usefulness requires:

Passing score: 75%. Answers are checked in this browser.