Consistent names let anyone guess a metric and its unit, and PromQL functions assume the conventions.
Prometheus does not enforce naming, but the ecosystem relies on a few conventions, and tools such as Grafana, promtool check metrics and the client libraries assume them.
A metric name has three parts: a prefix for the application or subsystem (http_, node_, myapp_), a description of what is measured, and a unit suffix. Use snake_case.
- Always use base units:
_seconds(not milliseconds),_bytes(not megabytes),_ratiofor 0 to 1 values (not percent),_celsius,_joules. Converting is the dashboard's job; mixed units in one query are a classic bug. - Counters end in
_total:http_requests_total. Histograms and summaries get_bucket,_sumand_countadded automatically, so the base name is justhttp_request_duration_seconds. - A metric should mean the same thing across all its label values. Don't put bytes sent and bytes received under one name with a
directionlabel unless summing them makes sense; do use labels for dimensions you will aggregate over. - Info metrics carry labels and the constant value 1:
app_build_info{version="2.3.1", go_version="1.24"}. Join them onto other series when you need the labels. - Don't repeat labels in the name:
http_requests_get_totalshould behttp_requests_total{method="GET"}.
Label names are snake_case too; job, instance and the __ prefix are reserved. Since Prometheus 3.0 any UTF-8 string is technically allowed in names (useful for OpenTelemetry data), but the conventions above are still what everyone expects.
Example
# Good
http_requests_total{method="GET",code="200"} # counter, _total
http_request_duration_seconds_bucket{le="0.25"} # histogram in seconds
process_resident_memory_bytes # gauge in bytes
queue_backlog_ratio # 0..1, not percent
myapp_build_info{version="2.3.1"} 1 # info metric
# Bad
requestsGET # no prefix, label baked into the name
http_latency_ms # not a base unit
cpu_percent # use a ratio and multiply by 100 in Grafana
errors # counter without _total, no namespace
# promtool can lint an exposition page:
# curl -s localhost:8000/metrics | promtool check metricsRemember
- prefix + what + base unit, in snake_case
- Counters end in _total; histograms get _bucket/_sum/_count for free
- Dimensions go in labels, not in the name; info metrics have value 1
Watch out for
- Exposing latency in milliseconds alongside other metrics in seconds, then mixing them in one query.