Implementation status
Check which Astilba Cache methods, helpers, drivers, and adapters work in the current unreleased source build.
Astilba Cache is unreleased. The portable correctness kernel and the main Workers source path are active. The Workers composition now keeps construction I/O-free, acquires request-scoped platform handles lazily, and carries its own request-driven recovery ticks. React Router provides scope-aware L3 dependency collection and response tags. Elapsed TTL and grace policy, CDN purge delivery, several convenience methods, and production release gates remain incomplete.
Use this page as the preview ledger. “Implemented” means behavior exists in the reviewed source snapshot and is exercised by the repository’s test lanes. It does not mean the package has an npm installation or production support commitment.
This ledger was reviewed against Cache source commit 726e1b0 from 27 July 2026. The Cache repository is not publicly accessible, so the identifier is maintainer provenance rather than a checkout link. Later source changes are not documented here until this snapshot advances.
Use API reference for exact exported shapes. When another page and this ledger appear to differ, follow this page and report the stale page.
Configuration requirements
Section titled “Configuration requirements”| Requirement | Current boundary |
|---|---|
namespace, clock, rng |
Required by raw createCache(). createWorkersCache() supplies Clock and Rng. |
l2 |
Required when a read must run its factory. Without L2, a fill throws NotImplementedError. |
l1 |
Optional. Required if principal-derived, L1-only values should survive beyond the current call. The Workers factory supplies bounded memory(). |
registry |
Required by expire(), delete(), and clear(). |
registry + bus + l2 |
Required for coordinated read validation and mirror recovery. Registry plus Bus without L2 throws at construction. |
| Workers bindings | createWorkersCache() requires a stable name, KV namespace, and Coordinator Durable Object namespace. The Coordinator separately requires the same KV namespace under REGISTRY_KV. |
| Workers compatibility | Use a compatibility date of 2024-09-23 or later and enable nodejs_compat. The root package uses node:crypto, and that flag also supplies the AsyncLocalStorage support the React Router adapter needs. nodejs_als alone cannot boot the package. |
Implemented in the root API
Section titled “Implemented in the root API”| Surface | Current behavior |
|---|---|
createCache() |
Builds the cache facade and optional invalidation reader and poller without performing I/O. Retention registration and Bus establishment are deferred until the first read or purge that uses them. |
getOrSet() |
Reads L1 then L2 or fills a value with compatible in-isolate singleflight. If a shared factory fails transiently, a waiting caller can still make its own stale-on-error decision using the stale candidate it read before joining. When an opted-in 404 takes the negative disposition, it resolves as undefined; callers using the plain form must include undefined in T. A terminal fenced fill throws FencedError. |
getOrSetEntry() |
Adds skip() and returns value, the tier actually observed, stale and skip state, elapsed age, optional serve-on-error metadata, and only the durability evidence that serve can prove. After a shared transient failure, it preserves the entry form’s miss result when its own candidate is no longer servable. A fresh cached negative reports value: undefined with the actual tier and durability evidence. |
| Consistency defaults | A per-call consistency overrides defaults.consistency; an omitted value otherwise resolves to eventual. |
| Strong reads and fills | Live-check stored entries and pre-check strong misses when coordinated invalidation is configured. Registry failure throws RegistryUnavailableError, or defaults.onUnavailable: “eventual” degrades that call and emits strong_degraded. A verified mid-fill hard purge can trigger a bounded re-mint and refetch. |
| Unknown error posture | unknownPolicy: “error” throws UnknownTagError instead of refilling. takedownSensitive selects the same outcome and outranks an explicit unknown policy. |
expire(), delete(), clear() |
Apply soft, hard, and namespace invalidation through a supplied Registry. |
collect() |
Records explicit dependencies and decides scope, timing, and byte/count budget eligibility at header commit. React Router binds it per request so served hits and fills contribute tags and scope evidence automatically. |
explain() |
Witnesses a default-public key in L1 then L2, its stored identity, current local invalidation verdict and reader state, including Bus channel state, and any request-scoped render attribution. It distinguishes present and proven absent, and returns read-failed when a classified Store read was suppressed and no tier supplies the entry. |
| Factory dependency tags | setTags() replaces the call-level base and dependsOn() adds memberships. The validated settle-time union is stored and used by render collection and write-back fencing. |
| Classified Store failures | Retryable classified L2 writes are suppressed into a non-durable fill. A classified Store read failure emits store_read_suppressed and is a plain serving-path miss; unclassified read failures propagate unchanged. |
| L2 negative-write guard | Before writing a negative, Cache reads the current L2 entry and applies the serving path’s codec and invalidation checks. It refuses the write when it finds a decodable value that is fresh or stale, or when that value’s invalidation verdict cannot be established. The value remains stored and the attempted negative is non-durable. |
memory() |
Provides a bounded per-instance LRU Store. It enforces maxEntries, UTF-8 maxBytes, and Store-level expiry when constructed with a Clock. |
t, compound() |
Build branded tags. t validates the complete final grammar and byte budget; compound() provides positional delimiter escaping. |
duration() |
Builds computed duration strings and rejects non-positive, non-finite, fractional-millisecond, or unsafe products with InvalidDurationError. |
httpError(), isRetriableHttp() |
Preserve HTTP status information and implement the default stale-on-error classifier. |
Custom Codec and Lock |
Participate in decode safety, fill identity, cross-isolate exclusion, and write arbitration when supplied. |
| Telemetry | Uses the exported TELEMETRY_EVENTS catalog, emits plain events or HMAC-pseudonymizes hosted string fields, and isolates sink throws or rejections with optional onSinkError. |
Scope resolution, negative-entry safety, serve-time stale revalidation, codec identity checks, classified L2 write failures, eventual fail-closed behavior, snapshot-capable recovery, and write-back fencing are also implemented. With notFoundTtl, an HttpError 404 has three singleflight dispositions:
- A factory-running caller with
graceand a still-servable stale value suppresses the negative write. Every compatible joiner inherits that value and its evidence. - If that candidate revalidates as dead or unknown, the leader attempts one negative L2 write and every compatible joiner inherits the negative result.
- If the leader has no grace-eligible candidate, it attempts the negative once and shares the not-found fact. A waiter with
graceand a still-servable stale value may return it; one without a servable stale candidate returnsundefined.
Serve-time validation can still throw when the configured Registry-unavailable posture does not permit a verdict.
The L2 negative-write guard resolves a Registry gap toward refusal rather than risking displacement. The current 404 outcome still surfaces undefined at tier: “origin” with durable: false, but L2 is unchanged and no L1 cleanup runs. The guard does not inspect L1. Codec-incompatible, undecodable, or dead L2 bytes do not trigger it; normal newer-envelope arbitration still applies afterward.
Both a guard refusal and a stale candidate suppressing the 404 emit neg_suppressed. A retryable Store write failure is a separate non-durable outcome. A waiter that returns its own candidate retains that candidate’s evidence.
Implemented source adapters and evidence
Section titled “Implemented source adapters and evidence”| Entry point | Current behavior |
|---|---|
@astilba/cache/cloudflare |
Exports createWorkersCache, cloudflareKV, Coordinator, doRegistry, doBus, redialingDoBus, and their public configuration types. |
@astilba/cache/react-router |
Exports root server middleware, typed Cache context, current request access, default L3 budget and ineligibility event constants, and the observable poll-tick event and interval constants. |
| Recovery poller | Observes pointer liveness, runs bounded delta and snapshot recovery, and backs baseline polling off on failure. createWorkersCache() drives both polling and lazy Bus redial from request-time reads; React Router can additionally adopt middleware ticks into the response lifecycle with waitUntil. |
| Local chaos demo | An unpublished React Router v8 app composes the real Workers factory with local KV and Coordinator bindings. Demo-owned wrappers inject a KV backend failure, refuse future Bus dials, or make mirror reads unavailable while leaving live Registry RPC intact. The last fault does not close an already-established socket. The app prints observed outcomes beside documented permissions and asserts no SLO. |
| Composed demo boot witness | A required CI lane builds that demo, boots its emitted Worker on local workerd with the real Coordinator and KV bindings, and reads a machine-facing status route. The healthy arm must reach established; an armed Bus-dial refusal is the negative control and must report never-established plus bus_dial_failed. The lane proves the app is wired to expose those states, not kernel semantics or deployed behavior. |
The two adapter subpaths are present in the source and publish export map, but no package has been published. The poller is an internal seam and the demo is an unpublished workspace app; neither creates another public package entry point.
Partial or provisional behavior
Section titled “Partial or provisional behavior”| Surface | Current boundary |
|---|---|
| TTL and grace | Duration builders work, but stored TTL and grace fields are zero and elapsed expiry is not enforced. Defaults for TTL and grace are not applied. Entry age is now measured from the served envelope’s bornMs fill-start timestamp; it is observability, not TTL enforcement. |
notFoundTtl |
Its presence allows an HttpError 404 to take one negative L2 write attempt, but the duration is not enforced. A negative fill and a later read that reaches the invalidation-fresh negative surface undefined, never the internal stored placeholder. A refused negative or suppressed retryable write failure leaves the origin outcome non-durable. Negative entries remain excluded from grace and stale-on-error. |
| Negative L1 cleanup | A negative result that reaches the serve path skips L1 hydration and best-effort deletes any older L1 copy unless the L2 negative-write guard refused the write. This cleanup still runs after a classified retryable L2 write failure. A failed L1 delete does not block the call; the older value can remain readable until that tier evicts it or a later value fill overwrites it. A guard refusal leaves both tiers unchanged. |
| Eventual stale refresh | The stale value is returned, but refresh work is currently awaited before that response resolves. Background adoption, queue retry, and latency decoupling are incomplete. |
| Factory cancellation and grace context | The factory receives a fresh AbortSignal, but the kernel does not abort it on a cache deadline. ctx.graced is not populated. |
compound() validation |
Positional escaping works, but compound parts do not receive t’s remaining character or 256-byte validation in the reviewed snapshot. Keep parts grammar-safe. |
| React Router response caching | Automatic dependency and scope collection, Cache-Tag emission, safe private demotion, immutable-response rebuilding, and an overridable 16 KB / 1,000-occurrence budget work. The middleware never invents public or s-maxage; the application must opt into shared caching. |
| Factory response qualifier | FactoryCtx.dependsOn(tag, { l3: false }) throws until stored per-tag emission metadata exists. The same qualifier works on RenderCollector.dependsOn(). |
| Explain scope and authority | explain(key) addresses only the default public canonical key. It uses current local knowledge and performs no live check, resync, or L1 hydration. |
| Telemetry catalog | neg_suppressed is live for a 404 suppressed in favor of a grace-eligible stale value or refused by the L2 negative-write guard. registry_degraded and state_stale are reserved names with no emit sites. createWorkersCache() accepts kernel telemetry, but its fixed internal memory L1 still has no separate private_evicted sink. React Router middleware telemetry also remains an explicit option. |
| Purge result | matchedHint is always “unknown”; flushed() and edgePurged() resolve without tracking the promised completion boundaries. |
| Key invalidation | { key } targets the contextless public canonical key only. Use dependency tags for tenant or principal-derived variants. |
| Scope-qualified tag selectors | The selector type accepts scope, but Registry tag resolution ignores it. A tag purge affects every entry carrying that tag. |
| Lock option | lock: true uses a configured Lock; without one it silently continues without cross-isolate locking. No production Lock adapter is exported. |
| Coordinator journal | Durable and replayable, but append-only without production checkpointing or truncation. |
| Workers measurements | Workerd lanes, the local chaos demo, and the required composed-app boot witness cover local composition and failure posture. Deployed consistency, propagation, caching, and production-threshold measurements are still pending. |
defaults.consistency, unknownPolicy, onUnavailable, takedownSensitive, maxEntryRetention, maxSyncLag, and heartbeatInterval are consumed. maxSyncLag tunes the attached recovery poller; heartbeatInterval tunes the reader’s silence threshold and must be coordinated separately with the Coordinator deployment variable.
Throwing placeholders
Section titled “Throwing placeholders”These exports or paths currently throw NotImplementedError:
globalTag()expireAll()anddeleteAll()FactoryCtx.reuseGraced()FactoryCtx.setTtl()FactoryCtx.dependsOn(tag, { l3: false })- a factory fill with no L2 Store
expire(),delete(), orclear()without a Registry
Declared but inert surfaces
Section titled “Declared but inert surfaces”These APIs currently return normally or exist in the types but do not apply their intended behavior:
CacheConfig.cdnand thecdnmode ondelete()do not invoke a CDN driver.defaults.graceBackoffis not consumed.Tierincludes“l1.5”, but the current read path does not emit it.
expireAll() and deleteAll() still require their explicit origin-load guard at the type level, but the methods do not run yet.
Integrations not present
Section titled “Integrations not present”There is no Redis or Valkey adapter, production Lock, CDN purge path, or deployed-probe package. React Router is the only shared-response adapter. Its fixture and the Cloudflare integration Worker are tests, while the local chaos demo is an evidence app; none of them is a production application template.
Related
Section titled “Related”- Source walkthrough follows the smallest reviewed source configuration.
- Cloudflare Workers documents the current runtime factory and bindings.
- Cache HTTP responses documents the implemented L3 collection and header boundary.
- Inspect cache behavior documents
explain()and the telemetry catalog. - API reference documents every root and adapter export.
- Runtime architecture maps configuration requirements to capability contracts.
- Driver implementations gives component-level implementation detail.