# Reactivity & Atom

**Unstable:** Every module in this section is imported from `effect/unstable/reactivity`. The
`unstable` namespace ships in core `effect` but its API may change between minor
releases. Pin your version if you depend on it.

The reactivity modules give Effect a small, framework-agnostic reactive state
system. You declare values as **atoms**, and an **`AtomRegistry`** evaluates
them, caches results, tracks which atoms depend on which, runs the effects and
streams they describe, and disposes nodes once nothing observes them.

## The mental model

An `Atom` does not hold a value. It *describes how to read one*. The registry is
the runtime owner of the actual cache:

- Reading an atom (`registry.get(atom)`) creates or reuses a node, evaluates the
  atom if its value is missing or stale, and records any nested reads as
  dependency edges.
- Calling `get(other)` **inside** an atom's read function creates a dependency
  edge. When `other` changes or refreshes, every dependent atom is invalidated
  and re-read on demand.
- Writing a writable atom updates its node, invalidates dependents, and notifies
  subscribers after the current batch settles.
- A node lives as long as something observes it (a subscription, a scoped
  `mount`, or a dependent child). When the last observer disappears,
  non-`keepAlive` atoms can be disposed immediately or after their idle TTL,
  which also runs finalizers and may rebuild derived values on the next read.

Because the cache lives in the registry, the *same* atom object can hold
different values in different registries. Use a separate registry per UI root,
request, test, or route boundary that needs isolated state.

## End-to-end example

```ts
import { Atom, AtomRegistry } from "effect/unstable/reactivity"

const count = Atom.make(0)
const doubled = Atom.make((get) => get(count) * 2)

const registry = AtomRegistry.make()

registry.set(count, 21)
registry.get(doubled)
// 42
```

`doubled` never recomputes on its own — it recomputes the next time it is read
after `count` has been invalidated by the `set`.

## The pieces, and when to use each
**Atom**
Declare reactive values: synchronous state, derived reads, effects, streams,
    command-style functions, and persisted/URL-backed state.
    [Read more →](https://effect.plants.sh/reactivity/atom/)

**AtomRegistry**
The runtime that owns the node graph: evaluates reads, caches values, tracks
    dependencies, and disposes unobserved nodes.
    [Read more →](https://effect.plants.sh/reactivity/atom-registry/)

**AsyncResult**
The value an effectful or async atom produces: `Initial`, `Success`, or
    `Failure`, each with a `waiting` flag.
    [Read more →](https://effect.plants.sh/reactivity/async-result/)

**Reactivity**
Key-based invalidation that connects writes to dependent reads — queues,
    streams, and mutations keyed by application data.
    [Read more →](https://effect.plants.sh/reactivity/invalidation/)

**AtomRef**
Local mutable cells and SSR hydration helpers for moving server-computed
    atom values to the client.
    [Read more →](https://effect.plants.sh/reactivity/atom-ref/)

**Server state**
Bind atoms to a server via RPC (`AtomRpc`) or an HTTP API
    (`AtomHttpApi`).
    [Read more →](https://effect.plants.sh/reactivity/server-state/)
**Note:** This is the framework-agnostic core. There is no React (or other UI) binding in
`effect/unstable/reactivity` itself — the registry exposes `subscribe` and
`mount` so a framework adapter can wire atoms to its render loop.