1.075 Deep Learning Frameworks#

PyTorch, TensorFlow and JAX sorted by where each one stops being Python and becomes a compiled graph — plus MXNet, which is retired.

At a glance#

LibraryBest forVerdictLatest release
PyTorchAny model that is not yet known to work, and any accelerator that is not NVIDIAEager by default, so the stack trace is the model and the graph is rebuilt every iteration — which is why it owns the debugging loop. torch.compile captures what it can and silently graph-breaks on the rest, falling back to eager after 8 recompiles. The deployment story changed underneath the previous pass: TorchServe is archived and unmaintained, TorchScript’s docs are marked deprecated, and pytorch.org/mobile 301s to ExecuTorch. What replaced them is torch.export, a hard boundary that errors rather than guesses. Widest first-party hardware coverage of the three — CUDA, ROCm, Intel XPU and Apple MPS — and the weakest TPU path.1.0.2 · 2019-04-24
TensorFlowAn existing SavedModel estate, and teams that need a maintained first-party model serverEager like PyTorch until you decorate, then tracing turns the function into a cached graph; the failure mode is silent retracing rather than a silent graph break. Its durable advantage was that the artifact is a file, and TF Serving is now the only maintained first-party model server among the three. Two things weakened the edge argument: LiteRT, the successor to TensorFlow Lite, converts from PyTorch and JAX as well, and TensorFlow.js has not published since October 2024. Slowest release cadence of the three — about seven months between minor versions.2.21.0 · 2026-03-06
JAXTPUs, sharded training you describe rather than assemble, and differentiable scientific computingCapture is the programming model rather than an optimization applied to one, which is why the constraints are enforced: pure functions, immutable arrays, explicit PRNG keys, no data-dependent shapes. In exchange the transformations compose — jit(vmap(grad(f))) — and the export path states its own contract, six months backward and three weeks forward on StableHLO. Not a neural network library: budget for Flax or Equinox plus Optax. No first-party model server, and Apple Silicon GPU support is stale (jax-metal 0.1.1, October 2024).0.11.1 · 2026-08-17
Apache MXNetNothing new. Existing deployments should be exiting.RETIRED, not declining. Became an Apache Top Level Project in September 2022, retired in September 2023, and the move to the Apache Attic completed in February 2024; mxnet.apache.org states “This project has retired.” The GitHub repository is archived and read-only. Beyond governance, it no longer installs cleanly: it pins numpy<2.0.0, and its manylinux2014_aarch64 wheel failed to import on a clean Python 3.12 environment on 2026-08-25 with a missing libarmpl_lp64_mp.so. The ~575k monthly downloads measure unmigrated code, not adoption. Export to ONNX while an environment that can run it still exists, then move training to PyTorch.1.9.1 · 2022-05-17

Latest release observed from PyPI in 2026-09.

What the research found

  • The category sorts on one question — at what moment does your Python stop being Python and become a graph? PyTorch says never unless you ask, TensorFlow says at a decorator, JAX says at every transformation.
  • The capture boundary is also the deployment boundary: the artifact you can ship off the training machine is exactly the part you could capture as a graph. The three frameworks’ deployment stories differ in the same way their execution models do.
  • The failure modes are the tell. PyTorch graph-breaks silently and falls back to Python after 8 recompiles; TensorFlow retraces silently; JAX raises. Two of the three would rather keep running than tell you capture went wrong.
  • Apache MXNet is RETIRED — Attic move completed February 2024, repository archived, zero commits in 52 weeks, last release 2022-05-17. The prior pass called it declining and offered a 12-24 month migration window that had already closed.
  • TorchServe is archived and its README states there will be no security patches. The prior pass recommended it as PyTorch’s production serving answer; the replacement, torch.export, is a stricter boundary than what it replaced.

Explainer

⚠️ CORRECTIONS — 2026-08-25 >#

This explainer was written against January 2024 figures. Four things in it have since been contradicted by primary sources, and the corrections are applied inline below: >

  1. MXNet is retired, not “declining” — moved to the Apache Attic in February 2024, repository archived, zero commits in the trailing 52 weeks.
  2. TorchServe is archived and unmaintained; its README states there will be no security patches.
  3. The adoption percentages cannot be re-verified. Their source, paperswithcode.com, has been shut down and redirects elsewhere.
  4. TensorFlow Lite’s successor, LiteRT, converts from PyTorch and JAX too, so the mobile target no longer forces the framework choice. > The current, sourced account is in 01-discovery/S2-comprehensive/.

What Are Core Deep Learning Frameworks?#

Production-grade software libraries that enable building, training, and deploying neural networks at scale

Executive Summary#

Deep learning frameworks are specialized software libraries that abstract the mathematical complexity of neural networks into programmable APIs. While traditional software operates on explicit rules (“if X then Y”), deep learning frameworks enable systems that learn patterns from data - recognizing images, translating languages, generating content, and making predictions without being explicitly programmed for each scenario.

Business Impact: Deep learning powers $100B+ in annual revenue across search (Google), recommendations (Netflix, Amazon), autonomous systems (Tesla), and content generation (OpenAI, Anthropic). Choosing the wrong framework or vendor lock-in can cost millions in re-engineering, while proper framework selection accelerates time-to-market and reduces infrastructure costs by 30-70%.

The Core Challenge#

Why specialized frameworks exist:

A deep learning model is more than code — it is a computational pipeline:

  • Tensor operations: Multi-dimensional array transformations (matrix multiplication at GPU scale)
  • Automatic differentiation: Computing gradients for billions of parameters
  • Distributed training: Splitting computation across hundreds of GPUs/TPUs
  • Hardware optimization: CUDA kernels, memory management, mixed-precision arithmetic
  • Model deployment: Serving predictions at millisecond latency for millions of users

Writing this from scratch requires 10-100× more engineering effort. Frameworks provide these capabilities as reusable libraries, letting teams focus on model architecture and business logic rather than GPU programming.

What These Frameworks Provide#

FrameworkPrimary StrengthBusiness Value
PyTorchResearch velocity, debuggingFastest prototyping; eager execution keeps the debugging loop short
TensorFlowProduction deployment, ecosystemGoogle-scale serving, mobile/edge deployment, mature tooling
JAXComposable transformations, TPUsjit/grad/vmap compose; TPU support ships with the framework
MXNetRETIRED (Apache Attic, February 2024). Do not start here; existing users should be exiting

When You Need This#

Critical for:

  • Recommender systems (e-commerce, content platforms): $50M-$500M+ annual revenue impact
  • Computer vision (autonomous vehicles, medical imaging): Safety-critical, regulatory compliance
  • Natural language processing (chatbots, search, translation): Customer experience, support cost reduction
  • Fraud detection (finance, payments): Preventing $100K-$100M+ annual losses
  • Predictive maintenance (manufacturing, IoT): Reducing downtime costs
  • Generative AI (content creation, code generation): New product categories

Cost of ignoring: Companies that built custom ML infrastructure pre-2015 spent $10M-$100M+ on capabilities now available free in PyTorch/TensorFlow. Tesla’s 2019 switch to PyTorch accelerated Autopilot development velocity by 3-5×.

Common Approaches#

1. Single-Framework (Recommended) Pick one framework and standardize. Reduces training costs, tooling complexity, and hiring friction. PyTorch dominates research (75% of papers), TensorFlow dominates production serving (Google, Uber, Airbnb).

2. Multi-Framework (High Cost) Using multiple frameworks in one organization 2-3× training time, splits hiring pools, and complicates infrastructure. Only justified for acquisitions or distinct use cases (research vs serving).

3. Cloud-Managed ML (Convenience, Vendor Lock-in) AWS SageMaker, Google Vertex AI, Azure ML abstract framework details but introduce vendor dependency. Costs 2-5× self-managed infrastructure at scale. Reasonable for small teams (<10 ML engineers).

4. Framework-as-a-Service (Emerging) Platforms like Hugging Face, Replicate, Modal abstract deployment entirely. Trade control for speed. Ideal for prototyping, risky for core business logic (pricing changes, service outages).

Technical vs Business Tradeoff#

Technical perspective: “We’ll support all frameworks for maximum flexibility” Business reality: Multi-framework environments create hiring friction (smaller candidate pools), training overhead (2× onboarding time), and infrastructure complexity (separate CI/CD, monitoring, profiling tools).

ROI Calculation:

  • Framework standardization cost: 1-2 weeks (pick framework, document decision)
  • Avoided costs: 50% reduction in onboarding time, 30% reduction in infrastructure complexity
  • Risk mitigation: Framework lock-in is low-risk (models portable via ONNX, training code rewritable in 2-4 weeks)

Data Architecture Implications#

Storage: Models range from 10MB (mobile) to 500GB+ (GPT-4-class). Training datasets: 10GB-10PB+. Requires object storage (S3/GCS), versioning (DVC, Weights & Biases), and lineage tracking.

Compute patterns: Training is batch/offline (hours to weeks), inference is real-time (1-100ms latency). Different scaling needs: training scales with GPUs, inference scales with CPUs/edge devices.

Serving: TensorFlow Serving and Triton Inference Server are actively maintained; TorchServe is archived (pytorch/serve, read-only, “no planned updates, bug fixes, new features, or security patches”). PyTorch’s replacement path is torch.export feeding AOTInductor, ONNX or ExecuTorch. Cloud managed services (SageMaker, Vertex AI) handle auto-scaling but cost 2-3× self-managed.

Strategic Risk Assessment#

Risk: Framework abandonment

  • MXNet was retired outright in September 2023 and moved to the Apache Attic in February 2024 — the clearest demonstration in this category that a framework with a permissive license and a large sponsor can still stop
  • Theano, Caffe, CNTK all deprecated within 5-7 years
  • Mitigation: Choose frameworks with multi-company backing (PyTorch: Meta/Microsoft/NVIDIA, TensorFlow: Google/Hugging Face)

Risk: Vendor lock-in

  • Cloud ML platforms (SageMaker, Vertex AI) introduce proprietary APIs
  • Switching costs: 3-6 months engineering for mid-sized teams
  • Mitigation: Use open frameworks (PyTorch/TensorFlow) even on cloud platforms

Risk: Performance ceiling

  • Wrong framework choice can limit scale (TensorFlow 1.x graph mode hindered debugging, slowed research)
  • Migration cost: Airbnb’s TensorFlow→PyTorch migration took 6 months (2020)
  • Mitigation: Prototype in multiple frameworks before standardizing (2-4 week eval)

Framework Selection Decision Tree#

Question 1: Is this primarily research or production?#

  • Research-first (iterating models): PyTorch — eager execution means the stack trace is the model
  • Production-first (serving existing models): TensorFlow (mature serving, mobile, edge)
  • Both equally: PyTorch (research→production path exists, TensorFlow 2.x closed gap)

Question 2: Do you need mobile/edge deployment?#

  • Yes (iOS, Android, embedded): pick the runtime first — LiteRT (converts from PyTorch, JAX or TensorFlow) or ExecuTorch (PyTorch). PyTorch Mobile no longer exists separately; pytorch.org/mobile/ redirects to ExecuTorch
  • No (cloud-only): PyTorch (simpler, faster iteration)

Question 3: Do you have existing infrastructure?#

  • Google Cloud: Either (Vertex AI supports both), lean TensorFlow
  • AWS: Either (SageMaker supports both). Historically MXNet, which is now retired
  • Azure: Either (Azure ML supports both), lean PyTorch (Microsoft investment)
  • Self-hosted: PyTorch (simpler deployment)

Question 4: What’s your team’s experience?#

  • Existing PyTorch expertise: PyTorch (retraining costs 2-3 months)
  • Existing TensorFlow expertise: TensorFlow (migration friction)
  • No expertise (new team): PyTorch (easier learning curve, better debugging)

Question 5: Do you need maximum performance (training speed)?#

  • Yes (100+ GPU clusters): measure it. No primary source in this survey supports a speed ranking; two of the three lower to XLA and the third to TorchInductor. JAX’s advantage at this scale is that sharding is described over a device mesh rather than assembled from mechanisms
  • No (typical workloads): PyTorch or TensorFlow (JAX has smaller ecosystem)

The figures in this section came from Papers With Code, which has been shut down; paperswithcode.com now redirects to huggingface.co/papers/trending. No equivalent public dataset replaced it. They are left here as a record of what the 2024 pass recorded and should not be cited.

Research (ML papers at NeurIPS, ICML, ICLR):

  • PyTorch: 75%
  • TensorFlow: 15%
  • JAX: 8%
  • Others: 2%

Production (job postings, StackOverflow):

  • PyTorch: 55% (rising)
  • TensorFlow: 40% (declining from 70% in 2019)
  • JAX: 3% (niche HPC/research)
  • MXNet: 2% (legacy)

Trajectory: PyTorch is winning. TensorFlow 2.x closed usability gap but lost momentum. JAX is growing in research/HPC but unlikely to overtake PyTorch for general use.

Migration Patterns#

Common migrations (2018-2024):

  • TensorFlow 1.x → PyTorch (Airbnb, Tesla, many startups)
  • TensorFlow 1.x → TensorFlow 2.x (Google, existing TF shops)
  • MXNet → PyTorch (AWS internal teams)
  • Caffe/Theano → PyTorch (academic labs)

Rare migrations:

  • PyTorch → TensorFlow (almost never, except for specific mobile/edge needs)
  • JAX → PyTorch (research prototypes moving to production)

Migration cost: 2-6 months for mid-sized teams (10-50 models), depending on complexity.

Ecosystem Maturity#

CapabilityPyTorchTensorFlowJAXMXNet
Training frameworks★★★★★★★★★★★★★☆☆★★★☆☆
Serving (production)★★★☆☆ (TorchServe archived)★★★★★★★☆☆☆— (retired)
Mobile/edge★★★★☆ (ExecuTorch, LiteRT)★★★★★★★☆☆☆ (LiteRT path)— (retired)
Debugging tools★★★★★★★★★☆★★★☆☆★★☆☆☆
Community support★★★★★★★★★★★★★☆☆★★☆☆☆
Pre-trained models★★★★★★★★★★★★★☆☆★★☆☆☆
Multi-GPU/TPU★★★★☆ multi-GPU, ★★☆☆☆ TPU (torch_xla lags)★★★★★★★★★★— (retired)

Cost Structure (Typical ML Project)#

Scenario: Mid-sized company, 5 ML engineers, training 10-20 models/month

ApproachUpfrontAnnual ComputeAnnual LaborTotal 3-Year
Self-hosted PyTorch$50K (infra setup)$120K (GPUs)$750K (eng time)$2.66M
Cloud PyTorch (AWS EC2)$10K (setup)$180K (GPU instances)$700K (less ops)$2.65M
Managed ML (SageMaker)$5K (minimal setup)$360K (2× compute markup)$600K (less DevOps)$2.69M

Key insight: Framework choice is cheap ($0-50K). Compute and labor dominate (90%+ of costs). Optimize for engineer productivity, not framework licensing (all major frameworks are free).

Further Reading#

  • PyTorch Documentation: pytorch.org (official docs, tutorials)
  • TensorFlow Documentation: tensorflow.org (official docs, guides)
  • JAX Documentation: docs.jax.dev, repository at github.com/jax-ml/jax
  • Papers With Code: paperswithcode.comshut down; redirects to huggingface.co/papers/trending
  • Hugging Face: huggingface.co (pre-trained models, both PyTorch and TensorFlow)
  • Stanford CS230: Deep Learning course (framework-agnostic fundamentals)

