Most tutorials still describe 2.x; knowing the breaking changes avoids silent query differences and failed upgrades.
Prometheus 3.0 (November 2024) was the first major release in seven years. The headline changes, continued in 3.1 to 3.5 (the 3.5 LTS release):
- UTF-8 names. Metric and label names may contain any UTF-8 characters. In PromQL and the exposition format quote them:
{"service.name"="api"}. The old restriction is kept for targets and clients that can't cope viaglobal.metric_name_validation_scheme: legacyand per-target escaping negotiated in theAcceptheader. - OTLP receiver. With
--web.enable-otlp-receiver, Prometheus accepts OpenTelemetry metrics on/api/v1/otlp/v1/metrics, so collectors and SDKs can push directly. Theotlp:config block controlstranslation_strategy(UnderscoreEscapingWithSuffixes, the default, rewriteshttp.server.durationtohttp_server_duration_seconds;NoUTF8EscapingWithSuffixeskeeps dots;NoTranslationkeeps the names untouched) andpromote_resource_attributesto turn chosen resource attributes such asservice.nameinto labels instead of leaving them intarget_info. - Left-open range selectors. A
[5m]window now excludes a sample exactly at its left edge, so a window holds a predictable number of samples;rateresults can differ slightly from 2.x. - Strict scrape protocols. Responses without
Content-Typefail unlessfallback_scrape_protocolis set;scrape_protocolsorders the negotiation. - New UI (React), with the old one gone in later 3.x;
--enable-feature=old-uiwas temporary. - Agent mode and the
@and negative-offset modifiers are no longer feature flags;holt_wintersbecamedouble_exponential_smoothingbehindpromql-experimental-functions; Remote Write 2.0 can be enabled per endpoint. - Removed flags and settings: deprecated
--storage.tsdb.retention, several--alertmanager.*and--storage.remote.*flags; check the release notes withpromtool check config.
Upgrading: go to 2.55 first, then 3.x; 3.x TSDB data can still be read by 2.55 if you must roll back. Regex matchers with . no longer match newlines in some edge cases, and alerts that relied on sample-at-edge behaviour may need their windows widened.
Example
# prometheus.yml additions for OpenTelemetry data
otlp:
promote_resource_attributes:
- service.name
- service.namespace
- k8s.pod.name
translation_strategy: UnderscoreEscapingWithSuffixes # or NoUTF8EscapingWithSuffixes
storage:
tsdb:
out_of_order_time_window: 30m # OTLP pushes may arrive late
# prometheus --config.file=prometheus.yml --web.enable-otlp-receiver
# OTel collector / SDK endpoint: http://prometheus:9090/api/v1/otlp
# PromQL after NoUTF8EscapingWithSuffixes (quoted UTF-8 names):
# histogram_quantile(0.9, sum by (le) (
# rate({"http.server.request.duration_seconds_bucket", "service.name"="api"}[5m])))
# Default strategy gives the classic form instead:
# http_server_request_duration_seconds_bucket{service_name="api"}Remember
- UTF-8 names with quoted syntax; legacy validation available
- --web.enable-otlp-receiver plus the otlp: block for OpenTelemetry push
- Left-open ranges and strict Content-Type can change behaviour
- Upgrade via 2.55; keep rollback possible
Watch out for
- Upgrading straight from an old 2.x release without passing through 2.55, which may not read the TSDB correctly.