Invalidate cached data
Mark dependent values stale, make them unreadable, or invalidate one contextless public key.
In Astilba Cache, tags describe what a value depends on. Invalidation advances tag watermarks, so readers can reject matching entries without scanning or deleting every stored value.
The application changes its source of truth; Cache only changes whether stored representations may be served. See Cache fundamentals for keys, tags, Registry, and Bus.
Choose soft or hard invalidation
Section titled “Choose soft or hard invalidation”| Operation | Effect |
|---|---|
expire() — soft |
Values born before the new soft watermark become stale. An eventual read may return the old value after attempting a refresh for a later read. |
delete() — hard |
Values born before the new hard watermark become unreadable wherever that invalidation is visible. Grace cannot resurrect them. |
const productTag = compound("product", productId)
// Mark every entry carrying the tag stale.await cache.expire({ tag: productTag })
// Make every entry carrying the tag unreadable.await cache.delete({ tag: productTag })Choose a tag builder
Section titled “Choose a tag builder”Use t when the final tag is already in the public tag grammar: lowercase letters, digits, :, _, -, ., |, and %. It rejects an empty value, a reserved __ prefix, off-grammar characters, and values over 256 UTF-8 bytes.
const productTag = t`product:${productId}`Interpolated values are not escaped. A space, slash, uppercase letter, or other off-grammar character throws InvalidTagError rather than being silently rewritten.
Use compound() when positional structure matters. It escapes percent signs and the : and | delimiters, then prefixes the vector’s arity. Delimiter-like values, empty strings, and vectors of different lengths therefore remain distinct.
const productTag = compound("product", productId)const categoryListingTag = compound("category", categoryId, "listing")Caller-supplied tags on getOrSet() and getOrSetEntry() are rejected when they begin with __. The kernel reserves that prefix for its per-key and per-namespace tags. The Tag brand prevents ordinary raw-string selectors; do not bypass it with a type assertion.
Add dependencies discovered by the factory
Section titled “Add dependencies discovered by the factory”Call-level tags are the initial dependency set. A running factory can refine that set:
factory: async (ctx) => { const product = await loadProduct(productId, ctx.signal) ctx.setTags([compound("product", product.id)]) ctx.dependsOn(compound("category", product.categoryId)) return product}setTags() authors a replacement for the call-level base. dependsOn() adds membership independently and is never erased by a later setTags(). At factory settlement, Cache deduplicates and validates the combined set, stores it with the entry, and uses it for invalidation and write-back fencing.
The final entry may carry at most 126 distinct user tags, whether they came from the call or factory. Reserved tags that Cache adds internally do not consume that user allowance. Invalid, reserved, or excessive factory tags fail the fill before anything is stored.
Dependency declaration closes when the factory promise settles. A later dependsOn() or setTags() call through a retained context throws FactorySettledError. FactoryCtx.dependsOn(tag, { l3: false }) is also not implemented and throws; use the render collector’s l3: false option only for render-only dependencies.
Invalidate by key carefully
Section titled “Invalidate by key carefully”The key selector maps a user key to Cache’s reserved per-key tag:
await cache.expire({ key: `product:${productId}` })await cache.delete({ key: `product:${productId}` })In the current kernel, that selector resolves the contextless public canonical key: it has no request or scope input. It does not target principal-derived or tenant-scoped variants of the same user key. Use a dependency tag when data can exist in more than one scope.
The selector types also expose scope on tag invalidation, but the current implementation does not apply it when resolving the Registry tag. Treat a tag purge as affecting every cached entry carrying that tag; do not rely on scope-qualified tag invalidation yet.
Clear a namespace
Section titled “Clear a namespace”clear() bumps the calling instance’s namespace version and issues a hard invalidation for the reserved namespace tag. The version makes old keys unreachable on that instance; the hard watermark makes other readers reject pre-clear entries as the invalidation reaches them.
Understand the result
Section titled “Understand the result”expire(), delete(), and clear() return a PurgeResult with an epoch, matchedHint, flushed(), and edgePurged().
In the current preview:
matchedHintis always“unknown”;flushed()resolves immediately without measuring mirror acceptance;edgePurged()resolves immediately without invoking a CDN queue;- the
cdnoption ondelete()is not wired.
Do not use those completion fields as rollout or takedown guarantees yet.
Configuration boundary
Section titled “Configuration boundary”The purge verbs require a Registry. For reads to observe coordinated invalidation, configure Registry, Bus, and L2 together. L2 remains required for fills and lets suspect readers recover through durable deltas and snapshots.
The source Workers factory wires the Coordinator Registry, redialing Durable Object Bus, and KV mirror. The CDN path and real purge-completion promises are still not implemented.
When React Router render collection is active, a served entry’s stored user tags can also become a Cache-Tag response header. Scope and budget checks run before emission, and reserved tags are filtered. This response tagging does not make the CDN purge path operational; see Cache HTTP responses.
Related
Section titled “Related”- How Cache works follows invalidation through live delivery and recovery.
- Consistency and resilience explains how reads treat stale or unknown knowledge.
- Read and cache values explains the complete factory lifecycle.
- Cache HTTP responses distinguishes stored dependencies from response emission.
- Implementation status records the current purge-result and selector limitations.