Documentation: 0.5.0 (source: v0.5.0).
# Caching and provenance

> How snapshots are keyed, when they expire, and how to tell where a value came from.

Markdown source of https://docs-v0-5-0.atlas-kit-docs.pages.dev/concepts/caching/ — see https://docs-v0-5-0.atlas-kit-docs.pages.dev/ai/ for the full machine-readable surface.

Every read goes through a cache, and every result knows where it came from.
Understanding both is what lets you tune an application's RPC traffic without
guessing.

## The cache key is an identity, not a call

Two reads of the same account through the same context return **the same
immutable snapshot** — not an equal copy, the same object — until it expires.

The key is: cluster identity, program address, account type, account address,
and the stable identity of the account definition used to decode it.

That last part matters more than it looks. Two decoders can never consume or
overwrite one another's data, because a different definition means a different
cache slot. It is why the SDK can hold several typed views of the same bytes
without them interfering.

The practical consequence: reading a fleet through `character.fleets.all()` and
reading the same fleet directly hits the same entry. You do not need to hoard
results yourself to avoid duplicate fetches.

## Freshness is a per-read decision

```ts
const sage = createSageClient({
  cluster: 'zink-ptr',
  rpc,
  defaultMaxAgeMs: 10_000,
});
```

That default applies everywhere unless a specific call overrides it. Raising it
cuts RPC traffic; lowering it costs requests. There is no universally right
value, because it depends on what you are reading — see the note on market data
in [markets](/guides/markets/).

## Commitment levels can coexist

Each typed slot may hold one snapshot per commitment level, so a lagging
stronger view and a newer weaker view can both be cached without fighting. A
read at a given commitment gets the snapshot for that commitment.

## Provenance answers "where did this come from?"

Snapshots carry read metadata: the strategy that produced them, the slot, and
the commitment. So "is this fresh?" and "was this served from cache?" are
always answerable rather than inferred.

The [interactive examples](/start-here/first-read/) make this visible — running
two examples on one page, the second completes in a fraction of the time
because it reuses what the first fetched.

## Contexts are isolated

Two contexts are genuinely independent: separate caches, separate endpoints.
That is what makes it safe to run several in one process, and why creating a
context does no network work.

Reconstructing an equivalent account definition creates an intentionally
separate cache partition. That is deliberate, not a leak — but it does mean
definitions should be treated as stable singletons rather than rebuilt per
call.

## Reference

- [`client`](/reference/client/) — context, cache, and provenance exports
- [How the SDK thinks](/start-here/how-it-thinks/) — the short version