Licensing Considerations#

FrameworkLicenseCommercial UseRisk
PyTorchBSD-3-Clause✅ PermissiveLow
TensorFlowApache 2.0✅ PermissiveLow
JAXApache 2.0✅ PermissiveLow
MXNetApache 2.0✅ PermissiveHigh — the license is permissive and the project is retired. A permissive license is not a maintenance commitment

All four are open-source with permissive licenses, and that says nothing about whether they are maintained — MXNet’s Apache 2.0 license did not prevent its retirement. No per-user fees, no runtime royalties, no vendor lock-in at the framework level (cloud platforms may add restrictions).


Bottom Line for CTOs (revised 2026-08-25): The framework question is smaller than it was, because the deployment runtimes — LiteRT, ExecuTorch, ONNX Runtime — now take models from all three live frameworks. Start with PyTorch unless a constraint above you says otherwise: TPUs point at JAX, an existing SavedModel estate points at TensorFlow, non-NVIDIA accelerators point back at PyTorch. Do not deploy with TorchServe; it is archived. And treat MXNet’s retirement as the category’s live lesson — a permissive license and a large corporate sponsor did not keep it alive.

S1: Rapid Discovery

Note — 2026-08-25: the “Papers With Code” data source named below no longer exists; paperswithcode.com redirects to huggingface.co/papers/trending. Every framework-share percentage produced by this pass is therefore unverifiable and is not carried into S2 or S3.

S1: Rapid Discovery - Approach#

Methodology: Speed-Focused, Ecosystem-Driven#

Time budget: 10 minutes per framework (40 minutes total) Goal: Identify viable frameworks, eliminate obvious non-starters, surface key differentiators

Data Sources (Prioritized for Speed)#

  1. GitHub metrics (5 min/framework)

    • Stars, forks, commit velocity (ecosystem health)
    • Issue close rate (maintenance quality)
    • Recent activity (abandonment risk)
  2. Papers With Code (3 min/framework)

    • Research paper usage trends (2020-2024)
    • Benchmark implementations (framework preference in practice)
  3. Job market signals (2 min/framework)

    • LinkedIn/Indeed job postings (industry demand)
    • StackOverflow activity (developer adoption)

Evaluation Criteria#

Each framework scored 0-10 on:

  • Ecosystem health (GitHub activity, community size)
  • Production maturity (serving tools, deployment options)
  • Research adoption (paper citations, benchmark implementations)
  • Learning curve (documentation, tutorials, error messages)
  • Performance (training speed, inference latency - from published benchmarks)

Speed Score = (Ecosystem + Maturity + Adoption + Learning + Performance) / 5

Exclusion Criteria#

Frameworks excluded if:

  • <500 GitHub stars (insufficient community)
  • No commits in 6+ months (abandonment risk)
  • <1% research paper usage (declining relevance)

Limitations of Rapid Discovery#

What this pass does NOT provide:

  • Detailed performance benchmarks (see S2-comprehensive)
  • Use-case specific recommendations (see S3-need-driven)
  • Long-term viability assessment (see S4-strategic)

What this pass DOES provide:

  • Quick elimination of non-viable options
  • Identification of clear leaders vs niche players
  • Surface-level understanding of trade-offs

Expected Outcome#

High-confidence outputs:

  • 2-3 frameworks clearly dominate
  • 1-2 frameworks are niche/declining

Uncertainty that requires deeper passes:

  • Performance differences (need benchmarks)
  • Use-case fit (need real-world scenarios)
  • Long-term risk (need maintenance/governance analysis)

Time commitment: 40 minutes total Confidence target: 70-80% (sufficient to eliminate bad choices, insufficient for final decision)


⚠️ CORRECTIONS — 2026-08-25 >#

  • Stars and commit velocity were understated. 36,216 stars and 7,826 commits in the trailing 52 weeks (GitHub API, 2026-08-25), against “28K+” and “20-40 commits/week” below.
  • The “2-10× faster” training claim is not verified by any primary source consulted in the S2 pass, and no source is cited for it here. Treat it as unverified.
  • The research-adoption percentages cannot be re-verified — see the note in pytorch.md.
  • “Mobile: ❌ Poor” — LiteRT documents a JAX conversion path. > Current account: S2-comprehensive/jax.md.

JAX - S1 Rapid Discovery#

Ecosystem Health: 7.5/10#

GitHub metrics (Jan 2024):

  • Stars: 28K+
  • Forks: 2.6K+
  • Contributors: 650+
  • Commit velocity: 20-40 commits/week
  • Issue close rate: ~70% within 30 days

Community size:

  • JAX Discussions (GitHub): 1,500+ threads
  • StackOverflow questions: 3,500+ (small but growing)
  • Smaller than PyTorch/TensorFlow but very active

Verdict: Healthy but niche (research/HPC focus), growing steadily

Production Maturity: 6.0/10#

Serving options:

  • Limited official serving tools (no JAXServe equivalent)
  • Can export to ONNX or TensorFlow SavedModel
  • Cloud support: Google Vertex AI (native), others via conversion

Deployment targets:

  • Cloud: ✅ Good (Google Cloud TPUs, GPU clusters)
  • Mobile: ❌ Poor (not designed for edge)
  • Edge: ❌ Poor (limited embedded support)
  • Web: ❌ Minimal

Tooling:

  • Profiling: JAX Profiler, TensorBoard integration
  • Debugging: Harder than PyTorch (functional programming paradigm)
  • Monitoring: Third-party tools (W&B, MLflow)

Verdict: Research/training focused, production deployment requires conversion

Research Adoption: 7.5/10#

Papers With Code (2024 snapshot):

  • NeurIPS 2023: 8% of papers (up from 3% in 2020)
  • ICML 2023: 9% of papers
  • ICLR 2024: 8% of papers

Growth areas:

  • Reinforcement learning (DeepMind uses JAX)
  • Scientific computing (differentiable physics simulations)
  • High-performance ML (large-scale training)

Trajectory: Growing in niche areas (HPC, RL), not challenging PyTorch for general use

Verdict: Strong in specific research domains, not a general-purpose standard

Learning Curve: 6.5/10#

Documentation:

  • Official docs: Good (improving, math-heavy)
  • Community tutorials: Limited (smaller ecosystem)

Conceptual overhead:

  • Functional programming paradigm (pure functions, no side effects)
  • Must understand: jit, vmap, pmap, grad (transformations)
  • NumPy-like API but with important differences

Error messages:

  • Cryptic when JIT compilation fails
  • Tracing errors can be hard to debug

Onboarding speed:

  • Beginner: 4-6 weeks (functional programming + ML)
  • Intermediate (from NumPy): 2-3 weeks
  • Expert (from PyTorch): 2-3 weeks (unlearning imperative style)

Verdict: Steeper learning curve, requires functional programming mindset

Performance: 9.5/10#

Training speed (published benchmarks):

  • ResNet-50 (ImageNet): 20-30% faster than PyTorch/TF (with XLA)
  • BERT-Large: 30-50% faster
  • Large-scale transformers (GPT-scale): 2-10× faster on TPUs

Inference latency:

  • CPU: Good (XLA compilation)
  • GPU: Excellent (XLA + CUDA)
  • TPU: Excellent (designed for Google hardware)

Memory efficiency:

  • Excellent (functional design enables aggressive optimization)
  • Gradient checkpointing, rematerialization well-supported

Key advantage: XLA (Accelerated Linear Algebra) compiler optimizes entire computation graphs

Verdict: Best-in-class performance for large-scale training

Speed Score: 7.4/10#

Calculation: (7.5 + 6.0 + 7.5 + 6.5 + 9.5) / 5 = 7.407.4/10

Quick Take#

Strengths:

  • ✅ Fastest framework for large-scale training (2-10× speedup)
  • ✅ Functional programming enables aggressive optimization
  • ✅ Excellent for research (DeepMind, Google Research use it)
  • ✅ NumPy-like API (familiar for scientific Python users)

Weaknesses:

  • ❌ Limited production serving tools
  • ❌ Small ecosystem (3% of ML papers vs PyTorch 75%)
  • ⚠️ Steeper learning curve (functional programming required)
  • ⚠️ Not designed for mobile/edge deployment

Best for:

  • Large-scale training (100+ GPUs/TPUs)
  • Research teams focused on performance
  • Reinforcement learning (DeepMind ecosystem)
  • Scientific ML (differentiable physics, optimization)

Avoid if:

  • Need production serving tools (use PyTorch or TensorFlow)
  • Mobile/edge deployment required
  • Team unfamiliar with functional programming

JAX Ecosystem Layers#

JAX is low-level. Most users use higher-level libraries:

LibraryPurposeMaturity
FlaxNeural network library (like PyTorch nn.Module)Good
HaikuDeepMind’s NN libraryGood
OptaxOptimizers (Adam, SGD, etc.)Good
EquinoxPyTorch-like API for JAXEmerging

Note: JAX itself is just NumPy + autograd + XLA. Need libraries above for deep learning.


⚠️ CORRECTION — 2026-08-25 >#

This file is wrong about MXNet’s status and is kept only as a record of what the January 2024 pass recorded. Apache MXNet is not “declining.” It is retired. It became an Apache Top Level Project in September 2022, was retired in September 2023, and the move to the Apache Attic completed in February 2024 — before this file’s advice to “migrate within 12-24 months” could have been acted on. > Specific claims below that the sources contradict: >

  • “Commit velocity: 5-10 commits/week” — the apache/mxnet repository is archived (read-only), last pushed 2023-10-25, with 0 commits in the trailing 52 weeks.
  • “Apache incubator graduation stalled” — it graduated to Top Level Project in September 2022 and was retired a year later.
  • “Migrate existing projects within 12-24 months” — the window had already closed when this was written. > The current, sourced account is in S2-comprehensive/mxnet.md, including the numpy<2.0.0 pin and an observed import failure of the published ARM Linux wheel. Read that file instead of this one.

MXNet - S1 Rapid Discovery#

Ecosystem Health: 4.5/10#

GitHub metrics (Jan 2024):

  • Stars: 20K+
  • Forks: 6.8K+
  • Contributors: 1,000+ (declining)
  • Commit velocity: 5-10 commits/week (down from 50+/week in 2018)
  • Issue close rate: ~50% within 30 days (declining maintenance)

Community size:

  • MXNet Forums: ~5K users (inactive)
  • StackOverflow questions: 12K+ (few new questions)
  • Discuss.mxnet.io: Largely abandoned (last activity 2022)

Red flags:

  • AWS stopped promoting MXNet (2021-2022)
  • SageMaker shifted default to PyTorch
  • Apache incubator graduation stalled
  • Major contributors (Amazon) reduced investment

Verdict: Declining ecosystem, abandonment risk

Production Maturity: 7.0/10#

Serving options:

  • MXNet Model Server (functional but unmaintained)
  • AWS SageMaker (legacy support)
  • ONNX export (migration path)

Deployment targets:

  • Cloud: ✅ Good (AWS legacy, others via ONNX)
  • Mobile: ⚠️ Fair (existed but unmaintained)
  • Edge: ⚠️ Fair (existed but unmaintained)
  • Web: ❌ Minimal

Tooling:

  • Profiling: MXNet Profiler (outdated)
  • Debugging: Difficult (imperative/symbolic hybrid)
  • Monitoring: Third-party tools

Note: Production maturity reflects 2018-era strength, not 2024 state

Verdict: Legacy systems only, do not start new projects

Research Adoption: 2.0/10#

Papers With Code (2024 snapshot):

  • NeurIPS 2023: <1% of papers
  • ICML 2023: <1% of papers
  • ICLR 2024: ~0% of papers

Trajectory: Collapsed (2018: 15% → 2024: <1%)

Historical context:

  • 2017-2018: AWS promoted MXNet as “deep learning for the cloud”
  • 2019-2020: PyTorch momentum unstoppable, AWS quietly shifted
  • 2021-2024: Research community abandoned MXNet entirely

Verdict: No longer relevant for research

Learning Curve: 6.0/10#

Documentation:

  • Official docs: Outdated (many broken links)
  • Community tutorials: Mostly obsolete (GluonCV/GluonNLP stale)

API design:

  • Hybrid imperative/symbolic (confusing)
  • Gluon API (high-level) was good but unmaintained

Onboarding speed:

  • N/A (do not onboard new engineers to MXNet)

Verdict: Not worth learning in 2024

Performance: 7.5/10#

Training speed (historical benchmarks, 2018-2019):

  • ResNet-50 (ImageNet): Competitive (slightly faster than TF 1.x)
  • BERT-Large: Not widely benchmarked
  • Multi-GPU: Good scaling (designed for distributed training)

Inference latency:

  • CPU: Good (optimized)
  • GPU: Good (CUDA support)

Memory efficiency:

  • Good (symbolic mode enabled optimizations)

Note: Performance scores based on 2018-era benchmarks. No recent data.

Verdict: Was performant, but irrelevant (no modern benchmarks)

Speed Score: 5.4/10#

Calculation: (4.5 + 7.0 + 2.0 + 6.0 + 7.5) / 5 = 5.405.4/10

Quick Take#

Historical strengths (2017-2019):

  • ✅ Good multi-GPU scaling
  • ✅ AWS SageMaker integration
  • ✅ Multi-language bindings (Python, Scala, Julia, R)
  • ✅ Gluon API (high-level, Keras-like)

Current weaknesses (2024):

  • ❌ Abandonment risk (declining contributions)
  • ❌ No research adoption (<1% of papers)
  • ❌ AWS stopped promoting (shifted to PyTorch)
  • ❌ Outdated documentation, broken examples
  • ❌ Small community (inactive forums)

Best for:

  • Maintaining legacy AWS SageMaker deployments (until migration)

Avoid for:

  • ❌ New projects (use PyTorch or TensorFlow)
  • ❌ Research (use PyTorch)
  • ❌ Long-term investments (high abandonment risk)

Migration Path (for existing MXNet users)#

If you have MXNet in production:

  1. Assess migration urgency:

    • Low: Model serving only (keep MXNet, plan migration)
    • Medium: Active training (migrate within 12 months)
    • High: New features needed (migrate immediately)
  2. Migration targets:

    • PyTorch (most common, easier learning curve)
    • TensorFlow (if mobile/edge required)
  3. Migration strategy:

    • Export via ONNX (for serving-only systems)
    • Rewrite training code (2-6 months for mid-sized teams)
  4. AWS SageMaker users:

    • SageMaker supports PyTorch/TensorFlow (no vendor lock-in)
    • Migration path well-documented by AWS

Historical Context: What Happened to MXNet?#

2017: Amazon selected MXNet as preferred deep learning framework (AWS Deep Learning AMI, SageMaker)

2018: Peak adoption (15% of research papers, strong AWS promotion)

2019: PyTorch momentum unstoppable (50% → 70% research adoption). AWS added PyTorch to SageMaker.

2020: AWS quietly de-emphasized MXNet (job postings shifted to PyTorch)

2021-2022: Community contributions collapsed. Apache incubator status unresolved.

