Understanding Cache Control
In HTTP, theCache-Control header is used to define the caching behavior of responses. It tells browsers and intermediary servers how to handle content caching. Some of the common Cache-Control directives include:
-
max-age: Specifies how long (in seconds) a response can be considered fresh. -
no-cache: Forces caches to submit the request to the origin server for validation before serving the cached copy. -
no-store: Prevents the storage of any part of the response by caches.
Expires is an older header used to specify an exact expiration time for cached content. If both Cache-Control and Expires are present, Cache-Control takes precedence.Cache Control Policy
To enable a restrictive cache control policy, insert the following snippet into your config.yaml file and adjust it according to your needs.
Restrictive Cache Control Policy
The cache control policy algorithm ensures that the strictest caching policy from all subgraphs is applied when propagating theCache-Control header (and related ones, such as Expires). This is critical for cases where different subgraphs have varying caching requirements, and you want to ensure that sensitive or time-sensitive data is properly handled.
This policy doesn’t need to be set for the entire federation, you can decide to only apply the restrictive cache control policy to a subgraph. In order to do that, just set
enabled: false in your cache_control_policy configuration-
no-cacheandno-storedirectives take priority, and these will override any other directives. -
max-agevalues: The smallestmax-agevalue from any subgraph (or the default, if specified in the configuration) is selected. -
Expiresheader: The earliest expiration date will be used ifExpiresheaders are provided.
no-cache/no-store always winsWhen any subgraph returns no-cache or no-store directives, they will take precedence over all other cache settings, regardless of max-age values. This guarantees that sensitive data will not be stored in caches, providing an extra layer of security.Mutation Requests Automatically Set
no-cacheIf a global cache control policy is enabled, we will automatically set Cache-Control: no-cache to GraphQL mutation request for security reasons, ensuring that mutation results are never cached.Requests with errors are always
no-cacheIf the final response to the client has any errors, we automatically set Cache-Control: no-store, no-cache, must-revalidate to prevent clients or caches re-serving the errored response.Example Scenarios:
Scenario 1: Global Default + Subgraph Specific max-age
-
Global Default:
Cache-Control: max-age=600(10 minutes) -
Subgraph A:
Cache-Control: max-age=300(5 minutes) -
Subgraph B: No cache control specified
- Result:
Cache-Control: max-age=300, since Subgraph A’smax-age=300is more restrictive than the global default.
- Result:
Scenario 2: Subgraph-Specific no-cache with Global Default
-
Global Default:
Cache-Control: max-age=600 -
Subgraph A:
Cache-Control: no-cache -
Subgraph B:
Cache-Control: max-age=300- Result:
Cache-Control: no-cacheoverrides everything due to its strictness.
- Result:
Scenario 3: Expires in Subgraphs
-
Subgraph A:
Cache-Control: max-age=300,Expires=Wed, 15 Sep 2024 18:00:00 GMT -
Subgraph B:
Cache-Control: max-age=600,Expires=Wed, 15 Sep 2024 17:00:00 GMT- Result: The response uses
Expires=Wed, 15 Sep 2024 17:00:00 GMT, the earlier expiration time.
- Result: The response uses
Scenario 4: Combining Global Defaults with no-cache
-
Global Default:
Cache-Control: max-age=600 -
Subgraph A:
Cache-Control: no-store -
Subgraph B: No cache control set
- Result:
Cache-Control: no-storetakes precedence, as it’s stricter than the global default.
- Result:
Scenario 5: No global default
-
Global:
enabled: true,valueunset - Subgraph A: no cache control set
-
Subgraph B:
Cache-Control: max-age=300- Result: Any requests which access
subgraph Bwill haveCache-Control: max-age=300set, but requests which don’t access subgraph B won’t have any cache-control set
- Result: Any requests which access
Scenario 6: With subgraph error
- Global: Any
- Subgraph A: Any
-
Subgraph B: Returns error response
- Result: Any requests which access
subgraph Bwill have an error, and thusCache-Control: no-store, no-cache, must-revalidateset, but requests which don’t access subgraph B won’t have any cache-control set.
- Result: Any requests which access
no-cache or no-store directives for security sensitive subgraphs.
Overriding Cache Control Policy
By using the
set operation in their header propagation rules, users can overwrite the cache control policy if necessary.specific-subgraph will have the desired subgraph cache control value set (max-age=5400).