Skip to main content

Datarax: Differentiable Data Pipelines for JAX

CI codecov Build Summary

Project Status: Active

Documentation - Issues


Research preview. The API will change while we iterate toward v1.0, so pin a version if you need stability, and do not put this in production yet. Throughput is still being tuned; the design is settled and the numbers are not.

This is public this early on purpose. Issues, questions and pull requests genuinely steer what gets built next, and a star tells us which layer to push on.


Datarax (Data + Array/JAX) is an extensible data pipeline framework built for JAX-based machine learning workflows. It uses JAX's JIT compilation, automatic differentiation, and hardware acceleration to build data loading, preprocessing, and augmentation pipelines that run on CPUs, GPUs, and TPUs.

Key Features

  • JAX-Native Design: All core components built on JAX's functional paradigm with Flax NNX module system for state management
  • High Performance: JIT-compiled pipelines via XLA, profiled and roofline-analysed through calibrax
  • DAG Pipelines: Graph-based construction via Pipeline.from_dag with branching, parallel execution, caching, and differentiable rebatching nodes
  • Scalability: Multi-device and multi-host data distribution with device mesh sharding
  • Determinism: Reproducible pipelines by default using Grain's Feistel cipher shuffling (O(1) memory), with resumable mid-epoch iteration for exact checkpoint/restore
  • Extensibility: Custom data sources, operators, and augmentation strategies via composable NNX modules
  • Benchmarking Suite: Comparative benchmarks against 14+ frameworks with calibrax-powered analysis and regression checks
  • Ecosystem Integration: Works with Flax, Optax, Orbax, HuggingFace Datasets, and TensorFlow Datasets

Why Datarax?

JAX has mature libraries for models (Flax), optimizers (Optax), and checkpointing (Orbax), but lacks a dedicated data pipeline framework that operates at the same level of abstraction. Existing options are either framework-agnostic loaders that return NumPy arrays (losing JIT/autodiff benefits) or wrappers around tf.data/PyTorch that introduce cross-framework overhead. Datarax aims to fill this gap. The framework is under active development with ongoing performance optimization - the architecture is functional, but throughput and API surface are still being refined.

JAX-Native from the Ground Up

Every component - sources, operators, batchers, samplers, sharders - is a Flax NNX module. Pipeline state is managed through NNX's variable system, which means operators can hold learnable parameters, be serialized with Orbax, and participate in JAX transformations (jit, vmap, grad) without special handling.

Differentiable Data Pipelines

Because operators are NNX modules, gradients flow through the entire pipeline. This enables approaches that are not possible with standard data loaders:

See the differentiable pipeline examples for details.

DAG Execution Model

Pipelines are directed acyclic graphs, not linear chains. Pipeline(stages=[...]) covers the sequential case; Pipeline.from_dag(...) builds arbitrary graphs whose nodes are NNX modules, with composition strategies (sequential, parallel, branching, merging, ensemble) handling multi-path logic. Graph nodes cover field routing (SplitField) and differentiable within-batch regrouping (RebatchNode), while CachingIterator memoizes at the iteration boundary.

Deterministic Reproducibility

Shuffling uses Grain's Feistel cipher permutation, which generates a full-epoch permutation in O(1) memory without materializing the index array. Stochastic operators are keyed on global record positions, so each record augments identically regardless of batch size, shuffle order, or host count. Iterating a random-access pipeline returns a stateful iterator whose get_state()/set_state() capture position and RNG counts for exact mid-epoch resume, and the live module stays consistent at every yield boundary so Orbax checkpoints taken inside a training loop restore the exact remaining stream.

Built-in Competitive Benchmarking

The benchmarking suite profiles datarax against 14 peer frameworks (Grain, tf.data, PyTorch DataLoader, DALI, Ray Data, and others) across 37 standardized scenarios. Results are converted to calibrax runs for direction-aware metrics, regression gating, and W&B export. This benchmark-driven loop is how datarax tracks progress toward competitive throughput - current results and optimization status are tracked in the benchmarking documentation.

