NGINX monitoring: connections, requests, latency and errors
Combine stub_status metrics, access log latency and status codes and OpenTelemetry traces to see how NGINX and the upstreams behind it serve every request.


Why monitor NGINX with Obseria
Golden signals at the edge
Request rate, error rate from status codes and latency from request_time give you an SLO-ready view of every virtual host.
Proxy versus upstream
upstream_response_time next to request_time shows whether time is spent in NGINX, on the network or in the backend service.
Requests you can follow
With the NGINX OpenTelemetry module, each proxied request becomes a span that continues into the upstream service trace.
NGINX components Obseria monitors
- stub_status. Accepted, handled and current connections by state, plus total requests, via the nginx receiver.
- Access logs. Status codes, bytes sent, request_time and upstream_response_time parsed from access logs.
- Error logs. Upstream timeouts, connection refusals and configuration errors from the NGINX error log.
- Upstreams. Latency and errors per upstream from access log fields and from traces of the backend services.
- Tracing. Spans for proxied requests from the ngx_otel_module with W3C trace context propagation.
- Kubernetes ingress. NGINX-based ingress controllers that expose Prometheus metrics, scraped by the Obseria Agent.
The NGINX signals that matter
Obseria collects these values automatically and shows them in ready-made dashboards and alerts.Traffic volume
Shows how many requests your website receives over time, helping you spot peaks, campaigns and unusual drops.
Connection reliability
Tells you whether every incoming visitor is actually served or whether connections are being dropped under load.
Current activity
Reveals how many visitors are being served right now and how many connections are idle or waiting.
Response speed
Shows how long visitors wait for a page and how much of that time is spent in your backend applications.
Show all 9 metrics in detail
| Metric | Unit | What it tells you |
|---|---|---|
nginx.requests | {requests} | Total client requests; its rate is the request throughput. |
nginx.connections_accepted | {connections} | Client connections accepted by NGINX. |
nginx.connections_handled | {connections} | Handled connections; lower than accepted means resource limits were hit. |
nginx.connections_current{state=active} | {connections} | Open client connections including idle keep-alive. |
nginx.connections_current{state=reading} | {connections} | Connections where NGINX is reading the request header. |
nginx.connections_current{state=writing} | {connections} | Connections where NGINX is writing the response; grows when upstreams are slow. |
nginx.connections_current{state=waiting} | {connections} | Idle keep-alive connections waiting for the next request. |
$request_time | s | Access log variable: total time to serve a request, from first byte read to last byte sent. |
$upstream_response_time | s | Access log variable: time spent waiting for the upstream response. |
Set up NGINX monitoring in minutes
- Step 1
Enable stub_status
Expose stub_status on a local-only location such as 127.0.0.1:8080/nginx_status and reload NGINX.
- Step 2
Configure metrics and logs
Add the nginx receiver and a filelog receiver for access logs to the OpenTelemetry Collector or Obseria Agent.
- Step 3
Add tracing
Load the NGINX OpenTelemetry module and point it at the local Collector, so proxied requests appear in traces.
receivers:
nginx:
endpoint: http://127.0.0.1:8080/nginx_status
collection_interval: 10s
filelog/nginx_access:
include: [/var/log/nginx/access.log]
start_at: end
exporters:
otlphttp:
endpoint: ${env:OBSERIA_OTLP_ENDPOINT}
headers:
Authorization: "Bearer ${env:OBSERIA_TOKEN}"
service:
pipelines:
metrics:
receivers: [nginx]
exporters: [otlphttp]
logs:
receivers: [filelog/nginx_access]
exporters: [otlphttp]
Out of the box
Dashboards, alerts and SLOs that are ready the moment data arrives.
- NGINX overview: requests, connections by state
- Status code breakdown and 5xx rate per host
- Request time versus upstream response time
- Alert: 5xx rate above 1% for 5 minutes
- Alert: handled connections lower than accepted
NGINX monitoring: what matters
Why NGINX monitoring matters
NGINX is the front door for many applications: web server, reverse proxy, load balancer and TLS terminator. Every user request passes through it, which makes it the best place to measure what users actually experience. It is also a frequent place where problems become visible first, as 502 and 504 responses, even when the cause lies in an upstream service. NGINX monitoring therefore has two jobs: watch NGINX itself, and use it as a vantage point on the services behind it.
Obseria collects NGINX metrics with the nginx receiver of the OpenTelemetry Collector, parses access and error logs with the filelog receiver, and receives spans from the NGINX OpenTelemetry module.
The NGINX metrics that matter
stub_status metrics
The open source stub_status module exposes a small but useful set of counters. nginx.requests gives request throughput. nginx.connections_accepted and nginx.connections_handled should grow at the same rate; if handled falls behind accepted, NGINX ran into a limit such as worker_connections. nginx.connections_current splits open connections into reading, writing and waiting. A growing number of writing connections usually means slow upstreams, because NGINX holds the connection while it waits for the response.
Enable it on a local-only listener:
server {
listen 127.0.0.1:8080;
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
}
Access log signals
Latency and errors come from the access log. Add $request_time and $upstream_response_time to your log format. The difference between both tells you whether time is spent in NGINX and the client connection or in the backend. Status codes give the error rate: 5xx for server-side failures, 499 for clients that gave up before a response arrived.
log_format timed '$remote_addr "$request" $status $body_bytes_sent '
'rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log timed;
Common problems and how to detect them
- 502 Bad Gateway: the upstream refused the connection or closed it. Check the error log for "connect() failed" and the health of the upstream service.
- 504 Gateway Timeout: the upstream did not answer within
proxy_read_timeout. Upstream response time approaching the timeout is the early warning. - Connection limits: handled connections lag accepted connections, or the error log reports "worker_connections are not enough".
- Rising 499s: clients cancel requests, often because of slow responses or aggressive client timeouts.
- TLS and certificate issues: handshake errors in the error log; combine them with synthetic checks that test certificate expiry.
Best practices for NGINX monitoring
- Keep stub_status on a local listener and never expose it publicly.
- Use a structured or key-value access log format with timing fields, so logs parse reliably.
- Define SLOs on request success rate and latency per virtual host or route, measured at NGINX.
- Propagate W3C trace context from NGINX to upstreams so a slow request can be followed end to end.
- Drop health check and static asset log lines in the pipeline if you do not need them, to control log volume.
How Obseria helps with NGINX monitoring
Obseria combines NGINX metrics, parsed access and error logs and traces in Obseria Lake. TopoGraph places NGINX in front of the services it proxies, so a 5xx spike points straight to the affected upstream. Obseria Intelligence correlates error and latency changes with deployments, upstream health and host metrics and explains the likely root cause with a chain of evidence. Obseria Pipeline can drop noisy log lines and mask IP addresses or query strings before storage, and filtered logs cost only ingestion. Dashboards, alerts and SLOs are included, and synthetic checks from 50+ locations add the outside view of your endpoints.
Start with stub_status and the access log on one host, add tracing for the routes that matter most, and roll the same Collector configuration out to every NGINX instance. Within a day you have request rate, error rate and latency per route, ready to turn into SLOs.
Related integrations
Related capabilities
Network Monitoring
Follow traffic between hosts, containers, clouds and data centers. Obseria shows latency, loss and errors on the network path and which services and users they affect.
Learn moreDistributed Tracing
Follow each request across services, queues and databases with OpenTelemetry-native distributed tracing, and find the slow span or failing dependency in seconds.
Learn moreSynthetic Monitoring
Test critical user flows and APIs around the clock from 50+ locations, and catch outages, slow responses and broken journeys before customers do.
Learn moreLearn more
The four golden signals: latency, traffic, errors and saturation
The four golden signals explained: latency, traffic, errors and saturation, how they relate to the RED and USE methods, and how to measure them with OTel.
What is an SLO (service level objective)?
What is an SLO? Learn how SLIs, SLOs, SLAs and error budgets work, how to calculate them, set targets and alert on burn rate, with examples.
NGINX monitoring FAQ
The OpenTelemetry nginx receiver reads stub_status: requests, accepted and handled connections and current connections by state. Latency and status codes come from access logs, and traces from the NGINX OpenTelemetry module.
No. stub_status, access logs and the OpenTelemetry module are all available for open source NGINX.
Add $request_time and $upstream_response_time to your access log format. Obseria parses them so you can chart percentiles per host, route and upstream.
Yes. The NGINX OpenTelemetry module creates spans for proxied requests and propagates W3C trace context to upstream services, which continue the trace.
Yes. Run the Obseria Agent as a DaemonSet to collect container logs and scrape metrics. NGINX-based ingress controllers that expose Prometheus metrics are scraped as well.
Start monitoring NGINX today
Connect NGINX in minutes with OpenTelemetry or the Obseria Agent. Free for 14 days.