Getting Real Prometheus Metrics Out of Nginx via OpenResty
How a team moved from nginx's four-metric stub_status to full Prometheus observability using OpenResty, solving cardinality and gauge/histogram tradeoffs.
Nginx's built-in stub_status endpoint reports just four numbers — active connections, accepts, handled, and requests — leaving teams blind to per-route latency or error breakdowns. Access logs exist, but they aren't metrics you can graph or alert on in real time.
The fix came through OpenResty, an nginx distribution that embeds Lua into the request lifecycle, discovered via the nginx-lua-prometheus project. After confirming OpenResty tracks upstream nginx closely and is proven at scale, the team swapped out stock nginx and began exporting Prometheus metrics directly from request-handling code.
The bulk of the real engineering work was taming cardinality. Raw request paths, client IPs, and Host headers each threatened to spawn unbounded time series. The fix: pattern-based sanitization that collapses UUIDs, numeric IDs, and hex tokens into a generic '$param' placeholder, subnet-level masking for IP addresses, and classification of Host values into a handful of buckets instead of raw strings.
For response-time tracking, the team chose gauges over histograms on low-traffic routes, since histogram-derived percentiles are unreliable with few samples and inflate storage costs. A gauge reports the literal duration of the last request — more honest for quiet endpoints, though it demands care since stale values persist silently until overwritten.