Installation

# Basic installation
uv pip install datarax

# With data loading support (HuggingFace, TFDS, audio/image libs)
uv pip install "datarax[data]"

# With GPU support (CUDA 12)
uv pip install "datarax[cuda12]"

# Full development installation
uv pip install "datarax[all]"

macOS / Apple Silicon

# macOS CPU mode (recommended)
uv pip install "datarax[all-cpu]"
JAX_PLATFORMS=cpu python your_script.py

# Metal GPU acceleration (experimental, M1/M2/M3+)
uv pip install jax-metal
JAX_PLATFORMS=metal python your_script.py

Note: Metal GPU acceleration is community-tested. CI runs on macOS with CPU only.

Quick Start

import jax
import jax.numpy as jnp
import numpy as np
from flax import nnx

from datarax import Pipeline
from datarax.operators import ElementOperator, ElementOperatorConfig
from datarax.sources import MemorySource, MemorySourceConfig
from datarax.typing import Element


def normalize(element: Element, key: jax.Array | None = None) -> Element:
    return element.update_data({"image": element.data["image"] / 255.0})


def augment(element: Element, key: jax.Array) -> Element:
    key1, _ = jax.random.split(key)
    flip = jax.random.bernoulli(key1, 0.5)
    new_image = jax.lax.cond(
        flip, lambda img: jnp.flip(img, axis=1), lambda img: img,
        element.data["image"],
    )
    return element.update_data({"image": new_image})


# Create in-memory data source
data = {
    "image": np.random.randint(0, 255, (1000, 28, 28, 1)).astype(np.float32),
    "label": np.random.randint(0, 10, (1000,)).astype(np.int32),
}
source = MemorySource(MemorySourceConfig(), data=data, rngs=nnx.Rngs(0))

# Build pipeline with DAG-based API
normalizer = ElementOperator(
    ElementOperatorConfig(stochastic=False), fn=normalize, rngs=nnx.Rngs(0),
)
augmenter = ElementOperator(
    ElementOperatorConfig(stochastic=True, stream_name="augmentations"),
    fn=augment, rngs=nnx.Rngs(42),
)

pipeline = (
    Pipeline(source=source, stages=[normalizer, augmenter], batch_size=32, rngs=nnx.Rngs(0))
)

# Process batches
for i, batch in enumerate(pipeline):
    if i >= 3:
        break
    print(f"Batch {i}: images {batch['image'].shape}, labels {batch['label'].shape}")

Advanced: Branching and Parallel DAGs

# Define additional operators
def invert(element: Element, key=None) -> Element:
    return element.update_data({"image": 1.0 - element.data["image"]})

inverter = ElementOperator(
    ElementOperatorConfig(stochastic=False), fn=invert, rngs=nnx.Rngs(0),
)

# Build a branching DAG:
# - augment and normalize each consume the source independently
# - merge takes both outputs and averages them
class Merge(nnx.Module):
    def __call__(self, augmented, clean):
        return {
            "image": (augmented["image"] + clean["image"]) / 2,
            "label": clean["label"],
        }

complex_pipeline = Pipeline.from_dag(
    source=source,
    nodes={"augment": augmenter, "normalize": normalizer, "merge": Merge()},
    edges={"augment": [], "normalize": [], "merge": ["augment", "normalize"]},
    sink="merge",
    batch_size=32,
    rngs=nnx.Rngs(0),
)

Architecture

