Hosting · WordPress · performance · infrastructure
explainer

Nginx add_header Inheritance and the ‘always’ Flag: Context Overrides and Error Header Emission

Short answer

Understand how Nginx evaluates add_header inheritance across http, server, and location blocks, how child directives override parent headers, and how the always flag ensures header emission on error responses.

Research-based

Last verified:

Applies to: NGINX HTTP headers module; add_header behavior generally, with add_header_inherit available in NGINX 1.29.3+ and always available since 1.7.5.

Comparison of NGINX header inheritance modes: default override, merge, and off.

In Nginx web server administration, configuring HTTP response headers using the add_header directive is a standard practice for managing caching, security policies, and custom application metadata. However, two aspects of add_header frequently surprise administrators: headers declared at a parent configuration level (such as http or server) can disappear when a nested location block defines its own header, and custom headers often fail to emit when the server returns error status codes like 404 or 500. Understanding the exact context inheritance model and the role of the always parameter resolves these operational pitfalls.

The Standard add_header Inheritance Rule

According to the official Nginx ngx_http_headers_module documentation, the add_header directive can be declared inside the http, server, location, and if in location contexts. The foundational inheritance rule states:

“These directives are inherited from the previous configuration level if and only if there are no add_header directives defined on the current level.”

This design means that inheritance is an all-or-nothing mechanism by default. If a parent block (for example, the server block) defines five security headers, and a child location block defines a single custom header such as add_header X-Custom-Header "Value";, Nginx does not append the new header to the parent list. Instead, the presence of an add_header directive at the current level blocks inheritance completely, causing all parent-level headers to be silently omitted for requests matching that location.

Altering Inheritance with add_header_inherit (Nginx 1.29.3+)

In Nginx version 1.29.3, Nginx introduced the add_header_inherit directive to provide granular control over this behavior. The syntax and allowed parameters are:

Syntax: add_header_inherit on | off | merge ;
Default: add_header_inherit on;
Context: http, server, location, if in location

The directive supports three operational modes:

  • on (default): Preserves the standard inheritance model, where child-level add_header definitions prevent headers from the previous configuration level from being inherited.
  • merge: Enables appending values from the previous configuration level to the directives defined at the current level, allowing parent headers to remain active alongside child headers.
  • off: Explicitly cancels inheritance of values from the previous configuration level, even if no add_header directive is declared on the current level.

The add_header_inherit rules themselves are inherited down the configuration tree in the standard way. For instance, declaring add_header_inherit merge; at the top http level will be inherited recursively across all nested server and location blocks unless explicitly redefined at a deeper level.

HTTP Status Codes and the ‘always’ Flag

By default, add_header does not attach headers to all HTTP responses. The official documentation specifies that add_header adds the designated field only if the response code equals one of the following supported success or redirection codes:

  • 200, 201 (since version 1.3.10)
  • 204, 206
  • 301, 302, 303, 304
  • 307 (since versions 1.1.16, 1.0.13)
  • 308 (since version 1.13.0)

If the server issues an error response—such as a client error (400, 403, 404) or a server error (500, 502, 503)—standard add_header declarations are ignored. Consequently, critical response headers (such as CORS headers or security headers) will not be sent to the client during an error response.

To override this restriction, Nginx version 1.7.5 introduced the optional always parameter:

Syntax: add_header name value [ always ];

When the always parameter is appended to an add_header directive, the header field is added regardless of the HTTP response status code, ensuring its presence on both successful responses and error pages.

Configuration Scenarios and Directives Comparison

To evaluate how these directives interact in practical configurations, consider the default behavior versus configured overrides:

Configuration State Child Block Header Count Inheritance Outcome Error Status Code Behavior
Standard default (add_header_inherit on) Child defines ≥ 1 add_header All parent headers dropped Emits on supported 2xx/3xx only (unless always specified)
Standard default (add_header_inherit on) Child defines 0 add_header All parent headers inherited Emits on supported 2xx/3xx only (unless always specified)
Merged mode (add_header_inherit merge) Child defines ≥ 1 add_header Parent and child headers combined Emits on supported 2xx/3xx only (unless always specified)
Cancelled mode (add_header_inherit off) Any Zero parent headers inherited Emits on supported 2xx/3xx only (unless always specified)
Comparison of NGINX header emission with always versus without always.

Text version of the diagrams

  • NGINX Header Inheritance: Default on — Child headers replace parent; Merge — Parent and child combine; Off — Parent headers are excluded
  • When Headers Are Emitted: Without always — Only listed statuses emit; With always — Any response status emits; Error response — Headers need always

Research Method and Limitations

This article was prepared solely from public technical documentation excerpts for the Nginx ngx_http_headers_module retrieved on 2026-09-17 from nginx.org. It details verified directive syntax, version requirements (such as 1.7.5 for always and 1.29.3 for add_header_inherit), and documented inheritance rules. No hands-on lab benchmarks, physical server tests, or third-party web server comparisons were performed. Specific third-party modules or upstream proxy interactions not documented in the official ngx_http_headers_module specification remain outside the scope of this reference.

Related guides