mobx-state-tree: a typed, transactional state container on top of MobX
Full-featured reactive state management without the boilerplate
At a glance
- What is it?
- MST wraps MobX observables in a typed model tree with snapshots and actions. It suits TypeScript teams that want structure without Redux ceremony, and it costs you a schema for every piece of state.
- Who is it for?
- Adopt mobx-state-tree if your team already writes TypeScript and wants typed models, snapshots and time-travel-friendly actions without Redux boilerplate; skip it if your state is mostly server cache, or if you want plain objects and minimal ceremony. Before committing, verify how the v8.0.0 release behaves with your MobX version, and check that the snapshot format your app persists still round-trips through the models you define.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 28 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem MST solves for TypeScript app teams
MobX gives you observables and reactions. It does not tell you what shape your state has, how two stores relate, or how to serialize everything for persistence. mobx-state-tree, usually shortened to MST, adds that layer: a state container system built on MobX, in the project's own words. You describe state as models, and the library enforces the description at runtime.
The target reader is a team building a React or React Native app in TypeScript where state is expected to grow. The README says MST is valuable in a large team but also useful in smaller applications when you expect your code to scale rapidly. The pitch against Redux is explicit: better performance and much less boilerplate. That is a claim from the project, not a measured result, and how it plays out depends on what your reducers were doing.
What you actually get is a schema. A model declares its fields and their types, references between models are checked, and mutations go through actions so changes stay traceable. In a codebase with several contributors, that schema is the part that keeps state from drifting.
How models, references and snapshots fit together
The README's example shows the core mechanism. types.model defines a shape with fields such as types.string, types.number and types.identifier. An array field is types.array(Author). A relationship is types.reference(Author), which the comment says stores just the id. So the tree holds identifiers, and the reference resolves through the tree at read time rather than embedding a copy of the object.
Instances come from create. You build an Author with Author.create({...}), build a Tweet that points at the author's id, then build the root store from arrays of those instances. From that point the tree is observable, and a React component wrapped in observer from mobx-react-lite re-renders when a field it read changes. The README notes that if you are not using React you can listen to changes with onSnapshot.
Snapshots are the other half. The project credits Dan Abramov's work on Redux as an influence on the idea of snapshots and transactional actions in MST, and the package description calls itself an opinionated, transactional, MobX powered state container. Transactions mean a group of mutations can be applied as one unit, which is what makes undo, replay and persistence plausible rather than something you bolt on later.
The README credits Giulio Canti's tcomb and type systems generally as an influence on MST's type system, which is a fair description of what it feels like: a runtime type layer that also produces TypeScript types.
Installing mobx-state-tree and defining your first model
The project publishes to npm under the name mobx-state-tree, and the README points to the Getting started tutorial on mobx-state-tree.js.org for the full walkthrough. Install the package alongside MobX itself, since MST depends on it:
npm install mobx mobx-state-treeAfter that, define a model with types.model and create an instance. This is the smallest version of the README example:
import { types } from "mobx-state-tree"
const Author = types.model({
id: types.identifier,
firstName: types.string,
lastName: types.string
})
const jamon = Author.create({ id: "jamon", firstName: "Jamon", lastName: "Holmgren" })If you pass a wrong type or omit a required field, creation fails at that point rather than surfacing later in a render. To use the tree in React, wrap the component with observer from mobx-react-lite and read fields directly:
import { observer } from "mobx-react-lite"
const MyComponent = observer(() => <div>Hello, {jamon.firstName}!</div>)The README states that any change to a field the component read causes a re-render, which is the targeted re-render behaviour the project advertises. The README also notes you do not need to know MobX to use MST, though the mental model of observables helps once you start writing reactions.
Where mobx-state-tree gets in your way
Every piece of state you put in the tree needs a type. That is the point, and it is also the tax. Ad hoc objects that change shape as a feature is prototyped do not fit; you either model them properly or leave them outside the tree, and then you have two kinds of state in one app.
References are a good example of the trade-off. types.reference(Author) stores only the id, which keeps snapshots small and avoids duplicated data. It also means a reference can fail to resolve if the target is not in the tree, and the README example sidesteps this by passing jamon.id at creation time. Nothing in the README describes what happens on a dangling reference, so that is a behaviour to confirm in the docs before you rely on it for persisted data.
The React integration is a second constraint. The README's example uses mobx-react-lite and the observer wrapper; the project's topic list includes mobx-react as well. If your team has settled on a different rendering model, the snapshot and onSnapshot path exists, but you are then wiring the subscription yourself.
MST is also the wrong tool when your problem is server cache rather than client state. A tree of typed models is not a request cache, and using it as one means reimplementing invalidation and refetching that a cache library handles directly.
mobx-state-tree vs Redux and vs plain MobX
Against Redux, the difference is where structure lives. Redux asks you to write reducers, action creators and selectors, and to keep state updates immutable by hand or through a toolkit. MST puts the schema in the model and lets MobX handle change propagation, so the boilerplate the README complains about mostly disappears. The cost is a runtime type system you now have to learn, and a dependency on MobX's reactivity model rather than plain functions.
Against plain MobX, the difference is enforcement. MobX alone will happily observe any object you mark observable, with no schema and no snapshot format. MST adds the tree, the types and the snapshot, which is exactly what you want when state must be serialized or shared across a team, and exactly what you do not want when a small observable store is enough.
A third comparison people search for is against newer store libraries. The relevant difference is that MST is a model layer with identity and references built in, while a minimal store is usually a single object with setters. If your state has real entities with relationships, the model layer earns its keep. If it is a handful of flags, it does not.
Version 8, maintenance and what the licence allows
The latest release is v8.0.0, published on 2026-09-02, the same day as the last push to the master branch. The project is not archived. That is a recent release, and the repository carries a changelog.md at the top level, which is where upgrade notes belong; the README itself does not document a migration path from v7 to v8, so read the changelog before bumping a major version.
Upgrade cost is mostly the major-version boundary. A v8 release after v7.4.0 in late August suggests active work, and the package's build scripts run TypeScript compilation plus rollup, with a size-limit check in the test:all script. That size check is a useful signal about how the maintainers treat bundle growth, since it fails the suite when the bundle grows past its budget.
The licence is MIT, stated in the repository's LICENSE file and in the package metadata. MIT permits commercial use, modification and redistribution with the copyright notice retained. That is a permissive licence with no copyleft obligation on your application code, but it is not legal advice and your own counsel should confirm how it interacts with anything you vendor or republish.
One practical note from the repository layout: the Dockerfile and docker-compose.yml at the top level build the Docusaurus website, not the library. They expose ports 3000 and 35729 and mount the docs and website directories. If you were hoping those files describe a production deployment for MST itself, they do not.
Editorial conclusion
Adopt mobx-state-tree if your team already writes TypeScript and wants typed models, snapshots and time-travel-friendly actions without Redux boilerplate; skip it if your state is mostly server cache, or if you want plain objects and minimal ceremony. Before committing, verify how the v8.0.0 release behaves with your MobX version, and check that the snapshot format your app persists still round-trips through the models you define.
Frequently asked questions
What is mobx-state-tree?
It is a state container system built on MobX, described in its own package metadata as an opinionated, transactional, MobX powered state container. You define state as typed models, and the library enforces those types at runtime while MobX handles change propagation.
How is mobx-state-tree different from MobX alone?
MobX is the reactive engine; MST adds structure on top of it, in the README's phrasing. That structure means typed models, references between models, snapshots and transactional actions, none of which plain MobX gives you.
Which is better, MobX or Redux?
The README argues MST offers better performance and much less boilerplate than Redux, and credits Redux's snapshots and transactional actions as an influence on MST's design. That comparison is the project's own claim rather than a measured result, so weigh it against how much structure your state actually needs.
What are the alternatives to mobx-state-tree?
Plain MobX is the closest one: it observes state without a schema, so you lose the typed models and the snapshot format. Redux is the other direction, with explicit reducers and actions instead of a model tree.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mobxjs-mobx-state-tree)