2023-2024: MXNet effectively abandoned. Legacy support only.

Lesson: Single-vendor backing is risky. PyTorch (Meta + Microsoft + NVIDIA + community) and TensorFlow (Google + community) have multi-vendor support.


⚠️ CORRECTIONS — 2026-08-25 >#

  • “TorchServe (official, production-ready)” is no longer true. pytorch/serve is archived on GitHub and its README states the project “is no longer actively maintained … no planned updates, bug fixes, new features, or security patches.” Last PyPI release 0.12.0, 2024-09-30.
  • Stars and commit velocity were understated. 102,603 stars and 17,271 commits in the trailing 52 weeks (GitHub API, 2026-08-25), against “77K+” and “50-100 commits/week” below.
  • “Mobile: PyTorch Mobile”pytorch.org/mobile/home/ now returns HTTP 301 to the ExecuTorch documentation.
  • The research-adoption percentages cannot be re-verified. Their source, paperswithcode.com, now redirects to huggingface.co/papers/trending. > Current account: S2-comprehensive/pytorch.md.

PyTorch - S1 Rapid Discovery#

Ecosystem Health: 9.5/10#

GitHub metrics (Jan 2024):

  • Stars: 77K+
  • Forks: 21K+
  • Contributors: 4,500+
  • Commit velocity: 50-100 commits/week
  • Issue close rate: ~80% within 30 days

Community size:

  • PyTorch Forums: 50K+ users
  • StackOverflow questions: 85K+
  • Discord/Slack: 30K+ members

Verdict: Extremely healthy, active development, large community

Production Maturity: 8.5/10#

Serving options:

  • TorchServe (official, production-ready)
  • Triton Inference Server (NVIDIA, multi-framework)
  • Cloud support: AWS SageMaker, Azure ML, Google Vertex AI

Deployment targets:

  • Cloud: ✅ Excellent (all major clouds)
  • Mobile: ✅ Good (PyTorch Mobile, improving)
  • Edge: ✅ Good (ONNX export, quantization)
  • Web: ⚠️ Limited (ONNX.js, experimental)

Tooling:

  • Profiling: PyTorch Profiler, TensorBoard integration
  • Debugging: Native Python debugger (pdb, ipdb)
  • Monitoring: Weights & Biases, MLflow, Neptune.ai

Verdict: Production-ready with minor gaps (web deployment)

Research Adoption: 9.8/10#

Papers With Code (2024 snapshot):

  • NeurIPS 2023: 78% of papers
  • ICML 2023: 74% of papers
  • ICLR 2024: 76% of papers

Benchmark implementations:

  • ImageNet: 95% PyTorch
  • GLUE (NLP): 90% PyTorch
  • Reinforcement Learning: 85% PyTorch

Trajectory: Dominant and growing (2019: 50% → 2024: 75%+)

Verdict: Clear research standard

Learning Curve: 9.0/10#

Documentation:

  • Official docs: Excellent (tutorials, API reference, examples)
  • Community tutorials: Abundant (fast.ai, PyTorch Lightning)

Error messages:

  • Clear, actionable (Python-like stack traces)
  • Shape mismatches caught eagerly (easier debugging)

Onboarding speed:

  • Beginner: 2-4 weeks (Python familiarity assumed)
  • Intermediate (from NumPy): 1-2 weeks
  • Expert (from TensorFlow): 1 week

Verdict: Pythonic, intuitive, gentle learning curve

Performance: 8.0/10#

Training speed (published benchmarks):

  • ResNet-50 (ImageNet): ~baseline
  • BERT-Large: ~baseline
  • GPT-3 scale: Competitive with TensorFlow, 20-50% slower than JAX (on TPUs)

Inference latency:

  • CPU: Good (optimized for x86)
  • GPU: Excellent (CUDA optimized)
  • TPU: Fair (Google hardware, TensorFlow advantage)

Memory efficiency:

  • Good (dynamic computation graph = some overhead)
  • Gradient checkpointing available
  • Mixed precision (AMP) for 2-3× speedup

Verdict: Competitive performance, not bleeding-edge (see JAX for max speed)

Speed Score: 9.0/10#

Calculation: (9.5 + 8.5 + 9.8 + 9.0 + 8.0) / 5 = 8.969.0/10

Quick Take#

Strengths:

  • ✅ Research standard (75% of ML papers)
  • ✅ Pythonic, easy to debug
  • ✅ Excellent community and ecosystem
  • ✅ Strong production tooling (TorchServe, cloud support)

Weaknesses:

  • ⚠️ Slightly slower than JAX for large-scale training
  • ⚠️ Web deployment less mature than TensorFlow.js
  • ⚠️ Mobile support improving but behind TensorFlow Lite

Best for:

  • Research teams (prototyping, experimentation)
  • Teams prioritizing developer velocity
  • Cloud-first deployments

Avoid if:

  • Mobile/edge is primary deployment target
  • Maximum training speed critical (100+ GPU clusters)

⚠️ SUPERSEDED — 2026-08-25 >#

This ranking is kept as a record. Two of its four entries were factually out of date and its method — a five-part score averaged into one number — sorts frameworks that are not attempts at the same thing. >

  • “MXNet: declining … migrate within 12-24 months” → MXNet is retired; the Apache Attic move completed February 2024.
  • PyTorch “production ready: TorchServe”pytorch/serve is archived and unmaintained.
  • The adoption percentages the ranking rests on cannot be re-verified; paperswithcode.com has been shut down and redirects elsewhere. > The current recommendation is S2-comprehensive/recommendation.md (what the mechanism decides) and S3-need-driven/recommendation.md (which constraint decides for which reader).

S1 Rapid Discovery - Recommendation#

Framework Rankings (Speed Score)#

RankFrameworkScoreStatusRecommendation
1PyTorch9.0/10✅ DominantPrimary choice for most teams
2TensorFlow8.3/10✅ StrongUse for mobile/edge, Google Cloud
3JAX7.4/10⚠️ NicheUse for HPC, max performance
4MXNet5.4/10❌ DecliningAvoid (legacy only)

Clear Winner: PyTorch#

Confidence: 85% (high for rapid discovery)

Evidence:

  • Research dominance: 75% of ML papers (vs TF 15%, JAX 8%, MXNet <1%)
  • Ecosystem health: 77K stars, 50-100 commits/week
  • Learning curve: Pythonic, easiest to debug
  • Production ready: TorchServe, cloud support

When PyTorch is best:

  • Research-heavy workloads (prototyping, experimentation)
  • New teams (easiest onboarding)
  • Cloud-first deployments
  • General-purpose ML (vision, NLP, RL)

TensorFlow: Production Specialist#

Confidence: 80%

Evidence:

  • Best production deployment (TF Serving, TF Lite)
  • Mobile/edge standard (TF Lite Micro)
  • Strong performance on Google Cloud (TPU optimization)

When TensorFlow is best:

  • Mobile/edge deployment critical (iOS, Android, embedded)
  • Existing TensorFlow codebase
  • Google Cloud native (Vertex AI, TPUs)
  • Production-first teams (serving > training)

Trend: Declining research adoption, stable production use

JAX: Performance Specialist#

Confidence: 70%

Evidence:

  • Fastest training (2-10× speedup for large-scale)
  • Growing in specific niches (RL, scientific ML)
  • Functional programming paradigm (requires expertise)

When JAX is best:

  • Large-scale training (100+ GPUs/TPUs)
  • Performance critical (willing to sacrifice ecosystem)
  • Team has functional programming expertise

Limitation: Small ecosystem, limited serving tools

MXNet: Avoid#

Confidence: 90% (clear decline)

Evidence:

  • <1% research adoption (down from 15% in 2018)
  • AWS stopped promoting (shifted to PyTorch)
  • Declining commits, inactive community
  • Abandonment risk

Decision: Do not start new projects. Migrate existing projects within 12-24 months.

Decision Framework (Quick)#

Question 1: Is this a new project?#

  • Yes → PyTorch (unless mobile/edge critical, then TensorFlow)
  • No → Assess migration (if MXNet, migrate; if TF/PyTorch, keep)

Question 2: Mobile/edge deployment primary requirement?#

  • Yes → TensorFlow (TF Lite is standard)
  • No → PyTorch

Question 3: Need maximum training speed (100+ GPUs)?#

  • Yes → JAX (if team can handle learning curve)
  • No → PyTorch

Question 4: Google Cloud TPUs required?#

  • Yes → TensorFlow or JAX
  • No → PyTorch

Multi-Framework Antipattern#

Avoid using multiple frameworks in one organization (unless strong justification)

Cost of multi-framework:

  • 2-3× training/onboarding time
  • Split hiring pools (PyTorch vs TensorFlow skills)
  • Duplicate infrastructure (CI/CD, monitoring, profiling)

Valid reasons for multi-framework:

  • Acquisition (inherit different codebase)
  • Distinct teams (research uses PyTorch, mobile uses TensorFlow)
  • Migration period (TensorFlow → PyTorch, time-limited)

Invalid reasons:

  • “Maximum flexibility” (flexibility = complexity)
  • “Different projects need different tools” (standardize on one)

Rapid Discovery Limitations#

This pass does NOT provide:

  • Detailed performance benchmarks (need S2-comprehensive)
  • Use-case specific validation (need S3-need-driven)
  • Long-term risk assessment (need S4-strategic)

This pass DOES provide:

  • Clear leaders: PyTorch (research), TensorFlow (mobile/edge), JAX (HPC)
  • Clear loser: MXNet (avoid)
  • Sufficient confidence to eliminate bad choices (85%)

Next Steps#

High confidence (can decide now):

  • ✅ Eliminate MXNet (do not use for new projects)
  • ✅ PyTorch default for new projects (unless mobile/edge)

Requires deeper analysis:

  • ⚠️ PyTorch vs TensorFlow (production trade-offs) → See S3-need-driven
  • ⚠️ JAX viability (long-term support) → See S4-strategic
  • ⚠️ Performance differences (quantified benchmarks) → See S2-comprehensive

Recommendation Summary#

For 80% of teams:PyTorch (research velocity, ecosystem, learning curve)

For mobile/edge specialists:TensorFlow (TF Lite standard, production deployment)

For HPC/performance specialists:JAX (max speed, willing to sacrifice ecosystem)

For everyone:Avoid MXNet (abandonment risk, declining community)


Confidence: 85% (sufficient to eliminate MXNet, insufficient for final PyTorch vs TensorFlow decision in edge cases)

Time to decision: 40 minutes (rapid discovery) + 2-4 weeks (deeper evaluation via S2/S3/S4 if needed)


⚠️ CORRECTIONS — 2026-08-25 >#

  • “TensorFlow Lite (mobile/edge standard)” — TF Lite’s successor is LiteRT, whose documentation states it converts from “PyTorch, JAX or TensorFlow.” The mobile target no longer forces this framework.
  • “TensorFlow.js: Excellent” is no longer supportable on activity. @tensorflow/tfjs on npm last published 4.22.0 on 2024-10-21.
  • Stars and commit velocity were understated. 197,638 stars and 13,982 commits in the trailing 52 weeks (GitHub API, 2026-08-25).
  • The research-adoption percentages cannot be re-verified — see the note in pytorch.md. > Current account: S2-comprehensive/tensorflow.md.

TensorFlow - S1 Rapid Discovery#

Ecosystem Health: 9.0/10#

GitHub metrics (Jan 2024):

  • Stars: 182K+
  • Forks: 88K+
  • Contributors: 3,900+
  • Commit velocity: 30-50 commits/week (declining from 2019 peak)
  • Issue close rate: ~75% within 30 days

Community size:

  • TensorFlow Forums: 40K+ users
  • StackOverflow questions: 155K+ (largest, but growth slowing)
  • Reddit: 25K+ members

Verdict: Very healthy but momentum shifted to PyTorch (2019-2024)

Production Maturity: 9.8/10#

Serving options:

  • TensorFlow Serving (mature, Google-scale proven)
  • TensorFlow Lite (mobile/edge standard)
  • TensorFlow.js (web deployment)
  • Triton Inference Server (multi-framework alternative)

Deployment targets:

  • Cloud: ✅ Excellent (native on Google Cloud, supported everywhere)
  • Mobile: ✅ Excellent (TF Lite, industry standard)
  • Edge: ✅ Excellent (TF Lite Micro, embedded systems)
  • Web: ✅ Excellent (TensorFlow.js)

Tooling:

  • Profiling: TensorBoard (industry standard), TF Profiler
  • Debugging: Improved in TF 2.x (eager execution), still harder than PyTorch
  • Monitoring: TensorBoard, cloud-native integrations

Verdict: Best-in-class production deployment, especially mobile/edge

Research Adoption: 6.5/10#

Papers With Code (2024 snapshot):

  • NeurIPS 2023: 15% of papers (down from 45% in 2019)
  • ICML 2023: 18% of papers
  • ICLR 2024: 14% of papers

Trajectory: Declining in research, stable in production (2019: 70% → 2024: 15%)

Reason for decline:

  • TensorFlow 1.x was hard to debug (graph mode, sessions)
  • TensorFlow 2.x (2019) fixed issues but researchers already migrated to PyTorch
  • Keras integration helped but couldn’t reverse momentum

Verdict: Losing research mindshare, still strong in production environments

Learning Curve: 7.5/10#

Documentation:

  • Official docs: Excellent (comprehensive, well-organized)
  • Community tutorials: Abundant (legacy TF 1.x content can confuse)

Error messages:

  • Improved in TF 2.x (eager execution helps)
  • Still cryptic for graph-mode errors
  • Shape inference issues harder to debug than PyTorch

Onboarding speed:

  • Beginner: 3-5 weeks (conceptual overhead with graph/eager modes)
  • Intermediate (from NumPy): 2-3 weeks
  • Expert (from PyTorch): 1-2 weeks (unlearning dynamic graphs)

Keras integration:

  • High-level API (tf.keras) is easier than core TensorFlow
  • Most new users start with Keras (gentler curve)

Verdict: Steeper than PyTorch, but Keras helps

Performance: 8.5/10#

Training speed (published benchmarks):

  • ResNet-50 (ImageNet): ~baseline (comparable to PyTorch)
  • BERT-Large: ~baseline
  • TPU optimization: Excellent (Google hardware advantage)

Inference latency:

  • CPU: Excellent (highly optimized)
  • GPU: Excellent (CUDA + cuDNN)
  • TPU: Excellent (native Google hardware)
  • Mobile: Excellent (TF Lite quantization)

Memory efficiency:

  • Good (graph mode can optimize memory)
  • XLA compiler for additional speedups
  • Mixed precision well-supported

Verdict: Excellent performance, especially on Google infrastructure

Speed Score: 8.3/10#

Calculation: (9.0 + 9.8 + 6.5 + 7.5 + 8.5) / 5 = 8.268.3/10

Quick Take#

Strengths:

  • ✅ Best production deployment story (TF Serving, TF Lite)
  • ✅ Excellent mobile/edge support (industry standard)
  • ✅ Strong performance on Google Cloud (TPU optimization)
  • ✅ Mature ecosystem (TensorBoard, cloud integrations)

