Skip to content

Tweak cache control headers to properly support nginx #8686

@txau

Description

@txau

Unfortunately, nginx does not adhere to standard cache header policies. We want to keep our current cache-control headers as they are, since they are useful for browsers and standardized caches such as CloudFlare, but we need to add extra headers for nginx:

Here is a short, developer-ready instruction summarizing exactly what needs to be implemented on the application side and how Nginx will behave with it. This version assumes:

  • You will use custom cache-control header X-Cache-Policy to tell Nginx what to do.
  • You will use Last-Modified + If-Modified-Since for revalidation (not ETags).
  • The app already sets normal Cache-Control headers, but these new headers are strictly for Nginx and override its behavior.

You can forward this as-is to your developer.


Developer Instructions: Nginx-Controlled Caching via X-Cache-Policy + Last-Modified

We are adding Nginx-level caching for selected endpoints.
To control caching behavior, the backend must send two additional headers:

  1. X-Cache-Policy – tells Nginx whether and how long to cache.
  2. Last-Modified – enables Nginx revalidation via If-Modified-Since.

Nginx will ignore the app’s normal Cache-Control header for its own cache logic.
These new headers are strictly for Nginx’s internal caching.


1. Custom Header: X-Cache-Policy

Backend must send one of the following values:

X-Cache-Policy: no-cache

Do not allow Nginx to cache this response.

X-Cache-Policy: short

Allow Nginx to cache this response for 60 seconds, then revalidate.

X-Cache-Policy: long

Allow Nginx to cache this response for 600 seconds, then revalidate.

(We can adjust these TTL categories later.)

These strings are mapped in Nginx and control whether the response is cached and for how long.


2. Revalidation Support (Required)

To allow Nginx to revalidate stale cached entries:

The backend must send:

Last-Modified: <timestamp>

This should represent the last update time of the resource.

On receiving a conditional request:

Nginx will send:

If-Modified-Since: <timestamp>

Backend must handle this logic:

If the resource has NOT changed since the provided timestamp:

Return:

304 Not Modified

with no response body.

If the resource HAS changed:

Return:

200 OK
Last-Modified: <new timestamp>
(body)

This allows Nginx to reuse cached responses efficiently.


3. Summary of Required Backend Changes

  1. Add X-Cache-Policy to all responses for which we want custom Nginx caching.

    • no-cache → Nginx will not cache
    • short → cached 60s
    • long → cached 600s
  2. Include a Last-Modified header on all cacheable responses.

    • Use the resource’s last update timestamp.
  3. Implement conditional GET handling:

    • Check If-Modified-Since
    • If unchanged → return 304 Not Modified
    • If changed → return normal 200 OK plus updated Last-Modified
  4. Existing Cache-Control headers remain for browsers, but Nginx will use the new custom header for caching decisions.


Optional Example Response

Cacheable (short TTL)

HTTP/1.1 200 OK
X-Cache-Policy: short
Last-Modified: Wed, 12 Feb 2025 10:32:00 GMT
Cache-Control: public, max-age=30
Content-Type: application/json
...

Conditional response

HTTP/1.1 304 Not Modified
Last-Modified: Wed, 12 Feb 2025 10:32:00 GMT

If you want, I can also provide the corresponding Nginx config block using your chosen policies (X-Cache-Policy: short|long|no-cache).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions