http2_push_preload directive stability when upgrading Nginx from 1.19.2 to newer releases
0 reputation · 02 Feb 2024, 09:11 UTC
0 reputation · 02 Feb 2024, 09:11 UTC
The goal is to enable nginx’s http2_push_preload feature to preload critical assets via the X-Accel-Redirect header while keeping alert noise low by suppressing unnecessary push‑related warnings.
Because the directive is marked experimental, its behavior may change across versions, it interacts with caching layers (potentially causing duplicate pushes when a pushed resource is already cached), and browser support for HTTP/2 server push varies. This creates uncertainty about long‑term reliability and the appropriate logging configuration to avoid notification noise without losing other important alerts.
Will enabling http2_push_preload continue to generate push promises after upgrading to Nginx 1.22.x or later? How can duplicate pushes be avoided when cached resources are involved? What error_log level should be set to suppress push‑related warnings while preserving other critical alerts?
32775 reputation · 02 Feb 2024, 14:05 UTC
Yes — http2_push_preload still exists and still emits push promises in Nginx 1.22.x and later releases, and its basic behavior (converting Link: </asset.css>; rel=preload response headers into HTTP/2 PUSH_PROMISE frames) has not changed in any way that would break a config written for 1.19.2. Your existing configuration will load and function after the upgrade. The bigger risks are not the upgrade itself but two things the directive was never able to do — detect the client cache — and one external factor: browsers dropping push support.
Confirmed (well-established behavior): the directive is present in 1.22.x and current stable/mainline branches; it is still documented as experimental; and Nginx has no mechanism to ask the client whether a resource is already cached before sending a push promise. Push deduplication against the browser cache is simply not something the server can do.
Likely, but verify in your environment: that your specific push flow via X-Accel-Redirect behaves identically after the upgrade. Internal-redirect-driven pushes depend on your location blocks and header handling, so treat this as a smoke-test item rather than a guarantee.
http2_push_preload triggers on Link: rel=preload headers, not on X-Accel-Redirect itself. If your application sends the preload Link headers alongside (or after) an internal redirect, that still works — but if you were expecting X-Accel-Redirect alone to cause pushes, it won't, on any version. Worth checking which header your app actually emits before blaming the upgrade.
You cannot fully solve this server-side; you can only reduce it:
Link: rel=preload headers exclusively from the document request, never from API or asset responses, so repeat asset requests don't re-trigger pushes.add_header Set-Cookie on the pushed routes or from the app), and have the application omit the Link headers when the cookie is present. This is the closest practical approximation of cache-awareness.Cache-Control: max-age of days, most repeat visitors already have it; pushing it wastes bandwidth and can contend with the HTML stream. Restrict pushes to first-visit-critical resources.Push-related chatter (e.g. stream resets when a client cancels a push, RST_STREAM frames) is logged at info/debug level. Setting:
error_log /var/log/nginx/error.log warn;suppresses those messages while preserving genuine errors (error, crit, alert, emerg). warn is the right level here; notice is quieter than info but still admits some routine messages. You do not need a push-specific log filter — nothing push-related is logged at warn or above in normal operation.
Chrome removed HTTP/2 server push support, and other browsers never broadly shipped it or have deprecated it. For a growing majority of clients, your pushes are silently ignored — the directive works, but nothing consumes the promise. Before investing in dedup logic, measure how much of your traffic actually accepts pushes.
curl --http2 -sv https://your.host/ -o /dev/null 2>&1 | grep -i pushLook for PUSH_PROMISE frames, and check the browser devtools Network tab initiator column for "Push". Then scan the error log at warn for a day to confirm signal-to-noise is acceptable.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.