Cache fundamentals
Learn the Astilba Cache vocabulary from a basic read through distributed invalidation.
You can understand Astilba Cache without starting with its distributed machinery. Begin with a key, a factory, and a Store. Add the remaining components only when an application spreads across isolates, machines, and shared caches.
Begin with the read path
Section titled “Begin with the read path”| Term | Plain-language meaning |
|---|---|
| Cache instance | The object returned by createCache(). Application code reads and invalidates through it. |
| Key | The application-facing name of one result, such as product:sku-123. |
| Factory | The async function that loads the value on a miss. The database or upstream API it calls is the origin or source of truth. |
| Hit | Cache found a stored value that is legal to serve. |
| Miss | Cache could not reuse a stored value, so it runs the factory or reports a miss outcome. |
| Entry | A stored value plus metadata such as its tags, scope, codec identity, and invalidation epoch. |
| Namespace | A stable boundary around one cache domain. clear() advances that namespace so older keys become unreachable. |
| Tag | A dependency label. Several keys can carry the same tag and be invalidated together. |
| Scope | A sharing rule: public, tenant-scoped, or principal-derived and local-only. |
getOrSet() returns only the value. getOrSetEntry() also reports where it came from and whether it was stale, skipped, or durable.
Understand the storage tiers
Section titled “Understand the storage tiers”The tier names describe where a value lives, not different value formats.
| Tier | What it is | Typical use |
|---|---|---|
| L1 | An optional Store local to one process or worker isolate. Other instances cannot see it. | Fast repeat reads and retention of principal-derived values that must not enter shared storage. |
| L2 | A Store shared or durable across calls and, depending on the driver, across instances. | The main reusable server-side copy. The current kernel requires L2 whenever a factory must run. The local quickstart uses memory() in this slot only as a non-durable demonstration. |
| L3 | A shared HTTP or CDN response cache outside the value-store path. | Caching rendered responses. The React Router adapter can emit safe dependency tags; CDN purge delivery is not implemented. |
| Origin | The factory result before or while it is written to a Store. | The database or upstream request supplied by the application. |
Both L1 and L2 implement the same Store contract. A runtime decides whether that Store is an in-memory map, a platform KV service, Redis, or another backend.
Separate values from invalidation
Section titled “Separate values from invalidation”Storage answers “do I have bytes for this key?” Invalidation answers “are those bytes still legal to serve?” Astilba Cache keeps those questions separate.
| Component | Responsibility |
|---|---|
| Registry | The authoritative record of soft and hard invalidation watermarks. Purge methods write to it; strong stored-entry reads check it live. |
| Bus | The fast delivery path for ordered invalidation events to active cache instances. A reset or gap makes local knowledge suspect. |
| Replication mirror | Durable L2 pointer, delta, and snapshot objects that let a suspect instance recover invalidation changes it missed on the Bus. |
| Recovery reader | Replays contiguous deltas first, then can use the pointer-blessed snapshot as a recovery floor when a persistent hole exhausts the delta retry budget. It remains fail closed if the chain cannot be established. |
| Replication poller | Drives baseline mirror observation and bounded recovery retries outside the value read. The React Router adapter supplies request-piggyback ticks; other runtimes need an equivalent driver. |
The Bus is not the authority. It transports updates; the Registry and verified local or mirror history establish what is known. Coordinated read validation is built only when Registry, Bus, and L2 are all available. createCache() rejects a Registry-plus-Bus configuration without L2 because that reader would have no safe recovery mirror.
Know the injected capabilities
Section titled “Know the injected capabilities”| Capability | Why it exists | Do basic callers usually choose it? |
|---|---|---|
| Store | Reads and writes encoded values or replication objects. | Use memory() locally or receive a driver from a runtime integration. |
| Clock | Supplies logical time without hard-coding a platform clock into the portable kernel. | The current API requires it; a runtime preset should normally provide it. |
| Rng | Supplies randomness through an explicit, testable source. | The current API requires it; a runtime preset should normally provide it. |
| Codec | Encodes values and identifies their wire format before decoding. | Only when the default JSON round trip is insufficient. |
| Lock | Coordinates opted-in fills across instances and supplies a fencing token. | Only for cross-instance contention. |
| Cdn | Accepts shared HTTP-cache purge work. | The contract exists, but no implementation is wired today. Response-tag emission does not call it. |
| Telemetry sink | Receives cache events; hosted mode pseudonymizes string fields with a project salt. | Only when operating or observing Cache. |
Clock and Rng exist for portability and deterministic tests. They are construction details, not concepts application code should need on every read.
Add components progressively
Section titled “Add components progressively”| Configuration | What it gives you today |
|---|---|
clock + rng + l2 |
Basic read, fill, and reuse without coordinated invalidation. The local quickstart uses memory() for this preview-only shape. |
Add l1 |
Process-local reads and retention for values that cannot be shared. |
Add registry |
Enables the purge methods, but does not create coordinated read validation by itself. |
Add registry + bus alongside the existing l2 |
Live invalidation delivery, coordinated validation, snapshot-capable mirror recovery, and an attached replication poller. The embedding runtime or adapter must supply a tick driver for background recovery; reads still perform reactive recovery without one. |
Add lock |
Lets individual calls opt into cross-instance fill exclusion. |
| Use React Router render collection | Automatically records served Cache entries, rejects non-public response dependencies, and emits eligible user tags. |
Add cdn |
Declares the L3 purge boundary; the current implementation does not drive it. |
Use createWorkersCache() |
Composes memory L1, KV L2, Coordinator Registry, and redialing Bus with Workers defaults. |
Distinguish policy terms
Section titled “Distinguish policy terms”- TTL is how long a value should be fresh by elapsed time. Duration values and the
duration()builder are implemented, but the cache does not enforce elapsed TTL yet. - Grace is the period in which an eligible stale value may be reused after a classified transient failure. Its duration is not enforced yet.
- Eventual consistency uses verified local invalidation knowledge and fails closed when that knowledge is insufficient.
- Strong consistency performs a live Registry check before serving a stored entry and before running the factory for a strong miss when coordinated invalidation is active.
- Soft invalidation makes an older value stale.
- Hard invalidation makes an older value unreadable.
- Singleflight lets compatible callers in one instance share one foreground factory execution.
- Fencing prevents a result produced across a conflicting hard invalidation from being accepted as current. The current fill path can re-mint its birth epoch and refetch within a bounded three-attempt budget when verified knowledge advances.
Continue with the local quickstart for a concrete read, Cloudflare Workers for the composed runtime, Cache HTTP responses for L3 collection, How Cache works for the complete sequence, or runtime architecture for the capability contracts.