Weaknesses:

  • ❌ Declining research adoption (15% of papers vs PyTorch 75%)
  • ⚠️ Steeper learning curve than PyTorch
  • ⚠️ Legacy TF 1.x content causes confusion
  • ⚠️ Debugging still harder than PyTorch (graph mode issues)

Best for:

  • Production-first teams (serving existing models)
  • Mobile/edge deployment requirements
  • Google Cloud native environments
  • Teams with existing TensorFlow codebases

Avoid if:

  • Research-heavy workload (PyTorch ecosystem larger)
  • New team (PyTorch easier to learn)
  • Prototyping speed critical (PyTorch faster iteration)

TensorFlow 1.x vs 2.x Note#

TF 1.x (2015-2019):

  • Graph mode only (define-then-run)
  • Sessions, placeholders (verbose, hard to debug)
  • Dominated research/production

TF 2.x (2019-present):

  • Eager execution by default (define-by-run, like PyTorch)
  • Keras integrated as high-level API
  • Backward compatible (can still use graph mode)

Migration: Most production systems migrated TF 1.x → TF 2.x (2019-2022). Research teams migrated TF 1.x → PyTorch instead.

S2: Comprehensive

S2: Comprehensive Analysis - Approach#

Research date: 2026-08-25 (S1 was written against January 2024 figures) Focus: Where each framework stops being Python and becomes a compiled graph — and what that single choice decides downstream

What This Pass Asks#

S1 ranked four frameworks on a five-part score and produced an ordering. An ordering is the wrong shape for this category, because these frameworks are not four attempts at the same design. They are four different answers to one question:

At what moment does your Python stop being Python?

Every accelerator — a GPU, a TPU, an NPU in a phone — runs a compiled program, not a Python interpreter. Somewhere between the model you typed and the kernel that runs, the Python has to be turned into a graph. The frameworks differ in when that happens, who asks for it, and what happens when it fails:

FrameworkCapture happensWho asksOn failure
PyTorchNever, by defaultOpt-in torch.compileSilently falls back to Python
TensorFlowAt a decorator@tf.functionRetraces, silently
JAXAt every transformationjit, grad, vmapRaises
MXNetAt hybridize()Opt-in, on a HybridBlockRaises — and the project is retired

This is the boundary the survey sorts on, and it is not a matter of taste. It decides how you debug, what you can deploy, which hardware you can reach, and what a wrong guess costs.

The second half of the finding follows from the first: the capture boundary is also the deployment boundary. The artifact you can move off the training machine is exactly the part you were able to capture as a graph. That is why PyTorch’s own deployment story has moved from serving Python to exporting graphs, why LiteRT accepts models from all three live frameworks, and why “which framework do I deploy with” turns out to be a less interesting question in 2026 than it was in 2020.

Method#

Primary sources only, checked on 2026-08-25:

  1. The projects’ own source and docs, read from tagged releases — torch.compile’s signature and docstring from torch/__init__.py at v2.13.0, torch.export’s guarantees from docs/source/user_guide/torch_compiler/export.md at the same tag, MXNet’s HybridBlock docstring from the installed 1.9.1 package.
  2. Registries — PyPI’s JSON API for versions, upload dates, license metadata and dependency pins.
  3. Repository state — the GitHub API for archive status, last push, and commits over the trailing 52 weeks.
  4. The Apache Attic, for MXNet’s governance status.
  5. One install. MXNet 1.9.1 was installed into a clean Python 3.12.3 virtualenv and imported. What happened is in mxnet.md.

Where a claim could not be checked against one of those, it is marked unverified or left out. S1’s adoption percentages are in that category and are addressed in recommendation.md.

Structure of This Pass#

  • pytorch.md — eager by default, capture as an optimization
  • tensorflow.md — capture at a decorator, and the artifact that made it famous
  • jax.md — capture as the programming model
  • mxnet.md — retired: what the status is, and what to do about it
  • recommendation.md — what the mechanism changes, and what S1 got wrong

Scope Boundary#

This survey covers the frameworks you build and train a model in. Inference runtimes (ONNX Runtime, LiteRT, TensorRT, vLLM) appear only where a framework’s deployment path runs through them; they are a neighboring category, not this one. Higher-level libraries that sit on top — Keras, Flax, Lightning, Hugging Face Transformers — appear only where they change what a framework can do.


JAX in Depth#

Version checked: 0.11.1 on PyPI, uploaded 2026-08-17. Repository: jax-ml/jax, not archived, 7,826 commits in the trailing 52 weeks, 36,216 stars (GitHub API, 2026-08-25). Release cadence: 0.9.2 (2026-03-18), 0.10.0 (2026-04-16), 0.10.1 (2026-05-20), 0.10.2 (2026-06-17), 0.11.0 (2026-07-16), 0.11.1 (2026-08-17) — monthly.

Execution Model: Capture Is the Programming Model#

PyTorch and TensorFlow both let you write ordinary Python and then bolt capture on. JAX inverts that. Capture is not an optimization applied to a program; it is what every JAX transformation does, and the language you are allowed to write is constrained so that capture is always sound.

The transformations, per the API reference: jit (compile with XLA), grad / value_and_grad / jacfwd / jacrev / hessian / jvp / vjp (differentiate), vmap (vectorize), and for parallelism shard_map and smap, with pmap documented as the “Old way of doing parallel map.”

They compose. jit(vmap(grad(f))) is a compiled, batched gradient, and you did not write a batch dimension, a backward pass, or a kernel. This composition is the thing JAX has that the others do not, and it is available only because every transformation operates on a function rather than on a running program.

Autodiff Is a Function Transformation, Not a Tape#

grad(f) returns a new function. There is no tape, no .grad attribute on an array, no backward() call, and no notion of gradients accumulating in a model object. Forward-mode (jvp) and reverse-mode (vjp) are both first-class and both composable with each other, which is why JAX turns up in scientific computing — higher-order derivatives and Jacobians are ordinary function calls rather than research projects.

The Price: Purity Is Enforced#

The constraints are not style advice. They are what make the transformations correct, and the documentation states them as rules:

  • Pure functions. All input data passes through parameters and all results come out through return values. Side effects during tracing are captured once, or not at all.
  • Immutable arrays. “Allowing mutation of variables in-place makes program analysis and transformation difficult.” x[i] = v becomes x.at[i].set(v), which returns a new array.
  • Explicit PRNG keys. There is no global random state to seed; a key is a value you thread through, which is what makes a JAX computation bit-reproducible across devices.
  • Shapes cannot depend on values. Inside jit, “the size of slices can’t be functions of argument values but only functions of argument shapes.”
  • Out-of-bounds indexing does not raise. “JAX must choose some non-error behavior for out of bounds indexing” — reads clamp, writes are dropped. This is the one constraint that bites without telling you.

A JAX program that runs at all is usually a JAX program that compiles. That is the trade: the errors arrive at the top of the funnel rather than at the deployment boundary.

JAX Is Not a Neural Network Library#

The package is array programming plus transformations plus XLA. Layers, parameter management and optimizers come from a separate tier: Flax 0.12.9 (2026-08-18), Optax 0.2.8 (2026-03-20), Equinox 0.13.8 (2026-05-05), dm-haiku 0.0.17 (2026-07-27). All four are active. This is a real cost — it is one more decision, and the tier has churned before — and a real benefit, because none of them own your training loop.

Deployment: StableHLO, With a Written Compatibility Window#

JAX’s export path is the most specific of the three about what it promises. jax.export lowers to StableHLO and serializes it, and the documentation states the window in plain numbers: a consumer can be “up to 6 months newer than the version of JAX used for exporting” (backward compatibility), and “up to 3 weeks older than the version of JAX used for exporting” (forward compatibility).

Six months backward and three weeks forward is a narrow, explicit contract, and it is more than either of the other two frameworks states about its own artifact. It also tells you what JAX expects: that the thing consuming your model is redeployed often.

For on-device targets, LiteRT lists “Convert JAX models” as a supported path.

Hardware#

jax publishes extras for cpu, cuda12, cuda13, rocm7-local, oneapi (Intel) and tpu. The TPU extra pins libtpu==0.0.46.*, whose current release is dated 2026-08-14 — three days before jax 0.11.1. TPU support is not a bridge project here; it ships with the framework.

Apple Silicon GPU is the gap: jax-metal last released 0.1.1 on 2024-10-08.

What JAX Cannot Do#

  • Let you keep your Python habits. In-place mutation, global RNG state and data-dependent shapes are all gone, and no library restores them.
  • Fail loudly on out-of-bounds indexing. Reads clamp silently.
  • Give you a model server. There is no first-party equivalent to TF Serving. Deployment means exporting StableHLO and hosting it yourself, or converting.
  • Be one decision. Choosing JAX is choosing JAX plus a neural network library plus an optimizer library.

Sources#


MXNet: Retired#

Status: Apache MXNet is retired. It is not declining, not under-resourced, and not at risk of abandonment. It has been formally retired by the Apache Software Foundation and moved to the Apache Attic.

Everything in this file was checked on 2026-08-25.

What “Retired” Means Here, With Sources#

The Apache Atticattic.apache.org/projects/mxnet.html, which lists MXNet among the Foundation’s retired projects, states:

“MXNet became a Top Level Project in September 2022, retired in September 2023 and the move to the Attic was completed in February 2024.”

The project’s own websitemxnet.apache.org redirects to /versions/1.9.1/ and carries the line:

“This project has retired. For details please refer to its Attic page.”

GitHubapache/mxnet is archived (read-only). Its last push was 2023-10-25. The GitHub statistics API reports 0 commits in the trailing 52 weeks, including 0 in each of the last twelve weeks.

PyPI — the newest mxnet release is 1.9.1, uploaded 2022-05-17. Four years and three months without a release, against PyTorch’s eight-week cadence.

The Attic’s own framing is the operative one: a retired project’s resources are read-only, and the Foundation’s note to anyone still interested is “if you should choose to fork outside of Apache, please let us know so we can link to your project.”

It Does Not Install Cleanly Any More#

Retirement is a governance fact. This is the operational one.

MXNet 1.9.1 was installed into a clean Python 3.12.3 virtualenv on aarch64 Linux on 2026-08-25. pip succeeded. The import did not:

OSError: libarmpl_lp64_mp.so: cannot open shared object file:
No such file or directory

ldd on the shipped libmxnet.so shows three unresolved dependencies — libarmpl_lp64_mp.so, libamath.so, libastring.so — all part of Arm Performance Libraries, none bundled in the wheel and none installable from PyPI. The manylinux2014_aarch64 wheel is, as published, not importable on a stock ARM Linux machine. No one is going to fix that: the repository is archived.

The dependency pin is the other trap. MXNet 1.9.1 declares numpy (<2.0.0,>1.16.0). Any environment that has moved to NumPy 2 — which is most of them — cannot hold MXNet and the rest of its stack at the same time. Resolvers will happily pin you back to numpy==1.26.4, and 1.26.4 has no wheels for Python 3.13 or later.

Practical reading: MXNet today is an x86-64 Linux, Python ≤3.12, NumPy 1.x artifact. Anything outside that box is a build project against a codebase nobody maintains.

What It Was, Mechanically#

For the reader inheriting MXNet code, the design is worth understanding, because it is where the capture boundary of this survey shows up in its most explicit form.

MXNet had two front ends and a switch between them. mx.nd was imperative; mx.sym was symbolic. Gluon’s HybridBlock joined them, and its docstring in the shipped 1.9.1 package states the rule exactly:

“Before activating with hybridize(), HybridBlock works just like normal Block. After activation, HybridBlock will create a symbolic graph representing the forward computation and cache it. On subsequent forwards, the cached graph will be used instead of hybrid_forward.”

and the constraint that comes with it:

“Forward computation in HybridBlock must be static to work with Symbols, i.e. you cannot call NDArray.asnumpy, NDArray.shape, NDArray.dtype, NDArray indexing (x[i]) etc on tensors. Also, you cannot use branching or loop logic that bases on non-constant expressions”

That is the same bargain torch.compile and tf.function make, offered in 2017 with an explicit switch rather than a compiler. MXNet had the right idea about the boundary and lost the ecosystem anyway, which is the useful lesson in it.

If You Are On MXNet: What To Do#

1. Establish whether you can still run it. Confirm x86-64 Linux, Python 3.12 or earlier, NumPy 1.x. If you cannot, the migration is not optional and it is not scheduled — it has already happened to you.

2. Get an ONNX artifact out while you still can. The shipped package contains mxnet.onnx.mx2onnx (export) and mxnet.contrib.onnx.onnx2mx (import). The export path has a condition: export_model takes a symbol and parameters, so it works on a model that was hybridized. A Gluon Block that was never hybridized has no symbolic graph to export, and making it hybridizable means satisfying the static-forward rule quoted above — in unmaintained code, on a retired framework. Do this first, and do it before an OS upgrade forces the question.

3. Rewrite training in a live framework. Inference can ride on ONNX Runtime (1.29.0, 2026-08-17) indefinitely; training cannot. PyTorch is the usual destination — the imperative mx.nd half of MXNet maps onto it closely, and Gluon’s Block and PyTorch’s nn.Module are the same concept. TensorFlow is the destination if your deployment target is LiteRT and you would rather keep one vendor’s toolchain.

4. Do not treat the download count as a signal. mxnet was pulled 574,942 times in the 30 days to 2026-08-25 (pypistats). That is pinned requirements files and CI, not adoption. A retired project’s download count measures how much code has not been migrated yet.

What S1 Got Wrong About This#

S1 recorded “commit velocity: 5-10 commits/week (down from 50+/week in 2018)”, “Apache incubator graduation stalled”, and a recommendation to “migrate existing projects within 12-24 months.”

All three are wrong. The commit rate is zero and the repository is read-only. MXNet did not stall in the incubator; it graduated to Top Level Project in September 2022 and was retired a year later. And the migration window S1 offered was already closed when S1 was written — the move to the Attic completed in February 2024.

Sources#


PyTorch in Depth#

Version checked: 2.13.0 on PyPI, uploaded 2026-07-08. Repository: pytorch/pytorch, not archived, 17,271 commits in the trailing 52 weeks, 102,603 stars (GitHub API, 2026-08-25). Release cadence: 2.10.0 (2026-01-21), 2.11.0 (2026-03-23), 2.12.0 (2026-05-13), 2.13.0 (2026-07-08) — a minor release roughly every eight weeks.

Execution Model: Python Is the Runtime#

PyTorch’s answer to “where does Python stop?” is: it doesn’t, unless you ask. Operations dispatch one at a time as the interpreter reaches them. Your stack trace is your model. print prints. pdb breaks where you put the breakpoint. This is the whole reason the framework won research, and it is a property of the execution model rather than of the API.

Autodiff: A Tape Built During the Forward Pass#

From docs/source/notes/autograd.md at v2.13.0:

“Autograd is a reverse automatic differentiation system. Conceptually, autograd records a graph recording all of the operations that created the data as you execute operations”

and the consequence, stated in the same note:

“the graph is recreated from scratch at every iteration, and this is exactly what allows for using arbitrary Python control flow statements, that can change the overall shape and size of the graph at every iteration. You don’t have to encode all possible paths before you launch the training - what you run is what you differentiate.”

