Skip to content

Commit 123d013

Browse files
authored
Put response cache in GA and remove preview_ prefix (#8678)
Signed-off-by: Benjamin <[email protected]>
1 parent ccbf23d commit 123d013

File tree

42 files changed

+294
-142
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+294
-142
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
### Response caching is now Generally Available 🎉 ([PR #8678](https://github.com/apollographql/router/pull/8678))
2+
3+
We're excited to announce that **response caching is now Generally Available (GA)** and ready for production use!
4+
5+
Response caching is a powerful feature that enables the router to cache subgraph query responses using Redis, dramatically improving query latency and reducing load on your underlying services. Unlike traditional HTTP caching solutions, response caching provides GraphQL-aware caching at the entity and root field level, making cached data reusable across different users and queries.
6+
7+
#### Key benefits
8+
9+
- **Improved performance**: Cache origin responses and reuse them across queries to reduce latency
10+
- **Reduced subgraph load**: Minimize redundant requests to your subgraphs by serving cached data
11+
- **Entity-level caching**: Cache individual entity representations independently, enabling fine-grained control over data freshness
12+
- **Flexible cache control**: Set different TTLs for different types of data based on `@cacheControl` directives in your schema or the `Cache-Control` response header
13+
- **Privacy-aware**: Mix public and private data safely—share cached data across users while maintaining privacy for personalized data
14+
- **GraphQL-native**: Solve unique GraphQL caching challenges that traditional CDNs can't address, such as mixed TTLs and high data duplication
15+
- **Active cache invalidation**: Use the `@cacheTag` directive in your schema to tag cached data, then actively invalidate specific cache entries via an HTTP endpoint when data changes
16+
17+
#### What's cached
18+
19+
The router caches two kinds of data:
20+
- **Root query fields**: Cached as complete units (the entire response for these root fields)
21+
- **Entity representations**: Cached independently—each origin's contribution to an entity is cached separately and can be reused across different queries
22+
23+
24+
#### Configuration
25+
26+
Response caching uses Redis as the cache backend and can be configured per subgraph with invalidation support:
27+
28+
```yaml
29+
response_cache:
30+
enabled: true
31+
# Configure the invalidation endpoint
32+
invalidation:
33+
listen: 127.0.0.1:4000
34+
path: /invalidation
35+
subgraph:
36+
all:
37+
enabled: true
38+
ttl: 30s
39+
redis:
40+
urls:
41+
- redis://127.0.0.1:6379
42+
invalidation:
43+
enabled: true
44+
shared_key: ${env.INVALIDATION_SHARED_KEY}
45+
```
46+
47+
The router determines cache TTLs from `Cache-Control` HTTP headers returned by your origins. You also get comprehensive Redis metrics to monitor cache performance, including connection health, command execution, and operational insights.
48+
49+
#### Cache invalidation with @cacheTag
50+
51+
Tag your cached data using the `@cacheTag` directive in your subgraph schema, then actively invalidate specific cache entries when data changes:
52+
53+
```graphql
54+
type Query {
55+
user(id: ID!): User @cacheTag(format: "user-{$args.id}")
56+
users: [User!]! @cacheTag(format: "users-list")
57+
}
58+
59+
type User @key(fields: "id") @cacheTag(format: "user-{$key.id}") {
60+
id: ID!
61+
name: String!
62+
}
63+
```
64+
65+
Send invalidation requests to remove cached data before TTL expires:
66+
67+
```bash
68+
curl --request POST \
69+
--header "authorization: $INVALIDATION_SHARED_KEY" \
70+
--header 'content-type: application/json' \
71+
--url http://localhost:4000/invalidation \
72+
--data '[{"kind":"cache_tag","subgraphs":["posts"],"cache_tag":"user-42"}]'
73+
```
74+
75+
#### Additional features
76+
77+
- **Cache debugger**: See exactly what's being cached during development with detailed cache key inspection
78+
- **Redis cluster support**: Scale your cache with Redis cluster deployments and benefit from read replicas for improved performance and availability
79+
- **Comprehensive metrics**: Monitor cache performance with detailed Redis-specific metrics including connection health, command execution, and latency
80+
81+
For complete documentation, configuration options, and best practices, see the [response caching documentation](/router/routing/performance/caching/response-caching/overview).
82+
83+
By [@bnjjj](https://github.com/bnjjj) in https://github.com/apollographql/router/pull/8678

.changesets/fix_response_cache_invalidation_endpoint.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
### Enable invalidation endpoint for response cache when any subgraph has invalidation enabled ([PR #8680](https://github.com/apollographql/router/pull/8680))
22

3-
Previously, the response cache invalidation endpoint was only enabled when global invalidation was enabled via `preview_response_cache.subgraph.all.invalidation.enabled`. This meant that if you enabled invalidation for only specific subgraphs without enabling it globally, the invalidation endpoint would not be started, preventing cache invalidation requests from being processed.
3+
Previously, the response cache invalidation endpoint was only enabled when global invalidation was enabled via `response_cache.subgraph.all.invalidation.enabled`. This meant that if you enabled invalidation for only specific subgraphs without enabling it globally, the invalidation endpoint would not be started, preventing cache invalidation requests from being processed.
44

55
Now, the invalidation endpoint is enabled if either:
6-
- Global invalidation is enabled (`preview_response_cache.subgraph.all.invalidation.enabled: true`), OR
6+
- Global invalidation is enabled (`response_cache.subgraph.all.invalidation.enabled: true`), OR
77
- Any individual subgraph has invalidation enabled
88

99
This allows for more flexible configuration where you can enable invalidation selectively for specific subgraphs:
1010

1111
```yaml
12-
preview_response_cache:
12+
response_cache:
1313
enabled: true
1414
invalidation:
1515
listen: 127.0.0.1:4000

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,4 +1161,4 @@ workflows:
11611161
- secops-oidc
11621162
- github-orb
11631163
git-base-revision: <<#pipeline.git.base_revision>><<pipeline.git.base_revision>><</pipeline.git.base_revision >>
1164-
disabled-signatures: "rules.providers.semgrep.security.javascript.lang.security.detect-insecure-websocket"
1164+
disabled-signatures: "rules.providers.semgrep.security.javascript.lang.security.detect-insecure-websocket"

DEVELOPMENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,4 @@ For full information on available options, including HTML reports and `lcov.info
184184

185185
## Project maintainers
186186

187-
Apollo Graph, Inc.
187+
Apollo Graph, Inc.

apollo-router/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ fred = { version = "10.1.0", features = [
9898
"i-cluster",
9999
"tcp-user-timeouts",
100100
"metrics",
101-
"replicas",
102-
"serde-json"
101+
"serde-json",
102+
"replicas"
103103
] }
104104
futures = { version = "0.3.30", features = ["thread-pool"] }
105105
graphql_client = "0.14.0"
@@ -310,7 +310,7 @@ fred = { version = "10.1.0", features = [
310310
"mocks",
311311
"i-cluster",
312312
"tcp-user-timeouts",
313-
"replicas"
313+
"replicas",
314314
] }
315315
futures-test = "0.3.30"
316316
insta.workspace = true

apollo-router/src/configuration/metrics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ impl InstrumentData {
323323

324324
populate_config_instrument!(
325325
apollo.router.config.response_cache,
326-
"$.preview_response_cache",
326+
"$.response_cache",
327327
opt.enabled,
328328
"$[?(@.enabled)]",
329329
opt.debug,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: Response cache feature is now GA
2+
actions:
3+
- type: move
4+
from: preview_response_cache
5+
to: response_cache

apollo-router/src/configuration/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,12 +586,12 @@ impl Configuration {
586586
}
587587

588588
// response & entity caching
589-
if self.apollo_plugin_enabled("preview_response_cache")
589+
if self.apollo_plugin_enabled("response_cache")
590590
&& self.apollo_plugin_enabled("preview_entity_cache")
591591
{
592592
return Err(ConfigurationError::InvalidConfiguration {
593593
message: "entity cache and response cache features are mutually exclusive",
594-
error: "either set preview_response_cache.enabled: false or preview_entity_cache.enabled: false in your router yaml configuration".into(),
594+
error: "either set response_cache.enabled: false or preview_entity_cache.enabled: false in your router yaml configuration".into(),
595595
});
596596
}
597597

apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,10 @@ expression: "&schema"
19291929
"type": "object"
19301930
},
19311931
"Config7": {
1932+
"description": "Configuration for the progressive override plugin",
1933+
"type": "object"
1934+
},
1935+
"Config8": {
19321936
"additionalProperties": false,
19331937
"description": "Configuration for response caching",
19341938
"properties": {
@@ -1974,7 +1978,7 @@ expression: "&schema"
19741978
],
19751979
"type": "object"
19761980
},
1977-
"Config8": {
1981+
"Config9": {
19781982
"additionalProperties": false,
19791983
"description": "Redis cache configuration",
19801984
"properties": {
@@ -2092,10 +2096,6 @@ expression: "&schema"
20922096
],
20932097
"type": "object"
20942098
},
2095-
"Config9": {
2096-
"description": "Configuration for the progressive override plugin",
2097-
"type": "object"
2098-
},
20992099
"ConnectorConfiguration": {
21002100
"properties": {
21012101
"all": {
@@ -9245,7 +9245,7 @@ expression: "&schema"
92459245
"redis": {
92469246
"anyOf": [
92479247
{
9248-
"$ref": "#/definitions/Config8"
9248+
"$ref": "#/definitions/Config9"
92499249
},
92509250
{
92519251
"type": "null"
@@ -11947,8 +11947,8 @@ expression: "&schema"
1194711947
},
1194811948
"type": "object"
1194911949
},
11950-
"^preview_response_cache$": {
11951-
"$ref": "#/definitions/Config7"
11950+
"^response_cache$": {
11951+
"$ref": "#/definitions/Config8"
1195211952
}
1195311953
},
1195411954
"properties": {
@@ -12144,7 +12144,7 @@ expression: "&schema"
1214412144
"$ref": "#/definitions/FileUploadsConfig"
1214512145
},
1214612146
"progressive_override": {
12147-
"$ref": "#/definitions/Config9"
12147+
"$ref": "#/definitions/Config7"
1214812148
},
1214912149
"rhai": {
1215012150
"$ref": "#/definitions/RhaiConfig"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
source: apollo-router/src/configuration/tests.rs
3+
expression: new_config
4+
---
5+
---
6+
response_cache:
7+
enabled: true
8+
subgraph:
9+
all:
10+
redis:
11+
urls:
12+
- "redis://test"
13+
required_to_start: true
14+
enabled: true
15+
invalidation:
16+
enabled: true
17+
shared_key: invalidate
18+
subgraphs:
19+
accounts:
20+
enabled: false
21+
products:
22+
ttl: 120s
23+
invalidation:
24+
enabled: true
25+
shared_key: invalidate

0 commit comments

Comments
 (0)