createCachedKeyResolver

@atiproto/key-resolver

Returns a KeyResolver that wraps createFetchKeyResolver with a SimpleStore cache in front of the DID document fetch. Multiple fragments on the same DID share a single network request, and multiple records sharing a signer share the cached document.

Signature

typescript
function createCachedKeyResolver(
options?: CachedKeyResolverOptions,
): KeyResolver
OptionTypeDefaultDescription
plcUrlstring"https://plc.directory"PLC directory base URL.
timeoutnumber3000Milliseconds before the fetch is aborted.
fetchtypeof fetchglobalThis.fetchOverride the global fetch.
cacheSimpleStore<string, DidDocument>SimpleStoreMemory (1hr TTL)Cache keyed by full DID string.

Cache behavior

  • Cache key is the bare DID (e.g. did:plc:abc). Fragment lookups happen in-process from the cached document.
  • did:key: references skip both the fetch and the cache.
  • On a cache miss the document is fetched and written back before the resolver returns.
  • DID rotation isn't free here, since keys can change. Use a TTL short enough that compromised keys can't keep verifying indefinitely (the in-memory default is 1 hour).

Edge (Cloudflare Workers)

On Cloudflare Workers, pair with @atiproto/edge-resolver-cache for an in-memory L1 backed by the Cache API L2:

typescript
import { verify } from "@atiproto/atproto-attestation";
import { createCachedKeyResolver } from "@atiproto/key-resolver";
import { createDidCache } from "@atiproto/edge-resolver-cache";
const keyResolver = createCachedKeyResolver({ cache: createDidCache() });
export default {
async fetch(req: Request) {
const result = await verify({
record,
repository,
keyResolver,
});
return Response.json(result);
},
};

Node / generic runtimes

The default in-memory cache works everywhere. For long-running services, supply your own store backed by Redis, Memcached, or similar:

typescript
import { createCachedKeyResolver } from "@atiproto/key-resolver";
const keyResolver = createCachedKeyResolver({
cache: myRedisBackedStore, // SimpleStore<string, DidDocument>
timeout: 5000,
});