Each tensor carries a .grad_fn pointing into that graph. The graph is built as a side effect of running the model, so anything Python can express — a loop whose length depends on the data, a branch on a tensor value — is differentiable without special syntax. The cost is that the graph exists only for the duration of one step: there is nothing to save, optimize ahead of time, or ship.

Compilation: torch.compile, and Its Escape Hatch#

torch.compile is the opt-in capture. Three pieces, per the 2.13 user guide:

  • TorchDynamo — “an internal API that uses a CPython feature called the Frame Evaluation API to safely capture PyTorch graphs.”
  • AOT Autograd — captures the backward pass ahead of time as well as the forward.
  • TorchInductor — “The default backend is called TorchInductor, also known as inductor.” Other in-tree backends include cudagraphs, ipex, tensorrt, tvm and openvino.

The defining behavior is what happens when capture fails. From the torch.compile docstring in torch/__init__.py at v2.13.0:

“A single frame may be compiled multiple times if previous compiled results are not applicable for subsequent calls (this is called a “guard failure”) … Multiple compiled results can be associated with a frame up to torch._dynamo.config.recompile_limit, which defaults to 8; at which point we will fall back to eager.”

And on partial capture, from the same docstring:

“If False (default), torch.compile attempts to discover compilable regions in the function that it will optimize. If True, then we require that the entire function be capturable into a single graph. If this is not possible (that is, if there are graph breaks), then this will raise an error.”

So the default is a soft boundary. Untraceable Python is not an error; it is a graph break, and the program keeps working at eager speed. That is excellent for adoption and treacherous for performance work — a model that “compiled” may have been cut into forty graphs. fullgraph=True is how you turn the soft boundary into a hard one, and it is the setting that tells you the truth.

Deployment: The Story Moved, and the Old One Is Archived#

This is where the trailing edge of the S1 pass is furthest from 2026.

  • TorchServe is no longer maintained. pytorch/serve is archived on GitHub (last push 2025-08-06); the torchserve package on PyPI last released 0.12.0 on 2024-09-30. Its README carries the notice: “This project is no longer actively maintained. While existing releases remain available, there are no planned updates, bug fixes, new features, or security patches. Users should be aware that vulnerabilities may not be addressed.”
  • TorchScript is deprecated. In docs/source/redirects.py at v2.13.0, every jit* documentation page is redirected under the comment # Redirects for deprecated TorchScript documentation.
  • PyTorch Mobile is gone as a separate thing. pytorch.org/mobile/home/ returns HTTP 301 to the ExecuTorch documentation.

What replaced them is a hard capture boundary. torch.export produces an ExportedProgram — a flattened ATen graph with no Python semantics in it — and it refuses to guess:

“When {func}torch.compile runs into an untraceable part of a model, it will “graph break” and fall back to running the program in the eager Python runtime. In comparison, torch.export aims to get a full graph representation of a PyTorch model, so it will error out when something untraceable is reached.”

That exported graph feeds ExecuTorch (1.4.1, 2026-08-14; mobile, embedded and MCU targets), AOTInductor (ahead-of-time compiled shared objects for server inference), ONNX, and LiteRT via litert-torch (0.9.4, 2026-08-24). All four are healthier than the serving stack they replaced.

The shape of this: PyTorch is the easiest framework to write and the one that asks the most of you at the deployment boundary, because the flexibility that made training pleasant is exactly what torch.export will refuse.

Hardware#

Wheels are published from download.pytorch.org/whl/ for CPU, CUDA (through cu132), ROCm (through rocm7.2), and Intel xpu. The tree at v2.13.0 contains first-party torch/mps (Apple Silicon GPU), torch/xpu and torch/mtia backends. This is the widest first-party accelerator coverage of the three live frameworks.

TPUs are the exception, and a sharp one — see jax.md and the TPU persona in S3.

Distributed Training#

In-tree and documented at v2.13.0: DDP, fully_shard (FSDP2), DTensor, tensor parallelism, pipeline parallelism, and symmetric memory. The stack is Python-level and composes with eager execution, so it can be stepped through in a debugger the way a single-GPU model can.

What PyTorch Cannot Do#

  • Give you a portable artifact for free. Anything you want to ship has to survive torch.export, and data-dependent control flow is the common thing that does not.
  • Reach TPUs on the current release. torch_xla’s latest release is 2.9.0 (2025-11-17), four minor versions behind torch 2.13.0.
  • Guarantee that “it compiled” means anything. Graph breaks are silent by design.

Sources#


S2 Recommendation: What the Mechanism Changes#

S1 produced a ranking. S2 finds that the ranking was measuring the wrong thing, that two of its four entries were factually out of date, and that the category is better read as three live positions on one boundary plus one retired project.

The Category Is Three Positions on the Capture Boundary#

Capture happensFailure modeArtifactSays what it promises about it
PyTorchOnly if you askSilent graph break, falls back to PythonExportedProgram (ATen), then ExecuTorch / AOTInductor / ONNXNo stated window
TensorFlowAt @tf.functionSilent retraceSavedModel, then LiteRT / TF ServingNo stated window
JAXAt every transformationRaisesStableHLO via jax.export6 months backward, 3 weeks forward

Read left to right, the table is one gradient: the later you let the capture happen, the more pleasant the writing and the more work the deployment. PyTorch defers everything and charges you at torch.export, which “will error out when something untraceable is reached.” JAX charges you at the first line — pure functions, immutable arrays, static shapes — and hands you a serialized graph with a written compatibility window. TensorFlow sits between them and always has.

There is no position on that gradient that is better than the others. There is only a question of which end of the project you would rather spend the difficulty at.

The Four Findings That Should Change a Decision#

1. The deployment argument for TensorFlow has weakened, and not because TensorFlow got worse. LiteRT — the successor to TensorFlow Lite — documents conversion from “PyTorch, JAX or TensorFlow.” The edge target that used to force the framework choice now accepts all three, and litert-torch shipped 0.9.4 on 2026-08-24. What survives of the argument is the SavedModel path being the best-worn one, and TF Serving being the last maintained first-party model server.

2. PyTorch’s serving story is gone and its replacement is different in kind. pytorch/serve is archived; its README says the project “is no longer actively maintained … no planned updates, bug fixes, new features, or security patches.” TorchScript’s documentation is marked deprecated in the 2.13 tree. pytorch.org/mobile/home/ 301s to ExecuTorch. Anyone who chose PyTorch in 2024 on the strength of TorchServe needs to re-plan around torch.export — which is a stricter boundary than TorchScript ever was.

3. TPUs are a JAX-first story now, by a wide margin. jax[tpu] pins libtpu==0.0.46.*, released 2026-08-14, three days before jax 0.11.1. torch_xla’s newest release is 2.9.0 (2025-11-17) against torch 2.13.0, and its repository logged 92 commits in the trailing 52 weeks with zero in the last twelve. A team on TPUs choosing PyTorch is choosing to run several versions behind.

4. MXNet is retired, not declining. Retired in September 2023, moved to the Apache Attic in February 2024, repository archived, zero commits in 52 weeks, last PyPI release 2022-05-17. See mxnet.md, including the observed import failure on ARM Linux and the NumPy 1.x pin.

Where S1 Was Wrong#

Recorded here because this survey is published and S1’s claims are on the public page.

S1 claimWhat the source says (2026-08-25)
MXNet: “5-10 commits/week”, “migrate within 12-24 months”0 commits in 52 weeks; repository archived; Attic move completed February 2024
MXNet: “Apache incubator graduation stalled”Became a Top Level Project in September 2022, then retired
PyTorch: “TorchServe (official, production-ready)”pytorch/serve archived; “no longer actively maintained”
PyTorch: “77K stars”, “50-100 commits/week”102,603 stars; 17,271 commits in 52 weeks
TensorFlow: “182K stars”, “30-50 commits/week”197,638 stars; 13,982 commits in 52 weeks
JAX: “28K stars”, “20-40 commits/week”36,216 stars; 7,826 commits in 52 weeks
“TensorFlow Lite: industry standard”Superseded by LiteRT, which converts from PyTorch and JAX too
Research adoption percentages sourced to Papers With Codepaperswithcode.com now 302s to huggingface.co/papers/trending; the cited source no longer exists and the figures cannot be re-verified

The last row matters beyond the numbers. S1’s whole ranking leaned on adoption percentages from a site that has since been shut down, and no equivalent public dataset replaced it. This survey therefore does not assert framework shares. It reports commit counts, release dates, archive status and download figures, all of which can be re-checked by the reader.

Choose By Where You Want the Difficulty#

  • “I need to see what my model is doing, step by step.” → PyTorch. The graph is rebuilt every iteration; what you run is what you differentiate.
  • “I need a file I can hand to a runtime and a promise about it.” → JAX, whose export contract is written down, or TensorFlow, whose SavedModel has the most tooling around it.
  • “I need TPUs.” → JAX. The evidence is in finding 3.
  • “I need it on a phone.” → Any of the three. Pick on the training experience, then convert to LiteRT or ExecuTorch.
  • “I need a maintained model server I do not write myself.” → TF Serving, or a framework-neutral runtime.
  • “I am on MXNet.” → Export to ONNX now; migrate training to PyTorch.

What S2 Did Not Settle#

Relative training speed. S1 asserted JAX is “2-10× faster”; nothing in a primary source verified that, published benchmarks are almost always vendor- or framework-authored on hardware you do not have, and all three live frameworks lower to broadly similar kernels on the same silicon. What survives is that the compiler you get is XLA in two cases and TorchInductor in the third, and that any number worth acting on has to come from your model on your hardware. That measurement is S3’s business, not a benchmark table’s.


TensorFlow in Depth#

Version checked: 2.21.0 on PyPI, uploaded 2026-03-06. Repository: tensorflow/tensorflow, not archived, 13,982 commits in the trailing 52 weeks, 197,638 stars (GitHub API, 2026-08-25). Release cadence: 2.20.0 (2025-08-13), then 2.21.0 (2026-03-06) — the slowest of the three live frameworks by a wide margin, about seven months between minor releases against PyTorch’s eight weeks.

Execution Model: Eager by Default, Graph at a Decorator#

TF2 runs eagerly like PyTorch. The graph is opt-in, and it arrives at a decorator rather than through a compiler pass. From the TensorFlow graphs guide:

“The code in a tf.function can be executed both eagerly and as a graph. By default, tf.function executes its code as a graph”

The capture mechanism is tracing: TensorFlow runs your Python once, with symbolic tensors, and records the TensorFlow operations it sees.

“Tracing captures the TensorFlow operations into a graph, and print is not captured in the graph.”

The result is a ConcreteFunction — “a wrapper around a tf.Graph” — keyed to one input signature. Python constructs that tracing cannot see are handled by AutoGraph, which rewrites Python control flow into graph-generating code: “tf.function uses a library called AutoGraph (tf.autograph) to convert Python code into graph-generating code.”

The Failure Mode Is Silent Retracing#

Where PyTorch’s failure mode is a silent graph break, TensorFlow’s is a silent retrace:

“New Python arguments always trigger the creation of a new graph, hence the extra tracing.”

and, from the same guide’s best practices:

“If you find you are getting unusually poor performance, it’s a good idea to check if you are retracing accidentally.”

Both frameworks, in other words, would rather keep running than tell you the capture went wrong. Both give you a way to demand the truth — fullgraph=True in PyTorch, input_signature and tf.config.run_functions_eagerly in TensorFlow — and in both cases you have to know to ask.

Autodiff: An Explicit Tape#

TensorFlow does not build a tape unless you open one. From the autodiff guide: “TensorFlow “records” relevant operations executed inside the context of a tf.GradientTape onto a “tape”. TensorFlow then uses that tape to compute the gradients of a “recorded” computation using reverse mode differentiation.”

Two behaviors decide most gradient bugs: the tape watches trainable tf.Variables automatically but not tf.Tensors — “To record gradients with respect to a tf.Tensor, you need to call GradientTape.watch(x)” — and it is consumed on first use: “By default, the resources held by a GradientTape are released as soon as the GradientTape.gradient method is called.” persistent=True is the opt-out.

Deployment: The Part That Still Leads#

TensorFlow’s advantage was never speed. It was that the traced graph is a file — the SavedModel — and an ecosystem grew around that file.

  • TF Serving is alive: tensorflow/serving last pushed 2026-08-25. It is the only first-party model server among the three that is still maintained. PyTorch’s equivalent is archived.
  • LiteRT is the on-device runtime, described by Google as “Built on the battle-tested foundation of TensorFlow Lite.” The ai-edge-litert runtime released 2.2.0 on 2026-08-12.
  • TensorFlow.js is the weak point. tensorflowjs on PyPI last released 4.22.0 on 2024-10-21, and tensorflow/tfjs last pushed 2026-06-23. It works; it is not moving.

The strategic fact under all of this: LiteRT is no longer a TensorFlow feature. Its own documentation says you can “Use .tflite pre-trained models or convert PyTorch, JAX or TensorFlow models to .tflite.” The mobile deployment target that was TensorFlow’s strongest reason to exist now accepts all three. That does not make TensorFlow a bad choice for edge work — the conversion path from a SavedModel is the most traveled one — but it removes the argument that edge work requires it.

Keras Is a Separate Decision Now#

From TF 2.16’s release notes: “Keras 3.0 will be the default Keras version.” Keras 3 runs on JAX, TensorFlow or PyTorch, selected by the KERAS_BACKEND environment variable, and “the backend must be configured before importing Keras, and the backend cannot be changed after the package has been imported.” Teams that thought they were choosing TensorFlow when they chose Keras are choosing an API layer that outlived that coupling. tf-keras (2.21.0) exists for code pinned to Keras 2.

Hardware#

pip install tensorflow[and-cuda] on Linux. Two documented gaps: “TensorFlow 2.10 was the last TensorFlow release that supported GPU on native-Windows”, and “Currently there is no official GPU support for running TensorFlow on MacOS” — tensorflow-metal is Apple’s separate plugin, last released 1.2.0 on 2025-01-31. TPU support is first-party, via tf.distribute.

What TensorFlow Cannot Do#

  • Move at the pace of the other two. Seven months between minor releases is a strategic fact, not a bug, but it is a fact.
  • Give you a clean single story. TF1 idioms, TF2 eager, tf.function graphs, Keras 2 and Keras 3 all coexist in the search results a new engineer will find.
  • Claim the edge exclusively any more. LiteRT takes PyTorch and JAX.

Sources#

S3: Need-Driven

S3: Need-Driven Discovery - Approach#

Research date: 2026-08-25 Focus: Which constraint decides, once you accept that all three live frameworks can train the model

What This Pass Asks#

S2 established that the three live frameworks differ in where they put the capture boundary, and that the boundary propagates into deployment, hardware and debugging. S3 asks the practical follow-on: for a given reader, what forces the answer?

The finding that emerges across the personas below is that it is almost never the model. Any of PyTorch, TensorFlow or JAX will train a transformer, a convolutional network, or a policy. What differs is everything around the model — the chip you are allowed to buy, the runtime you have to land on, whether you wrote the code you are maintaining, and whether anyone will ever step through it in a debugger.

So the personas are organized by constraint, not by workload. “Computer vision” is not a persona; “cannot buy NVIDIA” is.

Method#

Each persona is a WHO with a WHY, and it earns a file only if flipping its constraint flips the recommendation. Every technical claim underneath one traces to S2, which traces to a primary source checked on 2026-08-25.

