...

NGINX Stub Status: Monitor Web Server Activity in Real Time

With NGINX Stub Status, you can monitor client connections and request counters via a secure HTTP endpoint. The values show the Connection and Query Activity, but no direct CPU, memory, or capacity utilization. Repeated queries reveal changes and allow for the calculation of an average query rate. For this, the module must be available in the NGINX build being used. For long-term trends and alerts, the status page can be supplemented with an exporter and Prometheus; both endpoints require appropriate access controls.

What NGINX's "stub" status indicates

NGINX Stub Status Provides basic web server metrics as text via a configured HTTP endpoint. The response describes the activity of the queried NGINX process group—specifically, client connections and the total number of requests. You can retrieve this information locally and compare it repeatedly without having to deploy a full-fledged monitoring system.

You need to distinguish between two types of values: One Snapshot shows, for example, how many client connections are active during a retrieval. Total counters such as requests In contrast, these figures indicate the total number of requests recorded. Only by comparing multiple meter readings taken at known intervals can one draw conclusions about the request rate.

These values are not a direct measurement of CPU or memory usage, nor do they represent a percentage of available web server capacity. A large number of open connections can have various causes and associated costs. To assess the actual load, you therefore need additional resource metrics and information about response times and errors.

Stub Status does not break down the numbers by virtual website or requested URL. If an installation hosts multiple sites, the endpoint alone does not indicate which one is responsible for an increase. If you have multiple NGINX instances, you should record their values separately and assign them unambiguously.

Even retrieving the status page constitutes an HTTP request in itself and has a slight impact on the monitored counters. This should be taken into account when interpreting small volumes of requests or very frequent queries. A single retrieval provides only a snapshot anyway; only the trend over time reveals whether the activity is changing.

Distinguishing Between Connections and Requests

The value Active connections includes active client connections, including those that are waiting. In other words, it counts more than just connections through which a response is currently being transmitted. The "Reading," "Writing," and "Waiting" states help put this total number into context, but they do not describe CPU usage or the number of active applications.

When a request comes in, a connection is in the "Reading" state while NGINX reads the request headers. It may then appear in the “Writing” state while NGINX processes or writes the response. This does not mean that bytes are actually flowing to the client the entire time; waiting for an upstream response may also be part of this process.

If a connection remains open after a response to further requests, it can be treated as Waiting appear. This state includes inactive client connections that are waiting for the next request. A high "Waiting" value alone does not therefore indicate overload; it may also be consistent with an environment that uses many reusable connections.

Connections and requests are different quantities: Multiple requests can be sent sequentially over a single keepalive connection. With HTTP/2, multiple requests can be transmitted over a single connection. Therefore, a fixed number of requests cannot be deduced from the number of open connections, and the `requests` counter does not have to increase at the same rate as the connection counters.

For practical evaluation, it’s worth comparing data across multiple requests: If “Waiting” increases while response times and errors remain normal, this is initially just an observation and not cause for alarm. The article on explains how to configure reuse and its limits: NGINX Keepalive Requests.

Check Module and Version

To use Stub Status, you need an NGINX installation with the module ngx_http_stub_status_module, access to its configuration, and, later, the ability to query the protected endpoint from the designated network space. The module is not included by default in the NGINX build. Whether a distribution package includes it depends on the specific package and must be verified locally.

In the terminal, check the version and the `configure` parameters of the NGINX binary actually used by the service. The following command displays this information; among the parameters, --with-http_stub_status_module to the corresponding build option.

Terminal
nginx -V

The decisive factor is the correct binary file: A program launched via the search path nginx It may be a different installation than the one used by the service. If in doubt, check the service configuration and the program launch specified there. If necessary, explicitly call the relevant binary file instead of assuming it is part of the production service based on the output from another installation.

The version also affects how the directive is written. Starting with NGINX 1.7.5, stub_status Used without an argument; older versions required any argument, such as on. The version limit is a compatibility note, not an assumption about which version is installed on your system.

If the build option is missing from the installation you are testing, you should determine which appropriate package or build is intended for your environment before making any configuration changes. A status location alone does not replace a missing module. Changes to packages and service configurations must follow the applicable operational and approval procedures.

Set Up a Protected Status Endpoint

To check the local status, you can use a separate Loopback Listener Set up. The following example is a file configuration for the existing http-Context, not a terminal command. This requires that the stub status module be available and that the example port 8088 at the specified address not already be in use by another service.

