TieredStore
@atiproto/edge-resolver-cache
Implements SimpleStore by composing two stores into a read-through L1/L2 cache. On a cache miss, L2 is checked and a hit populates L1. Writes go to both tiers.
Constructor
typescript
new TieredStore<K, V>(l1: SimpleStore<K, V>, l2: SimpleStore<K, V>)
| Parameter | Type | Description |
|---|---|---|
| l1 | SimpleStore<K, V> | The fast, short-lived tier. Typically a SimpleStoreMemory instance. Checked first on reads. |
| l2 | SimpleStore<K, V> | The durable, slower tier. Typically a CacheApiStore instance. Checked on L1 miss; results are backfilled to L1. |
Read-Through Behavior
On get(key):
- Check L1 — return immediately on hit.
- Check L2 on L1 miss — backfill L1 and return on hit.
- Return
undefinedon L2 miss.
On set(key, value) and del(key): both tiers are written concurrently.
Example
typescript
import { CacheApiStore, TieredStore } from "@atiproto/edge-resolver-cache";import { SimpleStoreMemory } from "@atproto-labs/simple-store-memory";const tiered = new TieredStore(new SimpleStoreMemory({ max: 1000, ttl: 3_600_000 }), // L1: 1hr, 1000 entriesnew CacheApiStore({ prefix: "did:", ttlSeconds: 86400 }), // L2: 24hrs);await tiered.set("did:plc:abc123", didDocument);const doc = await tiered.get("did:plc:abc123"); // hits L1
Factory Functions
For the common case of caching DID documents or handles, use the built-in factories which return pre-configured TieredStore instances:
typescript
import { createDidCache, createHandleCache } from "@atiproto/edge-resolver-cache";// TieredStore with sane defaults for DID doc cachingconst didCache = createDidCache({ cacheName: "my-cache" });// TieredStore with sane defaults for handle cachingconst handleCache = createHandleCache({ cacheName: "my-cache" });