No persona here is the reason this survey exists. The survey is a category comparison for any reader; a persona whose constraints match one below can take its answer, and a reader whose constraints span two will find the answers compose.

Personas Covered#

  1. The interactive debugger — the model has to be inspectable while it runs
  2. The on-device shipper — a phone, a browser, or a microcontroller decides
  3. The TPU team — the chip is chosen and it is not a GPU
  4. The scaling lab — the model does not fit on one device
  5. The inheritor — maintaining a model somebody else wrote, in a framework nobody chose
  6. The non-NVIDIA shop — AMD, Intel, or an Apple Silicon laptop

What This Pass Does Not Do#

It does not rank the frameworks, and it does not benchmark them. S2 declined to assert relative training speed because no primary source supported a number; that decision holds here. Where speed matters to a persona, the answer is a measurement they have to run, and the survey says which measurement.


Persona: The Inheritor#

Who: someone maintaining a model they did not write, in a framework they did not choose — an acquisition, a departed colleague, a research prototype that went to production, a vendor deliverable.

Why this changes the answer: for everyone else the model is an asset and the framework is a choice. Here the model is a liability with a clock on it, and the only real question is how much time is left.

The Constraint#

Three things decay independently, and the inheritor usually discovers them in the wrong order:

  1. The framework — is it still released?
  2. The environment — can you still build the environment it needs?
  3. The knowledge — can anyone read the code?

The third is the one people plan for. The second is the one that ends projects, because it arrives as an OS upgrade rather than as a decision.

The Answer, by What You Inherited#

MXNet — act now, and read S2-comprehensive/mxnet.md first. The project is retired: moved to the Apache Attic in February 2024, repository archived, zero commits in the trailing 52 weeks, last PyPI release 2022-05-17. It pins numpy (<2.0.0,>1.16.0) and its ARM Linux wheel did not import on a clean Python 3.12 environment on 2026-08-25. Get an ONNX export out while an environment that can run it still exists, then rewrite training in PyTorch. There is no version of this that gets easier by waiting.

TensorFlow 1.x — the estimator API was removed in TF 2.16 and Keras 3 became the default in the same release. If the code imports tf.estimator or tf.Session, it is pinned to TF 2.15 or earlier and the pin is load-bearing. tf-keras (2.21.0) plus TF_USE_LEGACY_KERAS=1 buys time for Keras 2 code specifically.

TorchScript — it still runs, and its documentation is marked deprecated in the PyTorch 2.13 tree. Not urgent; do not build anything new on it. The successor is torch.export, and re-exporting is a real project because torch.export “will error out when something untraceable is reached” where TorchScript would have accepted it.

A model on TorchServepytorch/serve is archived and its README states there will be no security patches. If it is exposed to a network, this is the item on this page with the shortest fuse. Move to a framework-neutral runtime, or to torch.export plus AOTInductor.

The Trap#

Rewriting the model instead of extracting the weights. A trained model is weights plus a graph, and the weights are the part nobody can regenerate. The first move on any inherited model is to get a portable artifact — an ONNX file, an exported graph, a checkpoint with a documented schema — out of the environment that can still produce one. Doing the rewrite first means doing it with the original environment as your only reference, and that environment is the thing that is expiring.

What Would Flip It#

Inference-only. If nothing is being retrained, an ONNX artifact plus ONNX Runtime (1.29.0, 2026-08-17) is a stable place to sit for years, and the framework question becomes moot rather than urgent. That is the cheapest outcome available to this persona. Check for it before anything else.


Persona: The Interactive Debugger#

Who: someone whose loop is change one thing, look at what happened — a researcher on a new architecture, an engineer chasing a loss that goes to NaN on step 4,000, anyone whose model is not yet known to work.

Why this changes the answer: they need to stop the program in the middle of the forward pass and look at a tensor. That is a property of the execution model, and it is the one place where the three live frameworks are not interchangeable.

The Constraint#

The question is not “can I debug it” — all three have debuggers, profilers and TensorBoard integrations. The question is whether the thing running when you hit the breakpoint is your Python.

  • PyTorch: it is. The autograd note is explicit that the graph “is recreated from scratch at every iteration”, so a breakpoint inside forward stops inside forward, with real tensors and real shapes.
  • TensorFlow: inside a @tf.function, it is not. Tracing runs your Python once with symbolic tensors; print fires at trace time and never again. tf.config.run_functions_eagerly(True) gets you back, and you have to know that.
  • JAX: it is not, and the framework says so rather than pretending. Under jit you are holding tracers. Debugging means jax.debug.print, or dropping the jit and paying the speed.

The Answer#

PyTorch, and the margin is not close for this persona specifically.

The chain of reasoning is short: eager execution means the stack trace is the model, and a model that is not yet known to work is a model you will read stack traces of all week.

The Trap#

Reaching for torch.compile at the same time. Graph breaks are silent by default, and recompile_limit is 8 before it “will fall back to eager” — so a compiled model that got slower gives you no error to chase. Get the model correct eagerly; add torch.compile(..., fullgraph=True) afterward and let it tell you what it could not capture.

What Would Flip It#

Two things.

If the work is differentiable scientific computing — higher-order derivatives, Jacobians, forward-mode — JAX’s transformations are worth the loss of interactivity, because jacfwd(jacrev(f)) in JAX is a line and in PyTorch it is a project.

If the model is already known to work and the loop is now “train it faster”, this persona has ended and the TPU or scaling persona has begun.


Persona: The Non-NVIDIA Shop#

Who: a team whose accelerators are AMD, Intel, or Apple Silicon — by procurement policy, by price, by supply, or because the development machines are laptops.

Why this changes the answer: everything in this category assumes CUDA until you check, and the frameworks diverge sharply on what they publish first-party for anything else.

The Constraint#

Two different questions hide inside “does it support my hardware”:

  • Does the vendor ship it? A first-party wheel from the framework’s own release process is maintained on the framework’s cadence.
  • Does someone else ship it? A plugin from the chip vendor is maintained on the chip vendor’s cadence, which may be slower or stopped.

The distinction is not academic. It is the difference between upgrading your framework and being unable to.

The Landscape, Checked 2026-08-25#

AMD (ROCm) — PyTorch publishes ROCm wheels from download.pytorch.org/whl/, currently through rocm7.2, on the same release train as the CUDA builds. JAX ships a rocm7-local extra. TensorFlow’s ROCm story runs through a separate distribution.

Intel GPU — PyTorch has an in-tree torch/xpu backend at v2.13.0 and publishes xpu wheels. JAX ships an oneapi extra.

Apple Silicon GPU — PyTorch has a first-party in-tree torch/mps backend. TensorFlow does not: its own install page says “Currently there is no official GPU support for running TensorFlow on MacOS”, and tensorflow-metal is Apple’s separate plugin, last released 1.2.0 on 2025-01-31. JAX’s is worse — jax-metal last released 0.1.1 on 2024-10-08.

Windows — “TensorFlow 2.10 was the last TensorFlow release that supported GPU on native-Windows.” WSL2 is the documented path.

The Answer#

PyTorch, and this is the persona where its lead is widest and least disputed. It is the only one of the three that ships AMD, Intel and Apple GPU support from its own release process — ROCm and XPU wheels published from download.pytorch.org, plus in-tree torch/xpu and torch/mps.

JAX is a defensible second for AMD and Intel datacenter parts, through its rocm7-local and oneapi extras. It is not a choice for anyone whose development machine is a Mac and who expects the GPU to be used.

The Trap#

Treating a laptop GPU backend as a training target. torch/mps makes a MacBook a workable place to write and debug a model at small batch sizes. It is not where the run happens, and a team that conflates the two ends up with a model shaped by what fits in unified memory.

What Would Flip It#

Being on TPUs — a different chip question with a different answer, in the TPU persona. Or having no local hardware at all, in which case this persona dissolves into whatever the cloud provider offers and the choice returns to the other constraints on this page.


Persona: The On-Device Shipper#

Who: a team whose model has to run on a phone, in a browser, or on a microcontroller — not in a datacenter, not behind an API.

Why this changes the answer: in 2020 the target dictated the framework. In 2026 it dictates the runtime, and the runtime takes models from all three. That inversion is the single biggest change in this category since the survey’s first pass.

The Constraint#

The device runs a compiled graph. It has no Python, so whatever cannot cross the capture boundary does not ship. This persona therefore feels S2’s boundary harder than anyone: a model with data-dependent control flow is not a slow model here, it is an unshippable one.

The Answer, by Target#

Phone (iOS/Android) — either LiteRT or ExecuTorch, and the framework follows from which one you pick rather than the other way round. LiteRT documents conversion from “PyTorch, JAX or TensorFlow”; litert-torch released 0.9.4 on 2026-08-24 and ai-edge-litert 2.2.0 on 2026-08-12. ExecuTorch released 1.4.1 on 2026-08-14 and covers “Android & iOS”, “Linux, macOS, Windows” and “Embedded & MCUs”. Both are active. Pick on which conversion path your model survives, tested early on the real model.

Microcontroller — LiteRT’s lineage or ExecuTorch’s MCU support. This is the target where the model has to be co-designed with the constraint, and the framework is the least interesting decision in the project.

Browser — this is the one target where the choice is forced, and not toward TensorFlow. @tensorflow/tfjs on npm is at 4.22.0, published 2024-10-21; onnxruntime-web is at 1.29.0, published 2026-08-24. Export to ONNX and use ONNX Runtime Web. The S1 pass rated TensorFlow.js “Excellent” for web; on release activity that is no longer supportable.

The Trap#

Choosing the training framework first, on training-experience grounds, and discovering at the end that the model does not export. Run the conversion on day three with a stub model of the right shape. Every conversion path in this persona will refuse something, and the cost of learning which one is an order of magnitude lower at the start.

What Would Flip It#

An existing SavedModel estate. If the models already exist as SavedModels, the TensorFlow → LiteRT path is the best-worn one in this category and there is no reason to move.


Persona: The Scaling Lab#

Who: a team training a model that does not fit on one device — dozens to thousands of accelerators, weeks of wall-clock time, a job that has to survive a node failure.

Why this changes the answer: at this size the question stops being “which framework runs my model” and becomes “who decides how the model is split.” The two live answers are structurally different.

The Constraint#

Sharding a model is either something you describe or something you do.

  • JAX makes it a description. Sharding is expressed over a device mesh — jax.sharding, shard_map, smap, with pmap documented as the “Old way of doing parallel map” — and the compiler places the computation. The model code does not know how many chips it is on.
  • PyTorch makes it a composition of mechanisms you apply. At v2.13.0 the in-tree stack is DDP, fully_shard (FSDP2), DTensor, tensor parallelism, pipeline parallelism and symmetric memory, each documented separately, and you assemble the parallelism strategy from them.

Neither is wrong. They fail differently. A JAX sharding bug is a compilation error or a surprising placement; a PyTorch parallelism bug is a hang, at hour nine, on 512 ranks.

The Answer#

It depends on whether you own the model code.

If the model is yours to shape — a lab training its own architecture — JAX is the better fit at this scale. The purity constraints that annoyed the interactive-debugger persona are what let the compiler reason about placement, and describing a mesh once beats threading a parallelism strategy through a model.

If the model came from somewhere else — a Hugging Face checkpoint, a reference implementation, a partner’s code — PyTorch, because that is what it is written in, and porting a large model to JAX to get better sharding is a rewrite with a numerical-equivalence problem attached.

The Trap#

Choosing on throughput claims. S2 declined to assert relative training speed because no primary source supported a figure, and this persona is the one most often sold one. The number that decides a run of this size is tokens or samples per second per dollar, on your model, on the chips you can actually get, measured for a day. Two frameworks that both lower to XLA will not differ the way a marketing chart says they do — and if they do, you want to know it from your own run.

What Would Flip It#

A hard requirement for elastic or fault-tolerant training over unreliable nodes. That is an infrastructure decision above the framework — TorchElastic, Kubernetes, checkpoint cadence — and it can outweigh everything above.


Persona: The TPU Team#

Who: a team whose compute is Google TPUs — because of a research credit, a Cloud commitment, or a capacity constraint that made GPUs unavailable at the size they need.

Why this changes the answer: the hardware was chosen before the framework, and the software paths to that hardware are not in comparable health.

The Constraint#

TPUs are reached through XLA. All three live frameworks can lower to XLA in principle. Only one of them ships the TPU path as part of the framework’s own release.

Checked 2026-08-25:

TPU pathCurrent state
JAXjax[tpu] extra, in the framework’s own metadataPins libtpu==0.0.46.*, released 2026-08-14 — three days before jax 0.11.1
PyTorchtorch_xla, a separate bridge projectLatest release 2.9.0 (2025-11-17) against torch 2.13.0; pytorch/xla logged 92 commits in 52 weeks and zero in the last twelve
TensorFlowFirst-party, via tf.distributeShipped in the framework, on a roughly seven-month release cadence

The Answer#

JAX, unless you are already on TensorFlow.

The reasoning is release mechanics rather than performance. JAX’s TPU support is a dependency extra of the same package, versioned in lockstep, so upgrading the framework upgrades the TPU path. PyTorch’s is a separate project four minor versions behind and quiet for a quarter, so choosing PyTorch on TPUs means pinning torch at 2.9 and forgoing everything merged since — including whatever lands in 2.14.

TensorFlow’s TPU support is first-party and fine. The reason not to move to it from scratch is its release cadence: 2.20.0 in August 2025, 2.21.0 in March 2026.

The Trap#

Assuming “XLA on both sides” means the paths are equivalent. They compile to the same backend and are supported by different amounts of engineering — and the difference does not show up in a benchmark, it shows up as a CVE you cannot patch because the fix landed in a torch you cannot upgrade to.

What Would Flip It#

Hardware portability as a requirement. If the model must also run on GPUs from more than one vendor without a rewrite, weigh JAX’s plugin matrix — it publishes cuda12, cuda13, rocm7-local and oneapi extras — against PyTorch’s first-party CUDA, ROCm and XPU wheels, and see the non-NVIDIA persona.

Also flip it if the team is small and new to functional programming. JAX asks for purity, immutable arrays and static shapes before it gives you anything, and a TPU allocation does not by itself pay for that.


S3 Recommendation: Choose By Constraint, Not By Benchmark#

Across six personas, the framework that wins most often wins for reasons that have nothing to do with how fast it trains, and the two personas where it loses are decided by a release date rather than by a measurement.

That is the finding. In this category the constraint that decides is almost always upstream of the model.

The Table#

PersonaForcing constraintAnswer
Interactive debuggerThe stack trace has to be the modelPyTorch
On-device shipperThe runtime decides, and it takes all threeAny — pick the runtime first
TPU teamThe chip was chosen before the frameworkJAX
Scaling labWho owns the model codeJAX if you do, PyTorch if you don’t
InheritorHow much time is left on the environmentExtract the artifact, then PyTorch
Non-NVIDIA shopWho ships the accelerator backendPyTorch

The Three Rules That Cover Most Cases#

1. Pick the runtime before the framework if anything ships off the training machine. LiteRT converts from “PyTorch, JAX or TensorFlow”; ExecuTorch covers phones through microcontrollers; ONNX Runtime covers servers and browsers. Once the runtime is fixed, the framework question gets much smaller — and doing it in this order finds the models that will not export while they are still cheap to change.