src/datarax/
  core/         # Base modules: DataSourceModule, OperatorModule, Element, Batcher, Sampler, Sharder
  pipeline/     # Pipeline (nnx.Module): linear stages and Pipeline.from_dag for branching
  sources/      # MemorySource, TFDS (eager/streaming), HuggingFace (eager/streaming), ArrayRecord, MixDataSourcesNode, StreamingDiskSource
  operators/    # ElementOperator, MapOperator, CompositeOperator, modality-specific (image, audio)
    strategies/ # Sequential, Parallel, Branching, Ensemble, Merging composition strategies
  samplers/     # Sequential, Shuffle (Feistel cipher), Range, EpochAware, SlidingWindow, BufferSampler
  batching/     # DefaultBatcher with buffer state management
  sharding/     # ArraySharder, JaxProcessSharder for multi-device distribution
  checkpoint/   # IteratorCheckpoint over substrax's Orbax checkpoint store
  monitoring/   # MetricsCollector, callbacks, reporters (console/file)
  performance/  # XLA optimization, goodput tracking, host/device synchronization
  control/      # Prefetcher for asynchronous data loading
  memory/       # Shared memory manager for multi-process data sharing
  workers/      # Reserved namespace for the planned multiprocessing backend
  config/       # TOML-based configuration system with schema validation
  cli/          # datarax CLI entry point
  utils/        # PyTree utilities, external integration helpers

Benchmarking

Datarax includes a benchmarking suite for comparison against 14 data loading frameworks across 37 workload scenarios (vision, NLP, tabular, multimodal, distributed).

# Install benchmark dependencies (adds PyTorch, DALI, Ray, etc.)
uv sync --extra benchmark

# Optional: install calibrax with W&B support explicitly
uv pip install "calibrax[wandb] @ git+https://github.com/avitai/calibrax.git"

# Run benchmarks locally
uv run python -m benchmarks.runners.full_runner --platform cpu --repetitions 5

# Run on cloud (SkyPilot)
sky launch benchmarks/sky/gpu-benchmark.yaml --env WANDB_API_KEY=$WANDB_API_KEY

Benchmark results are exported to W&B with charts, gap analysis, stability reports, and raw result artifacts. See Benchmarking Guide for methodology and cloud deployment.

Development Setup

Datarax uses uv as its package manager:

# Clone and setup
git clone https://github.com/avitai/datarax.git
cd datarax

# Automatic setup
./setup.sh && source activate.sh

# Or manual install
uv sync --extra dev

Running Tests

# CPU-only (most stable)
JAX_PLATFORMS=cpu uv run pytest

# Include benchmark test suite in the same run
JAX_PLATFORMS=cpu uv run pytest --all-suites

# Specific module
JAX_PLATFORMS=cpu uv run pytest tests/sources/test_memory_source_module.py

Docker

# Build and run
docker build -t datarax:latest .
docker run --rm --gpus all datarax:latest python -c "import datarax, jax; print(jax.devices())"

# Benchmark images
docker build -f benchmarks/docker/Dockerfile.gpu -t datarax-bench:gpu .

See Docker Guide for full details.

Documentation

License

Datarax is licensed under the MIT License.

Release files for datarax 0.1.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for datarax 0.1.9
File Size Uploaded
datarax-0.1.9.tar.gz 240.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for datarax 0.1.9
File Interpreter ABI Platform
datarax-0.1.9-py3-none-any.whl Python 3 none any Details

Total release size: 529.4 kB

Release files / datarax-0.1.9.tar.gz

Download URL datarax-0.1.9.tar.gz
Size 240.3 kB
Tags Source
SHA-256 checksum
How to use checksums
0da02b99f6753761204d41f5b2636e98303b117d7418d00c1ac75e84a06961e9
BLAKE2b-256 checksum
How to use checksums
cd7621cdb49ce799c2d96344b8c31b3a0b3da02874eb5f2bea7fead911309583
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / datarax-0.1.9-py3-none-any.whl

Download URL datarax-0.1.9-py3-none-any.whl
Size 289.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c4ddc461dd02e7868a8f9dd3ecd72111aa1b6ca59b50dffe4172e174485b1847
BLAKE2b-256 checksum
How to use checksums
e877078a260a44e9e5f4136045cbe77dddf3d8ed947b1c9db1525e5792acd2cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.16

2 release files

0.1.15

2 release files

0.1.14

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

This release

0.1.9 This release

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page