Code
server {
    listen 127.0.0.1:8088;
    server_name localhost;

    location = /stub_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

The connection to 127.0.0.1 restricts this listener to the local IPv4 loopback interface. The exact location only maps to the specified path; the directive stub_status provides the status data there. This means the listener cannot be reached via other IPv4 interfaces, regardless of whether the other websites are public.

The Access Rules supplement the binding: NGINX checks them in order until the first match is found. The local IPv4 address is allowed; all other addresses are rejected. Because this location contains its own rules, access rules from a parent context are not additionally inherited. Therefore, check the complete configuration before implementing this example.

With containers, the network space is crucial: An exporter in a separate container accesses its own localhost This is not usually the NGINX container's loopback interface. For a remote query, you need a deliberately planned private connection path and appropriate access controls. Do not simply make the status page publicly accessible; it contains operational information.

An AI-generated stock image of a network connector on a small computer, illustrating the access path.
AI-generated illustrative image: For a protected status endpoint, the network space of the requesting service must be taken into account.

Check the configuration and retrieve the status

After entering the command, first check the configuration in the terminal. The following command checks the syntax and attempts to open the referenced files. Be sure to use the NGINX binary file specific to the service and, if necessary, its different configuration path; a successful check does not yet activate the change.

Terminal
nginx -t

A Approved Reload This is a separate production step. Do not execute it until you have received approval and in accordance with your environment’s operating procedures. When you reload, NGINX reloads the configuration, starts new workers with the new configuration, and shuts down the old workers in an orderly manner. Afterward, verify that the operation was successful and check the logs, rather than assuming that a change has taken effect simply because the syntax check passed.

Once activation has been approved, you can access the endpoint locally on the same network segment using curl retrieve. The switch -i Displays the HTTP status and headers in addition to the response body. The following example assumes that the listener and path have been specified in the file configuration.

Terminal
curl -i http://127.0.0.1:8088/stub_status

A successful HTTP response is expected, with status data as Text, not as JSON. If an error occurs, the status code and NGINX logs can help narrow down the issue. However, a successful local request only shows that this access path works; it does not prove that no other configuration makes the endpoint accessible from the outside.

Read Status Values and Calculate Rates

The output combines current connection statuses with cumulative values. For interpretation, this distinction is more important than the absolute value of a single figure: A Current value describes the state at the time of retrieval; a total counter records the number of events counted up to that point. The table lists the individual fields and typical erroneous conclusions.

Stub Status Fields and Their Classification
FieldTypeMeaningCommon Misinterpretation
Active connectionsCurrent valueActive client connections, including those in the "Waiting" stateDirect measure of CPU or capacity utilization
ReadingCurrent valueConnections When Reading the Request HeaderTotal number of incoming inquiries
WritingCurrent valueConnections in the response processing or write stateAn even number of bytes are sent on each connection
WaitingCurrent valueInactive client connections waiting for another requestIn and of itself, proof of overload
acceptsTotal CounterTotal number of client connections acceptedCurrently Open Connections
handledTotal CounterTotal number of connections processedNumber of successful HTTP responses
requestsTotal CounterTotal number of client requests countedCurrent requests per second

From the counter requests an average Inquiry Rate To calculate for an interval: Subtract the first reading from the second and divide the difference by the number of seconds that have elapsed. Illustrative calculation example (not a measurement): If the value rises from 12,000 to 12,600 in 60 seconds, 600 divided by 60 equals an average of 10 requests per second.

This average does not show either the highest short-term peak or which URLs were accessed. For each request, record the time and the instance accessed. If the counter decreases or you switch between instances, do not interpret the simple difference as a rate without verification; instead, start a new comparison series for the instance in question.

When comparing intervals of different lengths, use the actual elapsed time rather than the scheduled retrieval interval. For example, a delayed retrieval of two minutes requires a different divisor than a retrieval after one minute. A longer time frame smooths out short-term fluctuations more effectively; shorter intervals make changes more visible but increase the proportion of status queries.

The status query itself is also an HTTP request and has a slight impact on the monitored counters. This becomes particularly noticeable when traffic is very low or when queries are made frequently. A regular, documented query interval makes it easier to take such monitoring-related factors into account when interpreting the data.

If there are multiple instances, first calculate the rate based on the consecutive values for each individual instance. Only then can the rates for comparable time periods be combined. If a data point is missing or an instance’s assignment changes, the resulting gap should remain visible rather than creating the illusion of a continuous trend.

Examining Errors and Limitations

If the status endpoint returns an HTTP 403 response, first check the actual source address received by NGINX and the access rules for that location. allow and deny are evaluated in order until the first match is found. Rules specific to the location override any inherited rules, if applicable; they do not automatically supplement them.

If you get an HTTP 404 error, start by checking elsewhere: Are the port, listener, requested path, and selected server block correct? Also, verify that the intended configuration is actually active after the reload. A successful local request using a different port or path does not prove that the desired location was accessed.

If no HTTP response is received at all, distinguish between the listener being unreachable and a response with an error status. First, check the address, port, and network space of the requesting process, as well as the service status. Only once a connection to the correct listener has been established will the HTTP status and selected location help narrow down the issue further.

For ongoing error analysis, it is helpful to compare the total counters accepts and handles. Normally, they are the same. If the difference between them increases, it may be due to a resource limit being reached; however, comparing the counters alone does not reveal either the specific cause or the number of rejected HTTP requests. Therefore, include error logs and configuration settings in your investigation.

An existing difference initially shows only the gap between the two total counters. To determine whether the situation has changed during the observation period, compare this gap across multiple queries of the same instance. Make a note of the relevant time period so you can search for the corresponding log entries and operational events.

The Directive worker_connections Limits the number of connections per worker, not just client connections. This includes, for example, connections to proxied servers; file descriptor limits may also impose restrictions. Calculated as the number of active connections divided by the number of workers, multiplied by worker_connections Therefore, this does not provide a reliable picture of capacity utilization. Instead, check the actual limits and the remaining resource consumption in context.

A change to connection limits should not be based solely on a high status value. First, determine whether a limit has actually been reached and which other resources or upstream connections are involved. Plan any changes while monitoring errors and response times, and review them in accordance with the established operating procedures.

Classifying Trends and Upstream Issues

A single status check reflects only a single point in time. Repeated checks at fixed intervals, on the other hand, help determine whether connection states are rising above normal levels or falling back after a spike. Monitor multiple NGINX instances separately and keep track of which instance corresponds to each time series; otherwise, switching between endpoints can distort the trend.

A high Waiting value Describes waiting, currently inactive client connections. On its own, this is not evidence of overload: With reused connections, clients can wait for additional requests. An increase becomes more meaningful when you compare it to response times, errors, and resource metrics over the same time period.

Remains Writing If the value remains elevated for an extended period, examine both upstream times and client behavior. This status does not mean that bytes are being sent continuously; it may also include the wait time for an upstream response. The “Stub” status does not specify the affected backend service or the cause of a delay.

Supplementary data can help with troubleshooting: access logs and recorded upstream times show which requests and backends are causing issues; error logs provide clues about failed connections. If you’re dealing with CPU or memory pressure, you’ll need the corresponding system metrics. If repeated attempts to connect to the backend are affecting the investigation, the article on NGINX Upstream Keepalive the configuration of reusable upstream connections.

From Status to Monitoring

For an occasional diagnosis, a secure local status query may be sufficient. It provides information on which metrics the queried instance is currently reporting, but does not store any historical data itself. If you need to compare trends or be notified of persistent anomalies, you’ll need regular data collection and a system for time series and alerts.

The official NGINX Prometheus Exporter There is a separate component for this: It retrieves the stub status and provides the data as Prometheus metrics. Prometheus then retrieves the data from the exporter endpoint. Plan for availability and access restrictions for both paths—that is, both to the status endpoint and to the exporter's metric output.

AI-generated illustration of three separate stations for Status Endpoint, Exporter, and Prometheus.
AI-generated illustration: The status endpoint and the exporter are separate components whose access paths must be protected.

During setup, document which exporter queries which NGINX instance and from where Prometheus reaches the exporter. Especially with separate containers, these are two different network paths. Therefore, an accessible exporter endpoint alone does not replace the need to verify whether the exporter itself can successfully retrieve the correct status page.

The additional logging does not turn the base metrics into detailed response time or HTTP status class metrics. To investigate slow URLs, error responses, or individual upstreams, appropriate access logs and additional telemetry are required. Even the more comprehensive NGINX Plus API Stub Status in NGINX Open Source should be distinguished from other types; their availability and configuration are not interchangeable.

Select additional data based on the specific question: To determine whether the number of requests is increasing, a simple comparison of the counter over time is sufficient at first. If, on the other hand, the issue involves slow responses or a specific backend service, you’ll need latency and upstream data from the relevant time period. The status page can provide a reason to investigate, but it cannot determine the cause on its own.

Alarm thresholds should be based on the normal behavior of the respective instance and on service objectives, not on a general number for waiting or writing. Compare anomalies with latencies, errors, and available resources, and determine whether an alert actually warrants action. This way, a single counter reading becomes a reason for a targeted investigation rather than a hasty diagnosis.

When planning alerts, also take into account the failure of the data collection path: Missing data is not the same as zero requests or zero connections. A separate check of reachability helps distinguish a failed retrieval from a situation where activity is actually low. Also, specify who will handle an alert and what additional data must be available for diagnosis.

Sources and Current State of Knowledge

Status of the research:

Research and version status: November 4, 2026. As of NGINX 1.7.5, the `stub_status` directive no longer requires an argument; module availability and the binary file used depend on the installation.

https://nginx.org/en/docs/http/ngx_http_stub_status_module.html?from=20423&from_column=20423

https://github.com/nginx/nginx-prometheus-exporter

https://mailman.nginx.org/pipermail/nginx/2015-February/046679.html

https://nginx.org/en/docs/switches.html

https://nginx.org/en/docs/http/ngx_http_access_module.html

https://nginx.org/en/docs/ngx_core_module.html

https://nginx.org/en/docs/http/ngx_http_api_module.html

Current articles

AI-generated illustration of a diagnostic chain consisting of clues, time assessment, and controlled questioning.
Administration

Redis Insight 2.x: Tools for Secure Redis Diagnostics

Redis Insight 2.x remains a useful tool for existing installations to investigate keys, slow commands, and unusual memory usage. This article provides an overview of the older product line and shows how teams can safely use Browser, Database Analysis, Slow Log, and Profiler.

A schematic illustration of a central proxy node between applications, as well as primary and replica instances.
Databases

Using MariaDB MaxScale as a Database Proxy

MariaDB MaxScale decouples applications from primary-replica roles and can route SQL queries selectively. Key factors include router selection, replication latency, session state, TLS, and a clear operational process.