Why Causl

This page is for adopters deciding whether to use causl. It covers what causl exists to solve, how it compares to MobX, Jotai, and Redux Toolkit at high level, and the cases where one of those is a strictly better answer. If you have not read Introduction to Causl yet, read that first; it covers the engine fundamentals this page assumes.

The motivation

The TypeScript reactive-state ecosystem is genuinely good at the problems its libraries were designed for. Redux is excellent at transactional single-store state with time-travel debugging. MobX is excellent at ergonomic observable objects. Jotai is excellent at fine-grained atoms that compose. TanStack Query is the gold standard for server-cache state. Zustand and Valtio prioritise ergonomics and small bundle size. XState is the canonical statechart implementation in the language.

Each one is the right answer for the slice of the problem it owns. None of them is the right answer when the slices overlap. The repeating pattern in real applications — spreadsheets, CMMS, BIM-style asset graphs, capital planning tools, scheduling and Gantt systems, scenario planners, dashboard composers — is that more than one of the following is true at the same time:

The honest engineering answer to those problems used to be: stitch Redux's transactional commits, MobX's auto-dependency tracking, TanStack Query's stale protection, and XState's lifecycle modelling together, and pray your team holds the seams in code review forever. Causl is the single library that closes those seams by construction.

How causl is shaped

Causl is held together by fourteen commitments in SPEC §17.1 — the original eight commitments from the engineering shape, plus four §16A race-detection rows, plus the post-wave capability-cost residual (commitment 13, MECHANICAL), plus the host-tier substrate compatibility contract for the opt-in WASM backend (commitment 14, DESIGN-DISCIPLINE). Each commitment is marked MECHANICAL when a CI gate enforces it or DESIGN-DISCIPLINE when the discipline is enforced by review policy. Kent Beck's framing of commitments-as-contract is the load-bearing argument the SPEC names; Robert Martin and Martin Fowler are cited as counter-checks on the MECHANICAL / DESIGN-DISCIPLINE distinction.

The eight engineering commitments — denotational semantic foundation, transactions as the only mutation boundary, deterministic dynamic-dep cleanup, a single composite statechart, strict model/controller/engine layering, discriminated-union state everywhere, MVU-shaped application surface, and pre-runtime race detection in CI — are the shape the API is allowed to grow into. Every public surface addition has to name an unavoidable engine concept that the existing surface cannot express, or it doesn't ship. Today that means a canonical seven-method Graph plus a curated second tier of nine extensions; SPEC §12.2 audits the surface quarterly.

How causl compares — at a high level

This is the short version of the comparison table on the home page. Each library is the strictly better answer for the problem it owns; the rows below explain why causl's shape is different rather than just bigger.

vs Redux Toolkit

Redux Toolkit's strength is the transactional store plus the time-travel devtools that fall out of it. Every action is an atomic write, every action is logged, and the log is replayable. Causl shares that architectural commitment — graph.commit(intent, tx => …) is the only mutation boundary, and commitLog is the replayable log — but adds three things RTK does not:

Where RTK is the right choice: a flat single store, a small selector graph, a team that wants a well-trodden path with broad community tooling. RTK Query is also the right choice for HTTP cache state specifically; @causl/sync overlaps but is not a drop-in replacement.

vs MobX

MobX is the closest peer in ergonomics — both libraries do automatic dependency tracking, both libraries support derived values. The shape of disagreement is at the commit boundary:

Where MobX is the right choice: an existing MobX codebase you want to improve incrementally, or an application whose state is genuinely object-graph-shaped with no transactional cross-field invariants.

vs Jotai (and Recoil)

Jotai is excellent for fine-grained atoms that compose without ceremony. Atoms support derivations (read-only atoms with a get function), and the dependency graph is built automatically. Where causl differs:

Where Jotai is the right choice: small global state where atomicity does not matter, applications where the atomic-write boundary is cell-by-cell (e.g. an input form), or codebases that already lean into Suspense for everything async.

vs everything else

Zustand and Valtio prioritise ergonomics and bundle size; neither addresses dependency cascades, conflicts, or async safety as first-class concerns. Reach for them when you have a flat store and a small surface. TanStack Query is the right answer for HTTP cache state specifically; @causl/sync is complementary, not a replacement. XState is the closest peer in spirit for lifecycle modelling — causl uses statecharts internally (one composite chart for every lifecycle, per SPEC §6) but adds the dependency engine on top. Reach for XState directly when your problem is "a wizard with five steps and a back button," not "a dependency graph with statecharts governing the async edges."

When to use causl

Reach for causl when two or more of these are true:

When not to use causl

Reach for something else when:

Honest limit — state that is a tree of values. Causl is not the right tool for state that is genuinely tree-shaped. The denotational machinery, the commit pipeline, the IR, the CI gates, and the cost of laying out information-model / controller / engine in separate packages are all overhead a flat store does not need. Causl is over-engineered for simple apps and the only way to ship the complex ones without losing your mind. Pick the right tool — the SPEC is explicit about this at §18 and the README repeats it as a closing summary.

What causl is not

This list is repeated from the repo README because the previous SPEC draft promised too much:

Where to go next

Once you have decided causl fits, the SPEC is the normative source of truth and SPEC.async covers the async-resource statechart. The @causl/core API reference is generated from source on every build. The migration rule catalogue at docs/migration/RULE_CATALOGUE.md maps common Jotai / MobX / Redux patterns to their causl equivalents and pairs each rule with a @causl/migration-check codemod.

← Introduction Documentation →