2. Match the framework to who owns the hardware decision. If someone handed you TPUs, that points at JAX for release-mechanics reasons laid out in the TPU persona. If someone handed you AMD, Intel or Macs, that points at PyTorch for the same kind of reason. The chip is usually decided further up the organization than the framework, and it should propagate downward rather than be argued with.

3. Default to PyTorch when nothing above applies. Not because it is fastest — no primary source in this survey supports a speed ranking — but because eager execution keeps the debugging loop short, the accelerator coverage is the widest, and the largest body of published model code is written in it. The cost of that default is that you will meet the capture boundary later, at torch.export, rather than earlier.

The Question to Ask First#

Does this model ever leave the machine it was trained on?

If no — research, internal analysis, a batch job on the same box — the capture boundary never binds, and the whole deployment half of this survey is irrelevant to you. Optimize for the debugging loop and stop reading.

If yes, the boundary is the project, and it should be tested in week one against the actual runtime with the actual model. Every framework here will let you write something it cannot export. Finding that out early costs a day. Finding it out at the end costs the architecture.

What This Pass Does Not Do#

It does not pick for any particular product, and it does not rank the three live frameworks against each other in the abstract, because the abstract comparison is the one that produced S1’s wrong answers. Two teams with identical models land on different frameworks because one of them was given TPUs and the other was given Macs, and both are right.

S4: Strategic

S4: Strategic Selection - Approach#

Research date: 2026-08-25 Focus: not “which is best” but what does this choice cost to reverse in three years — and who pays

What This Pass Asks#

S1 ranked. S2 explained the mechanism. S3 matched constraints to readers. S4 asks the only question that is still open once a team has picked: if this turns out to be wrong, what does it cost to undo?

That question has a specific shape in this category, and the shape comes straight out of S2’s organizing idea. If the capture boundary is also the deployment boundary, then choosing a framework is not choosing an API. It is quietly choosing, three years ahead:

  • which runtimes your models can reach,
  • which chips you can buy,
  • what survives when you leave, and
  • how late you will find out.

None of those are visible on day one. All of them are decided on day one.

The Reversal-Cost Model#

Every section below scores one framework choice on five costs, in the order a team actually meets them:

CostThe question
SourceHow much of your code is framework-shaped rather than model-shaped?
ArtifactCan the trained weights leave, and what do they lose on the way out?
RuntimeDoes the framework fix which serving stack you can use?
HardwareDoes it fix which accelerators you can buy?
DiscoveryWhen do you find out any of this — day one, or month eighteen?

Discovery is the one people leave out, and it is where the category inverts. The framework that constrains you least while writing tells you least about your exit, and tells you latest.

Method#

Primary sources, checked 2026-08-25 and cited where used: the projects' own documentation and repositories at tagged releases, PyPI, npm, the Apache Attic, the Linux Foundation and PyTorch Foundation’s own pages, the ONNX specification’s versioning document, and ONNX Runtime’s stated compatibility policy.

Two rules held throughout, both inherited from S2:

  1. No number without a source. This pass makes no claim about relative training speed, market share, or migration duration in person-months, because no primary source consulted supported one.
  2. An absence is a finding, and is reported as one. Where a project states no compatibility guarantee for its own artifact, that is recorded as “states none” rather than filled in with an estimate.

Structure of This Pass#

  • lock-in.md — scoring the five costs across the three live frameworks
  • governance.md — who owns each project, and why that predicts less than it looks like it should
  • mxnet-postmortem.md — the worked example: what the end of a framework actually looks like
  • tpu-commitment.md — the one live decision in this category with a visible expiry
  • exit-strategy.md — ONNX, torch.export, StableHLO: what carries a model out, and what each drops
  • recommendation.md — what to commit to, and what to keep reversible

Exit Strategy: What Carries a Model Out, and What It Drops#

Every recommendation in this survey is conditional on being able to leave. This file costs that.

Three export formats matter, and they differ on the only two questions that decide an exit: what does the artifact drop, and what does its owner promise about reading it back.

The Comparison#

ONNXtorch.export (PT2)jax.export (StableHLO)SavedModelLiteRT .tflite
Produced byAll three, via convertersPyTorchJAXTensorFlowConverted from all three
Carries trainingNoTraining IR exists; not a training formatNoPartiallyNo
Owned byONNX, via an elected steering committeePyTorchOpenXLA (openxla/stablehlo)TensorFlowGoogle
Stated read-back guaranteeOpsets back to 7, by policyStates none6 months back, 3 weeks forwardStates none foundStates none found

The right-hand row is the whole file.

ONNX: The Strongest Guarantee, Owned by None of Them#

ONNX Runtime’s versioning document states it without hedging:

“All versions of ONNX Runtime will support ONNX opsets all the way back to (and including) opset version 7.”

Opset 7 corresponds to ONNX 1.2. The current release, ONNX 1.22.0 (2026-06-15), is at opset 27. So a model exported at opset 12 in 2020 loads in ONNX Runtime 1.29.0 (2026-08-17), by stated policy rather than by luck.

The mechanism underneath is stricter than the promise. From the ONNX specification’s versioning document: “Changes to the semantics of an operator or function MUST be introduced in a new operator, which MUST be introduced in a new operator set”, and the contributor procedure requires copying “the old operator schema to an old.cc file.” Operator semantics are never edited in place. An old graph does not merely load; it means what it meant.

It is also the only thing in this survey with governance that is not downstream of one company. ONNX’s own governance document describes “3 roles: Member, Contributor and Approver” and a Steering Committee elected by Contributors and Approvers, with the structure “based on the successful model of Kubernetes.”

The strategic reading is uncomfortable and useful: the most durable artifact format in this category is the one none of the frameworks own, and the only one whose governance is not controlled by a single vendor. Every framework here treats ONNX as an escape hatch, and the escape hatch has both better compatibility discipline and broader ownership than any of the framework-native formats.

What ONNX drops: training. An ONNX graph is inference. Optimizer state, the training loop, the data pipeline and any custom autograd all stay behind. It also drops anything the exporter could not express — which is where old exports get thin, and why the export should be produced and loaded back while the source environment still runs.

torch.export: A Full Graph, and No Written Window#

torch.export produces an ExportedProgram — a flattened ATen graph, normalized, with no Python semantics. It is a stronger capture than TorchScript ever was, and it will “error out when something untraceable is reached” rather than silently accepting something wrong.

On durability, the documentation at v2.13.0 is silent. The PT2 archive layout carries three separate version numbers — the archive version, “the export serialization schema version” and the “Aten Opset Version” — and the export documentation states no backward- or forward-compatibility span for any of them. Searching the export docs at that tag for compatibility guarantees returns none.

That is recorded here as an absence, not as a defect. The format is young and moving fast, and no promise is more accurate than a promise that gets broken. But for a team whose reason to export is archival — a regulator, a five-year support obligation, a model that has to be reproducible after the team disperses — an unstated window is not a window. Export to ONNX as well and store both.

jax.export: The Only Written Contract Among the Frameworks#

JAX’s export documentation states its window in numbers: a consumer may be “up to 6 months newer than the version of JAX used for exporting”, and “up to 3 weeks older than the version of JAX used for exporting.”

Six months backward is short for archival purposes. Three weeks forward is very short, and it encodes an assumption: that whatever consumes your model is redeployed often. This is a serving contract, not a preservation contract, and it is written by people who know the difference.

It is nevertheless more than either of the other two frameworks says about its own artifact, and a stated short window is more actionable than an unstated long one. A team can schedule against six months. It cannot schedule against silence.

SavedModel and .tflite: Durable in Practice, Undocumented in Promise#

TensorFlow’s SavedModel is the most widely-tooled artifact in the category and has survived TF1 to TF2, the removal of tf.estimator, and two generations of Keras without the format itself breaking. No compatibility window statement was found for it in this pass; it is recorded as durable by track record rather than by contract.

.tflite is a deployment endpoint, not an archive. It is quantized, device-targeted, and lossy relative to the source graph. Never let a .tflite be the only surviving copy of a model.

The Rule That Falls Out#

Weights are the irreplaceable thing. The graph is the expensive thing. The framework is the cheap thing.

A checkpoint of trained weights is recoverable in almost any scenario — it is a tensor dictionary and it can be read. The graph is what does not travel, and every format above is a different amount of graph. The framework is the layer everyone argues about and the layer that matters least at exit, because by then the question is what the artifact carries, not what produced it.

The Exit Checklist#

Cheap to do at the start of a project; expensive to reconstruct later.

  1. Export once, early, on a stub model of the right shape. You are testing whether the architecture is exportable, not the weights. Every path here refuses something.
  2. Load the export back, in a separate process. An export that has never been read is not an export.
  3. Keep two formats when the model matters. The framework-native one for fidelity, ONNX for the compatibility policy.
  4. Store the version numbers with the artifact. Framework version, exporter version, opset. All three formats above are versioned and none of them are self-describing about their producer.
  5. Re-run the export in CI. This is the only step that catches the day someone adds a data-dependent branch that quietly makes the model unshippable — which, on PyTorch’s silent-graph-break default, is a day nothing else will flag.

Step 5 is the one that converts this survey’s organizing idea into an engineering practice: if the capture boundary is the deployment boundary, put the capture boundary in the test suite.

Sources#


Governance: Who Owns Each Project, and What It Predicts#

The instinct in a strategic pass is to score governance and treat the score as a survival probability. This category contains a clean natural experiment showing that the mapping does not hold, so this file does the scoring and then says what it is good for.

Who Owns What, Checked 2026-08-25#

PyTorch is a Linux Foundation project. From its own announcement: “PyTorch is moving to the Linux Foundation (LF) as a top-level project under the name PyTorch Foundation”, with “a governing board of leaders from AMD, Amazon Web Services (AWS), Google Cloud, Meta, Microsoft Azure and NVIDIA.” The Linux Foundation’s press release carries the dateline “DUBLIN – September 12, 2022”. The foundation’s own site describes its mission as supporting “an open, vendor-neutral ecosystem built around PyTorch,” and the announcement is specific about the split: “The creation of the PyTorch Foundation will ensure business decisions are being made in a transparent and open manner by a diverse group of members … The technical decisions remain in control of individual maintainers.” The same post states plainly that “Meta remains the largest contributor to PyTorch.”

TensorFlow has no foundation. The repository sits in a Google-controlled GitHub organization; there is no GOVERNANCE.md in tensorflow/tensorflow. Process lives in a separate tensorflow/community repository holding “rfcs - design documents used by the design review process”, SIG documentation and “governance - operating processes for the TensorFlow project”, whose stated contact is a @google.com address. This is a real, documented, open process. It is not vendor-neutral ownership, and it does not claim to be.

JAX has no foundation either, and is the most direct about its status. Its own README states: “This is a research project, not an official Google product. Expect sharp edges.” The repository moved from google/jax to jax-ml/jax, which reads as a step away from single-brand identity, but no charter, foundation, or governing board accompanies it.

MXNet had the most formally neutral governance of the four: an Apache Software Foundation Top Level Project, with an elected PMC, a mailing-list decision record and a trademark held by a nonprofit.

The Natural Experiment#

Two of those milestones happened in the same month.

DateEvent
September 2022MXNet becomes an Apache Top Level Project
September 12, 2022PyTorch moves to the Linux Foundation
September 2023MXNet is retired
February 2024MXNet’s move to the Apache Attic completes

The framework with the most vendor-neutral governance in this category graduated to it and died within twelve months. Governance did not save it, and could not have: an Apache PMC is a decision-making structure, not a supply of contributors. What MXNet ran out of was people, and no charter generates those.

So the strategic reading is narrower than “prefer neutral governance”:

Governance tells you what happens to the project’s assets when the sponsor leaves. It tells you nothing about whether the sponsor leaves, and nothing about whether anyone remains.

That narrower claim is still useful. It is the claim that MXNet validates from the other direction: because MXNet was an Apache project, its retirement was orderly and legible. There is a dated Attic page, a read-only archive, preserved mailing lists, and an explicit invitation — “if you should choose to fork outside of Apache, please let us know so we can link to your project.” Compare the alternative ending, in which a single vendor stops funding a team and the repository simply goes quiet with no announcement and no date. MXNet’s users got a signal they could act on. That is what the governance bought.

What Actually Predicts Survival Here#

On the evidence in this survey, the leading indicators are boring and countable:

SignalPyTorchTensorFlowJAXMXNet
Commits, trailing 52 weeks17,27113,9827,8260
Time between minor releases~8 weeks~7 months~1 monthn/a
Downloads, 30 days to 2026-08-2591,234,41118,176,81620,858,459574,942
Repository stateactiveactiveactivearchived

Commit rate and release cadence are the two that moved first for MXNet. Downloads moved last and are still moving — 574,942 in the last 30 days, for a framework that has been read-only since 2023. A download count is the slowest-decaying signal in the set, which makes it the worst one to choose on.

The Concentration Risk Nobody Escapes#

All three live frameworks have a single dominant contributor: Meta for PyTorch (stated in PyTorch’s own announcement), Google for TensorFlow and for JAX. The PyTorch Foundation broadens who decides business questions and explicitly leaves technical decisions with maintainers, most of whom are employed by that dominant contributor.

There is no diversified option in this category. A team that wants to hedge sponsor risk cannot do it by picking a different framework; it can only do it by keeping the exit cheap, which is exit-strategy.md’s subject.

Sources#


Lock-In: Scoring the Capture Boundary#

S2’s finding was that the capture boundary is also the deployment boundary. Read forward three years, that sentence is a lock-in thesis: what you can ship later is fixed by what you could capture, and the capture rule was chosen the day you picked the framework.

This file scores that, on the five costs from approach.md.

The Scoring#

PyTorchTensorFlowJAX
SourceMedium — model code is framework-shaped, but the shape is imperative and reads like PythonMedium-high — tf.function boundaries, tf.data pipelines and Keras structure are all TF-shapedHigh — purity, .at[].set(), explicit PRNG keys and static shapes are not portable idioms
ArtifactWeights leave easily; the graph is the hard partSavedModel is the most portable artifact in the categoryStableHLO leaves with a written window
RuntimeWide and moving — ExecuTorch, AOTInductor, ONNX, LiteRTWidest and most settled — TF Serving, LiteRT, plus ONNXNarrow — no first-party server; export or convert
HardwareWidest — CUDA, ROCm, Intel XPU, Apple MPS from its own release process; TPU is the gapCUDA and TPU first-party; no macOS GPU, no native-Windows GPU after 2.10CUDA, ROCm, oneAPI and TPU as extras; Apple GPU stale
DiscoveryLatest. Graph breaks are silent; you learn your real boundary at torch.exportMiddle. Retracing is silent, but the SavedModel forces the question at save timeEarliest. The program does not run until it is capturable

The Inversion#

Rank those columns by how much they constrain you while writing, and you get JAX, TensorFlow, PyTorch. Rank them by how much you know about your own exit at the end of month one, and you get the same order.

The framework that constrains you most at write time locks you in least at exit time, because the constraints are what make the artifact exportable. A JAX program that runs has already proved it can be captured. A PyTorch program that runs has proved nothing about that at all.

