Learn how the Memento pattern fits immutable Clojure data, including undo stacks, snapshots, and state history, and how to manage snapshot size without confusing mementos with event logs.
Memento pattern: A pattern for capturing enough state at one moment to restore it later without exposing every internal detail of the object or system being preserved.
Memento fits Clojure unusually well because immutable values make snapshots natural. When a state value changes, the previous value can often be kept directly instead of being copied defensively. That does not make the pattern free, but it does make it much simpler than in mutable object models.
A basic undo history can be represented directly:
1(defn push-state [history current-state]
2 (conj history current-state))
3
4(defn restore-state [history]
5 [(peek history) (pop history)])
Because the states are immutable values, the snapshot is not a live object that might continue changing behind your back. That removes a lot of complexity from the pattern.
1(def app-state
2 (atom {:current {:title "Draft" :body ""}
3 :history []}))
4
5(defn update-document! [f & args]
6 (swap! app-state
7 (fn [{:keys [current history]}]
8 {:current (apply f current args)
9 :history (conj history current)})))
10
11(defn undo! []
12 (swap! app-state
13 (fn [{:keys [current history]}]
14 (if (seq history)
15 {:current (peek history)
16 :history (pop history)}
17 {:current current
18 :history history}))))
The pattern is clear:
It is important not to confuse Memento with event sourcing:
If you need exact historical causality, replay, or audit semantics, event sourcing may be the better model. If you mainly need undo, rollback, or temporary history, Memento is often enough.
The pattern becomes more expensive when:
In those cases, it may be better to store:
Immutable data helps, but it does not make memory costs disappear.
flowchart LR
A["Current state"] --> B["Save snapshot"]
B --> C["History stack"]
C --> D["Restore previous state"]
The central question is always: what exactly needs to be recoverable later?
Memento goes wrong when:
A snapshot mechanism should preserve the state you need, not every detail you happen to have nearby.
Use Memento for undo, rollback, and local recoverability. Store only the state that actually matters for restoration. If you need durable historical intent rather than recoverable snapshots, consider event sourcing instead.