Browse Learn Clojure Foundations as a Java Developer

Managing Atom State

Use atoms for one independent, in-process identity: model values immutably, update with pure functions, and keep coordination or durability outside the atom.

Atoms are the everyday Clojure tool for one independent state identity. They work best when the changing part of the program can be named clearly and updated without coordinating with another reference.

For Java engineers, the useful mental model is not “a field with magic thread safety.” It is an AtomicReference to immutable data, usually updated with a pure transition function.

Question Atom-friendly answer
What changes? One named identity, such as a metrics snapshot or local cache map.
What stays stable? Each value held by the atom is immutable.
How does it change? swap! applies a function from old value to new value.
What should stay outside? External I/O, multi-identity transactions, and durable storage.

Use this section to move from the basic atom API to practical design decisions: where the atom boundary belongs, how to update it safely, and when another Clojure or JVM concurrency tool is a better fit.

In this section

  • Create and Read Atoms
    Create Clojure atoms for independent in-process state, read them safely with deref, and design the stored value as immutable data rather than a mutable Java object.
  • Update Atoms with swap! and reset!
    Choose swap! when an atom update depends on the current value, use reset! only for direct replacement, and keep swap! functions side-effect free because Clojure may retry them.
  • Design Good Atom Use Cases
    Decide when an atom is the right state boundary for counters, snapshots, caches, and REPL-managed system maps, and when refs, agents, queues, or databases are better.
Revised on Saturday, May 23, 2026