This is not an argument for JAX. It is an argument for knowing which trade you took. PyTorch’s deferral is worth real money in the phase where the model is not yet correct — S3’s interactive-debugger persona is not wrong. The cost is that the deferral is also a deferral of information, and the information arrives at the least convenient moment: when the model works and someone wants to ship it.

What Each Lock-In Actually Feels Like#

PyTorch’s is a late surprise. Nothing stops you. torch.compile graph-breaks silently and keeps running; the docstring is explicit that after recompile_limit — “which defaults to 8” — “we will fall back to eager.” So a model can be written, trained, validated and scheduled for release before anyone runs torch.export, which “will error out when something untraceable is reached.” The lock-in is not to PyTorch. It is to the eager-only subset of your own codebase, and you find out how large that subset is at the end.

TensorFlow’s is a layer surprise. The artifact is durable; the Python around it is what has moved. tf.estimator was removed outright in TF 2.16, and Keras 3 became the default in the same release, with tf-keras plus TF_USE_LEGACY_KERAS=1 offered as the compatibility path. A team that wrote against TF’s high-level APIs has been asked to migrate twice without the SavedModel format itself breaking. The lock-in is to an API generation, not to a file format.

JAX’s is a stack surprise. JAX is array programming plus transformations; the neural network layer is a separate decision — Flax, Equinox, Haiku — plus Optax for optimizers. All are currently active (checked 2026-08-25), and all are a smaller dependency than the framework under them. The lock-in that matters here is not to JAX, whose exported StableHLO has a stated compatibility window; it is to whichever module-system library you chose, which has neither a foundation nor a compatibility contract.

The Cost Nobody Prices: Hardware#

Framework choice fixes your accelerator options more firmly than it fixes anything else, and it does so through code you will never read.

The concrete case is Apple Silicon. PyTorch has an in-tree torch/mps backend at v2.13.0. TensorFlow’s own install page states “Currently there is no official GPU support for running TensorFlow on MacOS”, and tensorflow-metal — Apple’s separate plugin — last released 1.2.0 on 2025-01-31. jax-metal last released 0.1.1 on 2024-10-08. A team whose developers are on Macs and who chose JAX in 2024 for good reasons now has a laptop story that has not shipped in nearly two years, and nothing about that was visible in the framework comparison they read.

The same logic runs the other way for TPUs, and it is sharp enough to have its own file: tpu-commitment.md.

Reversibility, Ranked#

If the question is “how bad is it if we are wrong”:

  1. Reversing the runtime is cheap and getting cheaper. LiteRT converts from all three. ONNX Runtime takes all three. The deployment layer has become framework-neutral, which means the runtime is now the least locked-in decision in this category — the opposite of its position in 2020.
  2. Reversing the artifact is bounded. Weights are weights. The graph is the part that does not travel, and exit-strategy.md costs that.
  3. Reversing the hardware is expensive, because it means changing framework, and often changing procurement.
  4. Reversing the source is the whole project, and no framework in this category makes that cheaper than any other.

The practical consequence is that a team should spend its caution on items 3 and 4 — the chip and the code — and stop treating item 1 as the strategic decision it was six years ago.


MXNet: What the End of a Framework Looks Like#

Every strategic assessment in this category is an argument about a risk nobody has watched happen. This one has been watched, start to finish, with dates. MXNet is the most instructive thing in this survey, and it is worth reading as a timeline rather than as a verdict.

S2 established the status and the sources. This file asks the S4 question: what did the end actually look like from inside, and which signal would have been worth acting on?

The Timeline, With Sources#

WhenWhatSource
2017–2018Peak. A major cloud vendor’s preferred framework; multi-language bindings; a high-level API (Gluon) that was ahead of its timeS1’s record
September 2022Becomes an Apache Top Level Project — the most formally neutral governance of any framework in this surveyApache Attic
2022-05-17Last release to PyPI: 1.9.1PyPI JSON API
2023-09RetiredApache Attic
2023-10-25Last push to apache/mxnetGitHub API
2024-02Move to the Apache Attic completedApache Attic
2026-08-25Repository archived; 0 commits in the trailing 52 weeks; mxnet.apache.org states “This project has retired.”GitHub API, project website
2026-08-25574,942 downloads in the previous 30 dayspypistats

Note the ordering. The last release preceded the retirement by sixteen months, and preceded the last commit by seventeen. The package registry went quiet well before the governance did.

The Signal That Would Have Been Worth Acting On#

Run the list backwards and ask which indicator moved first.

  1. Release cadence stopped — May 2022. Sixteen months of warning.
  2. Commit rate collapsed, then hit zero — through 2023.
  3. Governance changed — September 2023, and the paperwork finished in February 2024.
  4. Downloads — still 574,942 a month, three years after the last release.

The signal with the longest lead time was the cheapest to check: a registry page showing no new release. It costs one HTTP request and it was true a year and a half before anything official was announced.

The signal most teams actually watch — adoption, popularity, download counts — was the one that never moved. It is still not moving. Half a million downloads a month is not a floor under MXNet; it is a measure of how much code has not been migrated yet, and every one of those pulls is a build that is going to break.

Watch the release date. Ignore the download count. That is the transferable lesson, and it applies to every framework in this survey.

What “Retired” Escalated Into#

The strategically interesting part is what happened after the governance event, because this is the part teams underestimate when they plan a migration with a comfortable window.

Retirement is a status. Two years later it had become an operational failure:

  • The NumPy pin. MXNet 1.9.1 declares numpy (<2.0.0,>1.16.0). The ecosystem moved to NumPy 2. An environment cannot hold MXNet and a current scientific Python stack at once, and resolvers pin back to numpy==1.26.4, which has no wheels for Python 3.13 or later.
  • The wheel that does not import. Installed into a clean Python 3.12.3 virtualenv on aarch64 Linux on 2026-08-25, pip install mxnet succeeded and import mxnet raised OSError: libarmpl_lp64_mp.so: cannot open shared object file. The published ARM Linux wheel links three Arm Performance Libraries that are neither bundled nor available from PyPI.

Nobody decided either of those. They are what happens when the world moves and the repository is read-only. A retired framework does not stay where you left it — the ground moves under it, and the failures arrive as environment errors during an unrelated upgrade rather than as anything a roadmap would have flagged.

This is the specific reason S3’s inheritor persona is told to act now rather than to schedule a migration. The window is not defined by the framework. It is defined by the next time someone upgrades Python, NumPy, or a base image.

What MXNet Got Right, and Why It Did Not Matter#

Two things deserve recording, because both are commonly proposed as protection.

The license was permissive. Apache 2.0. Anyone could have forked it. Nobody did at a scale that produced a maintained successor. A permissive license is permission to rescue a project, not a supply of people willing to.

The design was sound. MXNet’s hybridize() put the capture boundary under an explicit switch in 2017 — the same bargain torch.compile and tf.function make today, offered years earlier. Being right about the architecture did not help. What it lost was the ecosystem: the tutorials, the pretrained checkpoints, the Stack Overflow answers, the next graduate student.

The Transferable Conclusions#

  1. Check the last release date, on a schedule. It is the earliest available signal and it is free.
  2. Treat “retired” as already operational, not as a countdown. Nothing gets fixed after that date, including things that break later for unrelated reasons.
  3. A permissive license is not a maintenance commitment. All four frameworks here are permissively licensed. One of them is dead.
  4. Vendor-neutral governance buys an orderly ending, not a longer life. MXNet’s users got a dated Attic page and a read-only archive. That is worth something. It is not survival.
  5. Get the artifact out while the environment still runs. This is the one that turns knowledge into a saved model, and it has a deadline somebody else controls.

Sources#


S4 Recommendation: Commit to the Boundary, Not to the Framework#

Three passes converged on one structure: the capture boundary decides the mechanism (S2), decides which reader gets which answer (S3), and decides what a choice costs to reverse (S4). The strategic conclusion follows from that and is narrower than a framework pick.

Commit to the export path. Keep the framework reversible.

Why That Way Round#

The deployment layer went framework-neutral while nobody was watching. LiteRT converts from “PyTorch, JAX or TensorFlow.” ONNX Runtime takes all three and supports opsets back to 7 by policy. ExecuTorch covers phones to microcontrollers. In 2020 the runtime followed the framework; in 2026 the runtime is the stable layer and the framework is the interchangeable one.

That inverts the usual advice. The durable commitment is to an artifact format with a stated compatibility policy. The framework above it is a developer-experience choice that can be revisited, and the cost of revisiting it is dominated by rewriting model code — which no framework in this category makes cheaper than any other.

What To Actually Commit To#

1. An export path, tested in CI from week one. Not documented — run. Step 5 of the exit checklist is the whole recommendation compressed: if the capture boundary is the deployment boundary, put it in the test suite. On PyTorch specifically this is not optional, because graph breaks are silent and torch.compile falls back to eager after recompile_limit, “which defaults to 8”. Nothing else will tell you the day a model stops being shippable.

2. ONNX as the archival copy for anything that must outlive the team. It has the only guarantee in this survey with a number and a floor: opsets back to 7, with operator semantics never edited in place. It is owned by none of the frameworks, which is a feature here.

3. A quarterly check of two dates per dependency: last release, and last commit. That is the check that would have given MXNet’s users sixteen months of warning, and it is the check that is currently the only visible signal on torch_xla.

What To Keep Reversible#

The framework. Default to PyTorch when no constraint above you says otherwise — widest hardware coverage, shortest debugging loop, largest body of published model code — and understand that you are trading early information for early velocity. Its lock-in is real and it is late.

The hardware, where you can. This is the most expensive thing to reverse, because reversing it usually means changing framework too. If TPUs are a cost optimization rather than a requirement, dropping them removes the survey’s only decision with a live expiry (tpu-commitment.md).

The high-level API. TensorFlow’s users have been migrated twice — tf.estimator removed in 2.16, Keras 2 to Keras 3 in the same release — without the SavedModel format ever breaking. JAX’s users carry the same exposure one layer up, in Flax or Equinox or Haiku. Keep the model definition thin enough that the layer library is replaceable.

What Not To Choose On#

Download counts. MXNet was pulled 574,942 times in the 30 days to 2026-08-25, three years after its last release and two after its retirement. Downloads are the slowest-decaying signal available and therefore the worst one to decide on. Release dates moved sixteen months earlier.

Governance form. The framework with the most vendor-neutral governance in this category — an Apache Top Level Project as of September 2022 — was retired twelve months later. Governance determines whether the ending is orderly, not whether there is one. All three live frameworks have a single dominant contributor and there is no diversified option available.

Permissive licensing. All four frameworks here are permissively licensed. One of them is dead, and nobody forked it into a maintained successor. A license is permission to rescue a project, not a supply of people who will.

Training speed. No primary source consulted in any pass of this survey supported a ranking, so none is offered. If it matters at your scale, it is a measurement on your model and your silicon, not a selection criterion you can read off a page.

The Three-Year View#

If nothing changes: PyTorch remains the default and its export story keeps consolidating around torch.export; TensorFlow remains the answer for existing SavedModel estates and holds the last maintained first-party model server; JAX remains the TPU and large-scale-sharding answer and does not become a general-purpose default. The runtimes keep absorbing the deployment decision.

The two things most likely to change that, and worth watching:

  • torch_xla resuming or not. One release closes most of the TPU gap; two more quiet quarters make it a strategic fact rather than a release-engineering one.
  • The inference-runtime layer’s own durability. ONNX, LiteRT and ExecuTorch now carry the deployment decision that frameworks used to. This survey did not assess that layer’s long-term health — it is a neighboring category, and on the evidence here it is the layer worth surveying next.

Where This Pass Would Change Its Mind#

If a maintained fork of a retired framework ever appeared and held, the “permissive licensing is not a maintenance commitment” claim would need qualifying. Nothing in this pass found one for MXNet, and the Apache Attic’s standing invitation — “if you should choose to fork outside of Apache, please let us know so we can link to your project” — has, as far as this survey could verify, gone unanswered.


TPU Commitment: The One Decision With a Visible Expiry#

S3 answered “I have TPUs, which framework?” with JAX. That was a recommendation. This file makes the strategic case, because the evidence is not a feature comparison — it is a divergence in release engineering that has been widening for nine months and is measurable to the day.

The Two Paths, Measured#

Checked 2026-08-25.

JAX’s TPU support is a dependency extra of the framework itself. jax declares a tpu extra pinning jaxlib<=0.11.1,>=0.11.1 and libtpu==0.0.46.*. libtpu 0.0.46 was released 2026-08-14; jax 0.11.1 was released 2026-08-17. The accelerator runtime shipped three days before the framework release that requires it. Upgrading JAX upgrades the TPU path, because they are versioned together by construction.

PyTorch’s TPU support is a separate bridge project. torch_xla’s newest release is 2.9.0, 2025-11-17. torch is at 2.13.0, 2026-07-08. That is four minor versions of divergence. The pytorch/xla repository logged 92 commits in the trailing 52 weeks and zero in the last twelve, against pytorch/pytorch’s 17,271.

What That Means for a Three-Year Commitment#

A team standardizing on PyTorch and buying TPU capacity is agreeing to something that is not written down anywhere in the decision:

  • Their torch version is pinned by their accelerator. Not to the current release, but to 2.9 — which shipped before 2.10, 2.11, 2.12 and 2.13.
  • Security patches follow the same pin. A fix landing in a torch they cannot install is not available to them. This is the failure mode that does not appear in any benchmark and is the one that wakes people up.
  • The gap is compounding, not static. torch has shipped four minor releases since torch_xla’s last. At PyTorch’s roughly eight-week cadence, the gap grows by one minor version per quarter unless torch_xla resumes.
  • They inherit a second project’s health. The framework’s own vitality signals — 17,271 commits, foundation governance, six-company board — say nothing about the bridge, which has its own and much quieter ones.

What Is Not Being Claimed#

That torch_xla is abandoned. It is not archived, it has releases within the last year, and twelve quiet weeks is not a retirement — MXNet’s equivalent quiet stretch ran to years before the announcement came. A 2.10 release could land next month and close most of this.

That JAX is faster on TPUs. No primary source consulted supports a speed ranking, and this survey does not make one.

The claim is narrower and checkable: on release mechanics, one of these two paths ships with the framework and the other does not, and the difference is currently four minor versions and twelve weeks.

How To Hold This Decision#

This is the one item in the survey with a re-check date attached, because it can change in either direction with a single release.

If you are choosing now and TPUs are fixed — JAX, and take the functional-programming cost with your eyes open (S3’s TPU persona covers what that cost is).

If you are on PyTorch and considering TPUs — do not treat the port as a framework-neutral infrastructure decision. Price the version pin, and ask what happens to the pin if the bridge stays quiet for another two quarters.

If you are already on PyTorch + TPUs — check torch_xla’s release page against torch’s each quarter. Two consecutive quarters with no torch_xla release, while torch ships, is a signal worth planning against. One quiet quarter is not.

If TPUs are a cost optimization rather than a requirement — this is the cheapest constraint in the survey to drop. GPUs are reachable from all three frameworks with first-party support, and dropping the TPU requirement removes this entire file from your decision.

Sources#

Published: 2026-08-25 Updated: 2026-08-25