Neural networks for JAX · the NNX API (Pythonic, stateful) · verified against Flax 0.12 (2026)

Flax cheat sheet

Flax is the neural-network library for JAX. This sheet focuses on Flax NNX — the modern API that uses regular Python objects with reference semantics: modules are mutable, you call them eagerly, and parameters live on the object (no separate params dict to thread). It pairs with Optax for optimization and bridges cleanly back to pure JAX when you need jit/grad. The older Linen (flax.linen) API is still supported; a migration note is included. Targets Flax 0.12.

modules & layers params & state training loop transforms & functional persistence & Linen gotcha most common

Verified 2026-08-24 against the official docs at flax.readthedocs.io (Flax 0.12, NNX Basics) and the google/flax repo. Built on JAX; optimizers come from Optax. New projects are encouraged onto NNX; Linen remains for existing code.

Outline

NNX feels like PyTorch (stateful, eager) but is JAX underneath. The one non-obvious piece is split/merge — how you cross back into pure-functional JAX for jit/grad.

Define

  1. 1 · Install & a Module
  2. 2 · Built-in layers
  3. 3 · Params, state, train/eval

Train

  1. 4 · grad & Optimizer
  2. 5 · The training step
  3. 6 · nnx transforms (jit/vmap)

Cross over & persist

  1. 7 · split / merge (pure JAX)
  2. 8 · Checkpointing
  3. 9 · Linen (legacy) & migration
  4. 10 · Gotchas
  5. Worth memorizing

Define a Model

Regular Python objects — construct, then call.

1Install & a ModuleNNX
2Built-in layersnnx.*
3Params, state, train/evalwhat's inside

Train

grad and Optimizer, NNX-style.

4grad & Optimizeroptax-backed
5The training stepput it together
6nnx transforms (jit / vmap)JAX-aware

Cross Over & Persist

Drop to pure JAX, save weights, and the Linen bridge.

7split / merge (pure JAX)functional core
8Checkpointingsave weights
9Linen (legacy) & migrationthe old API
!Common gotchasread before shipping

Worth memorizing

NNX is PyTorch-like on JAXstateful modules, eager call, params on the object
construct = initializeMLP(..., rngs=nnx.Rngs(0)) runs init; no lazy init/apply
nnx.Param for weightsnnx.Variable/BatchStat for non-trainable state
value_and_grad + Optimizer.updategrads shaped like the model; update mutates in place
@nnx.jit, not jax.jitthe nnx transforms understand reference state
split / merge = escape to pure JAXgraphdef + state pytree for any jax.jit/grad
train() / eval()toggle Dropout & BatchNorm just like PyTorch
save the state pytree (Orbax)params are arrays; merge back with a fresh graphdef
Linen still works@nn.compact + init/apply; new code prefers NNX