Skip to content

DRAFT: invalidation labels for CDN cache invalidation#9811

Draft
aaronArinder wants to merge 17 commits into
devfrom
ebylund-9481-response-cache-tag-propagation
Draft

DRAFT: invalidation labels for CDN cache invalidation#9811
aaronArinder wants to merge 17 commits into
devfrom
ebylund-9481-response-cache-tag-propagation

Conversation

@aaronArinder

Copy link
Copy Markdown
Contributor

Checklist

Complete the checklist (and note appropriate exceptions) before the PR is marked ready-for-review.

  • PR description explains the motivation for the change and relevant context for reviewing
  • PR description links appropriate GitHub/Jira tickets (creating when necessary)
  • Changeset is included for user-facing changes
  • Changes are compatible1
  • Documentation2 completed
  • Performance impact assessed and acceptable
  • Metrics and logs are added3 and documented
  • Tests added and passing4
    • Unit tests
    • Integration tests
    • Manual tests, as necessary

Exceptions

Note any exceptions here

Notes

Footnotes

  1. It may be appropriate to bring upcoming changes to the attention of other (impacted) groups. Please endeavour to do this before seeking PR approval. The mechanism for doing this will vary considerably, so use your judgement as to how and when to do this.

  2. Configuration is an important part of many changes. Where applicable please try to document configuration examples.

  3. A lot of (if not most) features benefit from built-in observability and debug-level logs. Please read this guidance on metrics best-practices.

  4. Tick whichever testing boxes are applicable. If you are adding Manual Tests, please document the manual testing (extensively) in the Exceptions.

ebylund and others added 11 commits July 15, 2026 10:47
Introduce the PropagateCacheTagsConfig type and OverflowPolicy enum that
will gate emission of an aggregated cache-tag header on the supergraph
response. The field is wired into Config but no behavior is enabled yet;
subsequent commits add the aggregator, persist cache tags on cache
entries, and emit the header.

Refs #9481
The aggregator collects the union of cache tags surfaced by each
subgraph response during a single supergraph request. It is stored as a
typed Context extension, mirroring the existing CacheControls pattern.

A small helper, record_external_cache_tags, filters internal-prefixed
tags before insertion so they cannot leak via the configured response
header (or via coprocessor/rhai consumers reading the context).

The aggregator is not yet populated by any production code path; that
work follows in subsequent commits.

Refs #9481
Previously the CacheEntry.cache_tags field was only populated when a
document was written with debug=true, primarily for the cache debugger.
The supergraph response cache-tag propagation in router#9481 needs the
tag set available on every cache hit (including non-debug production
hits), so the conditional is dropped: the document's pre-permutation
invalidation_keys are always persisted on the CacheValue.

The now-unused Document.debug field (and the parameter that threaded it
into cache_store_root_from_response) is removed to keep the type tight.
The Document.debug flag never participated in the on-disk Redis format,
so this is a Rust-only cleanup.

Legacy entries written before this change deserialize with
cache_tags: None and contribute zero tags until they age out via TTL.

Refs #9481
…ontext

Populate the CacheTagsAggregator at every site where a subgraph's cache
tag set becomes known during a supergraph request:

- Root cache miss + hit paths (cache_lookup_root): push schema-resolved
  @cacheTag values, plus value.cache_tags from the stored entry on hit.
- Root cache miss extension read: push apolloCacheTags from the
  subgraph response extension as it is added to invalidation_keys.
- Entity cache lookup (cache_lookup_entities): iterate the multi-fetch
  result and push cache_tags from every usable hit; this covers both
  the full-hit short-circuit and the partial-hit/error-path response
  reconstruction.
- Entity schema-resolved tags (extract_cache_keys): push per-entity
  invalidation_keys derived from @cacheTag and the subgraph/type
  template tag.
- Per-entity surrogate keys (insert_entities_in_result): push
  apolloEntityCacheTags from the subgraph response extension as they
  are added to invalidation_keys.

Internal __apollo_internal:: prefixed tags are filtered out via
record_external_cache_tags so they cannot leak through the aggregator.

Refs #9481
Extend supergraph_service map_response to read the per-request
CacheTagsAggregator and emit a configurable response header so a CDN
(or any downstream consumer) can perform tag-based purging keyed on the
router's response_cache invalidation tags.

Behavior:
- Off by default (propagate_cache_tags.enabled=false). Existing
  deployments are unchanged.
- When enabled, tags are sorted lexicographically for deterministic
  output and joined with the configured separator.
- An empty aggregated set suppresses the header rather than emitting
  an empty value.
- Overflow above max_bytes obeys on_overflow: truncate (default), drop,
  or header_per_tag. Truncate/drop log a structured tracing::warn! with
  max_bytes, actual_bytes, and dropped_count.
- Invalid header names or values are logged at warn level and skipped
  rather than panicking.

The aggregator is also exposed on the request context as a typed
extension (CacheTagsAggregator), accessible to coprocessor and rhai
without any additional plumbing.

A pure helper build_cache_tag_header returns a CacheTagHeaderPlan so
formatting (dedup-via-set, sort, separator, overflow, empty
suppression) can be unit-tested without an HTTP response in hand.

Refs #9481
…_tags

Regenerated via `INSTA_UPDATE=always cargo test --package apollo-router
--lib configuration::tests::schema_generation`. Captures the new
PropagateCacheTagsConfig and OverflowPolicy entries plus the
propagate_cache_tags field on response_cache Config.

Closes #9481
…i/coprocessor

When `propagate_cache_tags.enabled`, mirror the aggregated tag set onto the request
context under `apollo::response_cache::cache_tags` (sorted JSON string array) and register
the `APOLLO_RESPONSE_CACHE_TAGS_KEY` rhai global. This is a read surface: scripts and
coprocessors read the set and rewrite the response header to customize what reaches a CDN
(their map_response runs after response_cache emits the default header, so their value wins).

- plugin.rs: CONTEXT_CACHE_TAGS const + context mirror in supergraph map_response
- rhai/engine/mod.rs: APOLLO_RESPONSE_CACHE_TAGS_KEY global
- rhai integration test (it_can_read_response_cache_tags_and_rewrite_header) + fixture
- customization.mdx / overview.mdx: document the read + header-rewrite flow
- changeset: describe the context exposure accurately

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cargo fmt (imports_granularity=Item, group_imports=StdExternalCrate per CI); gitleaks: allowlist customization.mdx for curl-auth-header + generic-api-key, mirroring the existing invalidation.mdx allowlist (env-placeholder curl examples).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix numbered list → bullets, add code block language specifiers,
remove trailing periods from list fragments, improve verb tenses
and word choices per AI style review suggestions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
this bit of code missed the tower mock refactor
@aaronArinder
aaronArinder requested a review from a team as a code owner July 15, 2026 15:19
@apollo-librarian

apollo-librarian Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

✅ Docs preview has no changes

The preview was not built because there were no changes.

Build ID: 868dc863f48cfed29fb847d6
Build Logs: View logs


✅ AI Style Review — No Changes Detected

No MDX files were changed in this pull request.

Review Log: View detailed log

This review is AI-generated. Please use common sense when accepting these suggestions, as they may not always be accurate or appropriate for your specific context.

@aaronArinder
aaronArinder marked this pull request as draft July 15, 2026 15:54
@github-actions

Copy link
Copy Markdown
Contributor

@aaronArinder, please consider creating a changeset entry in /.changesets/. These instructions describe the process and tooling.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants