Getting a model out of Python  / field guide
Practitioner field guide · 24 September 2026

Everything that demanded the whole program got archived

Ten years of Meta's machine-learning platform, reconstructed from the artefacts it is changed through: the PyTorch source tree at eight release tags, design records including one closed without merging, dated archive banners on nine sibling repositories, four published security advisories, five package registries, and the issues downstream maintainers filed when a capture path was deprecated under them. The pattern it exposes is a rule you can apply to any system that has to move a program from the language it was written in to the place it has to run.

50 primary artefacts 8 release tags read 4 advisories Evidence through September 2026 Read: 30 min
01

The territory

A dynamic program written by people who keep changing it, and a destination where the language it is written in does not run.

State the problem without naming a framework and it stops being a machine-learning problem. You have a program in an interpreted language, authored by people whose job is to keep changing it, and you need to run that program somewhere the interpreter is unwelcome: inside a C++ service, on a phone, on an accelerator with its own compiler, in a fleet where per-request interpreter overhead is the cost line. Every design in this guide is a different answer to one question. How much of the program do you capture ahead of time, and what do you do with the part you cannot capture?

Meta has answered that question in public, repeatedly, for a decade, in a repository anyone can read. This guide reconstructs the answers from the tree rather than from the announcements, because the tree is dated and specific: a deprecation marker names the release it landed in, an archive banner names the day the owner gave up, and a package registry says exactly when the last artefact shipped. The finding that organises the rest of the page is that every layer which required the whole program to be captured before it could run has been retired or demoted, and the layers that survived are the ones that capture part of the program and hand the remainder back to Python.

586
catalogued reasons the compiler gives up and returns to Python
2.8
release where sound capture stopped being the default for export
2,258
lines in the build file of the framework that was removed in 2022
9
satellite repositories archived or wound down, 2023 to 2026
The surprise

The replacement for TorchScript made TorchScript's concession, in one line of code, in public. Through PyTorch 2.7 the signature of torch.export.export read strict: bool = True, meaning capture went through TorchDynamo and the resulting graph was sound. In 2.8, released 6 August 2025, the same line reads strict: bool = False. The docstring says what that costs: non-strict tracing "will not validate some of the implicit assumptions baked into the graph", while the strict path "will ensure the soundness of the resulting graph" but "has limited Python feature coverage, thus you may experience more errors". The project chose coverage over soundness for the second time in six years, and this time it wrote the trade-off into the parameter documentation instead of the marketing.

What this guide covers. The published path from authored model to running artefact: capture, intermediate representation, compilation, the runtimes that execute the result, the checkpoint format, and the lifecycle of the satellite libraries around all of it, between 2016 and September 2026. What it deliberately does not cover. Meta's internal training fleet, its accelerator hardware, its recommender serving stack, model quality, and cost. Nothing in the corpus speaks to those, and the network policy for this session blocked the hosts that would: pytorch.org, engineering.fb.com, every paper repository and every talk archive refused at the egress proxy. There are no blog posts, papers or talks in the evidence wall, which is a real limit and is stated again in the ledger.

Figure 1 · Three eras of one question

2023 to 2026: partial capture, explicit escapes

586 catalogued
graph breaks

Model

Capture what traces

Run remainder
in Python

Ahead-of-time artefact
for Python-free targets

2018 to 2024: one framework, whole-program capture

unsupported
Python

Model

Script or trace
the entire model

Rewrite the model

2016 to 2018: two frameworks

Research model
eager Python

Rewrite for
production framework

2023 to 2026: partial capture, explicit escapes

586 catalogued
graph breaks

Model

Capture what traces

Run remainder
in Python

Ahead-of-time artefact
for Python-free targets

2018 to 2024: one framework, whole-program capture

unsupported
Python

Model

Script or trace
the entire model

Rewrite the model

2016 to 2018: two frameworks

Research model
eager Python

Rewrite for
production framework

Each era answers "how much of the program do we capture" differently, and each boundary is dated by an artefact rather than an announcement. Sources: PyPI release history, torch/jit/__init__.py, 2.8.0 release notes.
Diagram source
02

How it is actually built

Four layers, one of which keeps being replaced. Every box below is traceable to a file in the tree.

The shape is stable and the middle is not. Layer one is authoring, which has never moved: eager Python, evaluated line by line. Layer four is execution, where the set of targets has only grown: in-process Python, a standalone shared library, an on-device runtime, an interchange format for somebody else's engine. Layers two and three, capture and lowering, have been rebuilt three times, and each rebuild is a different position on the same trade-off.

The current capture layer is documented as two products rather than one, and the project's own user guide states the difference plainly. On partial capture: "When 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." On full capture: "torch.export aims to get a full graph representation of a PyTorch model, so it will error out when something untraceable is reached." That sentence pair is the architecture. Two entry points, one tolerant and one strict, over a shared compiler stack, because no single answer survived contact with the models people actually write.

Figure 2 · Reference architecture, with the retired paths marked

deprecated in 2.5

Authored model
eager Python

torch.compile
partial capture, JIT

torch.export
full capture, AOT

torch.jit.script
trace

FX graph
plus guards

Inductor
Triton kernels

In-process
Python runtime

AOTInductor
shared library

ExecuTorch
on-device .pte

ONNX exporter
dynamo default from 2.9

Lite Interpreter
deprecated

deprecated in 2.5

Authored model
eager Python

torch.compile
partial capture, JIT

torch.export
full capture, AOT

torch.jit.script
trace

FX graph
plus guards

Inductor
Triton kernels

In-process
Python runtime

AOTInductor
shared library

ExecuTorch
on-device .pte

ONNX exporter
dynamo default from 2.9

Lite Interpreter
deprecated

The two live capture entry points share everything below them; the dashed boxes are deprecated in code, naming their own replacements. Reconstructed from the export user guide, torch/jit/_script.py and issue #151693.
Diagram source

The capture front end

Dynamo evaluates Python bytecode and emits a graph plus guards; where it cannot, it cuts the graph and lets the interpreter run that region. The failure surface is not hidden: it is enumerated, with 586 entries in graph_break_registry.json, each carrying a type, a context, an explanation and hints.

Evidence: the registry file, the site generated from it every three minutes.

The intermediate representation

The exported program claims two invariants that TorchScript never claimed together: soundness, "a sound representation of the original program", and normalisation, "There are no Python semantics within the graph". Those two claims are what make a Python-free target possible at all, and the strict flag is what pays for the first one.

Evidence: export user guide, torch/export/__init__.py.

The container nobody replaced

Checkpoints still travel in the ZIP container implemented under caffe2/serialize, present at every release tag checked from 2.8.0 to 2.14.0 and on main. The framework that contributed it was scheduled for removal in February 2022. The format outlived the framework, which is why the loader, not the graph, is where the security work landed.

Evidence: inline_container.h at v2.14.0, issue #72536.

Two details in that architecture are worth pulling out because they generalise. First, the merge of the production framework in 2018 did not put the acquired code in a corner; it put PyTorch's own build inside the acquired directory. caffe2/CMakeLists.txt on main today is 2,258 lines long and contains add_subdirectory(../aten aten), which is to say the tensor library and libtorch are built from the directory named after the framework a 2022 issue proposed to delete. Removal stalled because it was never a deletion problem; it was a build-graph problem, and build graphs are where architectural debt goes to become invisible.

Second, the escape hatches are load bearing and are treated as such. RFC-0032, the proposal that made NumPy calls traceable, states the policy in one sentence: "For niche functions in NumPy that don't have a PyTorch equivalent, it's okay to graph break and still call NumPy to execute the function call." A design document that plans for the compiler to give up, and names the fallback as acceptable, is a different engineering posture from one that treats unsupported input as a bug to be closed later. The 586-entry registry and the site regenerated from it every three minutes are what that posture looks like once it reaches operations.

03

The decisions that matter

Each fork below is dated, each rejection has a stated reason, and each has a condition under which the rejected option is the right one for you.

Decision: capture the whole program, or capture part of it?

Chosen
  • Partial capture with explicit graph breaks, shipped as torch.compile in 2.0 on 15 March 2023
  • Coverage of real Python beats a clean graph: the untraceable region runs in the interpreter rather than failing the build
Rejected
  • Whole-program scripting, marked .. deprecated:: 2.5 in torch/jit/__init__.py with the text "TorchScript is deprecated, please use torch.compile instead"
  • It required rewriting models to fit the subset of Python it understood
Flips when
  • Your target has no Python at all. Then a graph break is not a fallback, it is a failure, and you are back to full capture and to rewriting control flow with torch.cond and friends

Decision: should the ahead-of-time path guarantee soundness by default?

Chosen
  • From 2.8 on 6 August 2025, no: "Switched default to strict=False in torch.export.export"
  • The permissive path traces through the Python runtime and still validates "most critical assumptions like shape safety"
Rejected
  • Keeping strict=True as the default, which it was through 2.7 on 23 April 2025
  • Stated cost in the docstring: "TorchDynamo has limited Python feature coverage, thus you may experience more errors"
Flips when
  • You serialise once and run the artefact for years in another language or runtime. Then pay for strict=True, accept the rewrites, and treat every unvalidated assumption as a production incident waiting for an input distribution shift

Decision: incubate a new abstraction in a satellite repository, or in the core tree?

Chosen
  • Satellite repositories, with absorption into core as the success condition: TorchElastic landed in 1.9 and its repo was archived on 6 January 2023; functorch shipped in-tree from 21 September 2022 and its repo was archived on 21 August 2025; FairScale's README now reads "This library has been upstreamed to PyTorch"
Rejected
  • Satellites as permanent homes. The data stack stayed outside: DataPipes and DataLoader2 shipped from March 2022 and were removed in torchdata 0.10.1 on 13 December 2024, with the note "This release drops support for DataPipes and DataLoader2"
Flips when
  • The new abstraction requires callers to rewrite working code. Then the satellite never gets absorbed, because absorption means the core team inherits your migration, and they will not. Ship the adapter first, in core, or expect the archive banner

Figure 3 · Which capture path your target forces on you

yes

no

yes

no

no

yes

yes

no

Does the target
run Python?

Is per-call
overhead the cost line?

Stay eager
ship nothing new

torch.compile
budget the graph breaks in CI

Data-dependent
control flow in forward?

torch.export
then AOTInductor or ExecuTorch

Can you change
the model source?

Rewrite with torch.cond
and scan, then export strict

Export non-strict
and test the untested assumptions
on your own input distribution

yes

no

yes

no

no

yes

yes

no

Does the target
run Python?

Is per-call
overhead the cost line?

Stay eager
ship nothing new

torch.compile
budget the graph breaks in CI

Data-dependent
control flow in forward?

torch.export
then AOTInductor or ExecuTorch

Can you change
the model source?

Rewrite with torch.cond
and scan, then export strict

Export non-strict
and test the untested assumptions
on your own input distribution

The terminal nodes are actions, not preferences; the branch that costs the most is data-dependent control flow in a Python-free target. Derived from the export user guide and MONAI issue #8632.
Diagram source
DecisionChosenRejectedBecauseEvidence
Capture granularityPartial, with catalogued breaksWhole-program scriptingCoverage of real Pythondeprecated:: 2.5
Export soundness defaultNon-strict from 2.8Strict defaultDynamo coverage errors on real models2.8.0 notes
Mobile runtimeExecuTorch, 1.0 on 17 October 2025Lite Interpreter"Lite Interpreter is deprecated. Please consider switching to ExecuTorch."torch/jit/_script.py
Interchange exporterDynamo based, default from 2.9TorchScript basedKept only as automatic fallback for scripted modulesissue #151693
Own model serverLeave it to the ecosystemTorchServeArchived 7 August 2025 with no security patches promisedpytorch/serve
Accelerator compilerInductor plus Triton, in coreGlow, Tensor ComprehensionsArchived 1 July 2025 and 28 April 2023pytorch/glow
Checkpoint safetyAllowlisted unpickler by default from 2.6Trusting pickle, or requiring a new format"closing the loop on the deprecation that started in 2.4"2.6.0 notes
Governance boundaryNeutral project, company libraries in a separate organisationVendor-controlled direction"Technical governance is strictly separated from business governance."governance.md

The governance row deserves a sentence of its own, because it explains an artefact that looks like a rebrand and is not. The in-repo governance document states that "Technical governance is strictly separated from business governance", and answers the obvious follow-up bluntly: a company cannot buy a board seat to drive direction, only sponsor through the PyTorch Foundation. As of September 2026 the practical consequence is visible in the organisation names. The neutral project lives under pytorch; Meta's own adjacent libraries, including torchrec, monarch, torchcomms and the graph-break site, live under meta-pytorch, and torchtune's issue tracker now resolves there. Neither organisation page says when the split happened, and I found no primary artefact that dates it, so treat the boundary as observed and the timing as open.

One rejected design is worth reading in full if you ever propose an abstraction to a platform team. RFC-0009, the DataLoader architecture proposal, opened on 29 January 2021 and closed unmerged on 7 July 2022. Its problem statement is exactly right: "Users want to point PyTorch to a remote data source... and iterate over contents without downloading the entire dataset." A reviewer suggested the ecosystem already had the pieces, naming fsspec, s3fs and gcsfs. The design was never accepted, the code shipped anyway in a satellite repository as DataPipes and DataLoader2, and it was removed two and a half years later while the plain DataLoader it intended to replace is still the default. The RFC process recorded the disagreement, the satellite let the code ship without resolving it, and the registry recorded the ending.

Figure 5 · Two endings that look identical from outside

shipped in its own repo

capability lands in core

repo archived, 1.5 to 3 years later

API required callers to rewrite

registry goes quiet, then the banner

capability survives, import path changes

capability gone, no patches promised

Satellite

InTree

ArchivedOk

Dropped

ArchivedBad

functorch in-tree 2022-09-21
archived 2025-08-21

torchdata dropped DataPipes 2024-12-13
TorchServe archived 2025-08-07

shipped in its own repo

capability lands in core

repo archived, 1.5 to 3 years later

API required callers to rewrite

registry goes quiet, then the banner

capability survives, import path changes

capability gone, no patches promised

Satellite

InTree

ArchivedOk

Dropped

ArchivedBad

functorch in-tree 2022-09-21
archived 2025-08-21

torchdata dropped DataPipes 2024-12-13
TorchServe archived 2025-08-07

An archive banner is ambiguous: the same state is reached by absorption and by abandonment, and only the surviving tree distinguishes them. Dates from functorch, TorchElastic, torchdata and TorchServe.
Diagram source
04

What broke, and who found out

Three failure classes: capture that regresses, a format boundary that is not a boundary, and lifecycle promises that expire. Meta publishes no incident postmortems for this platform, so the incident-grade evidence here is its own security advisories and the issues filed by downstream maintainers.

Source

Sound capture regressed between two releases, on a published model

AssumptionA capture path that succeeded on a model in one release will succeed in the next, because the model did not change.
What happenedA Hugging Face maintainer reported on 15 May 2025 that a DPT hybrid export test passing under 2.6 failed under 2.7 and 2.7.1 RC with "Unexpected type in sourceless builder transformers.models.bit.configuration_bit.BitConfig", raised when the forward method reads a config object. It passed with strict=False.
Blast radiusOne model family in one library, visible in public. The general form is invisible: every strict export is coupled to Dynamo's coverage of the Python your model happens to use.
FixThree months later the default became non-strict, which converts this class of failure from a build error into an unvalidated assumption.
Design ruleIf a build step's success depends on how much of a general-purpose language your tool understands, that step is not a gate, it is a coverage test. Pin the version, and run it on your own models in CI before you depend on it.
Source

The replacement cannot express what the deprecated path expressed

AssumptionA deprecation names a replacement, so migration is mechanical.
What happenedMONAI's maintainer opened a migration issue on 14 November 2025 stating "Torchscript is now fully deprecated in Pytorch 2.9" and then the real problem: the replacement behaves more like tracing, cannot capture control flow the same way, and at the time of writing only networks without control flow in forward can be exported.
Blast radiusA medical-imaging framework with TorchScript in its published model zoo; still open on 24 September 2026, eleven months after opening and roughly two years after the deprecation marker landed in 2.5.
FixNone available to the downstream project: the work is rewriting models, writing helper routines, and re-testing, which is precisely the cost the deprecated path was introduced to avoid.
Design ruleWhen you deprecate a capability, check whether the replacement covers the expressive range, not the API surface. If it does not, your deprecation window is a rewrite programme for everyone downstream, and it should be priced and announced as one.
Postmortem

The safe-by-default loader was bypassable within three months

AssumptionAn allowlisted unpickler is a trust boundary: with weights_only=True, loading a hostile checkpoint is safe.
What happenedThe default flipped in 2.6 on 29 January 2025, "closing the loop on the deprecation that started in 2.4". A Critical advisory titled "torch.load with weights_only=True RCE" was published on 17 April 2025. On 26 January 2026 a second advisory described a crafted checkpoint that, loaded with weights_only=True, "can corrupt memory and potentially lead to arbitrary code execution", affecting every release up to 2.9.1.
Blast radiusEvery consumer of third-party checkpoints, twice, roughly nine months apart. Two of the five advisories the project has published concern this one boundary.
FixPatched unpickler releases, and guidance in the release notes to prefer a format that cannot execute code at all.
Design ruleA parser hardened inside a format that was designed to execute code is a mitigation, not a boundary. If you accept artefacts from outside your trust domain, require a format with no execution semantics, and treat the hardened loader as defence in depth.
Source

The server was archived eleven months after it stopped being built

AssumptionA first-party component of a large platform will be maintained for as long as the platform is.
What happenedTorchServe's newest published container images are tagged 0.12.0 with a last-updated date of 30 September 2024. The repository was archived on 7 August 2025 carrying an explicit notice: "there are no planned updates, bug fixes, new features, or security patches. Users should be aware that vulnerabilities may not be addressed."
Blast radiusAnyone running it in production, with an eleven-month window in which the registry already said what the repository had not.
FixThe serving layer moved to third parties. vLLM, which most teams now reach for, advertises "Automatic kernel generation and graph-level transformations using torch.compile", meaning the ecosystem server is built on partial capture rather than on a serialised graph.
Design ruleThe build clock is a better maintenance signal than the repository. Watch the artefact registry, not the commit graph: images and wheels stop before banners appear, and a component with no security patch promise is an unpatched dependency the day it is archived.
Source

A library reached 150 contributors and was stopped by strategy

AssumptionAdoption and contributor count protect a library from being discontinued.
What happenedtorchtune shipped its first release on 21 March 2024 and its last, 0.6.1, on 7 April 2025. On 15 July 2025 the maintainers announced they were stopping active development, citing that "The AI landscape has rapidly evolved, with ever-increasing scale, an emphasis on agents, and a reinforcement learning renaissance", and that the work continues in a new repository.
Blast radiusEvery pipeline pinned to a torchtune recipe, with support limited to "critical bug fixes and security patches during 2025".
FixA successor library, which is the same bet again one level up.
Design ruleWhen a sponsor's strategy is the only thing holding a dependency up, the dependency has a fiscal lifetime, not a technical one. Depend on the layer that would be expensive for the sponsor to move, which here is the framework and the format, not the recipe library on top.
Source

The README said active development on the day the repository was frozen

AssumptionA project's own description tells you its status.
What happenedGlow, the accelerator compiler, was archived on 1 July 2025. Its README still opens with the claim "This library is in active development." Tensor Comprehensions, the earlier kernel-synthesis effort, was archived on 28 April 2023. Both capabilities are now served by Inductor and Triton inside the core tree.
Blast radiusReputational rather than operational for most readers, but it is the reason evaluating a dependency on prose is unsafe.
FixConsolidation into one compiler in core, which is the pattern the whole decade shows: capability survives, the separate project does not.
Design ruleGrade a dependency on three dated signals: last artefact in a package or image registry, last commit, and whether the capability exists in the surviving component. Prose is not a signal.

Figure 4 · The checkpoint path, and where the boundary is not

"Process memory""Allowlistedunpickler""torch.loadweights_only=True""Checkpoint .pth inZIP container""Untrusted publisher""Process memory""Allowlistedunpickler""torch.loadweights_only=True""Checkpoint .pth inZIP container""Untrusted publisher"GHSA-53q9 2025-04-17,GHSA-63cw 2026-01-26craft pickle opcodes and storagemetadataloadrestrict callables to tensor rebuildreplay opcodes, write storagesmemory corruption on malformedmetadata
"Process memory""Allowlistedunpickler""torch.loadweights_only=True""Checkpoint .pth inZIP container""Untrusted publisher""Process memory""Allowlistedunpickler""torch.loadweights_only=True""Checkpoint .pth inZIP container""Untrusted publisher"GHSA-53q9 2025-04-17,GHSA-63cw 2026-01-26craft pickle opcodes and storagemetadataloadrestrict callables to tensor rebuildreplay opcodes, write storagesmemory corruption on malformedmetadata
Two advisories, nine months apart, both sit at the same arrow: the allowlisted unpickler inside a container that was designed to execute code. Sources: GHSA-63cw-57p8-fm3p, 2.6.0 release notes.
Diagram source

Across those six entries the classes are distinct and the lesson is shared. Capture failures come from a tool's coverage of a language it does not own. Format failures come from treating a hardened parser as a trust boundary. Lifecycle failures come from depending on a layer whose existence is a strategy decision rather than a technical necessity. The transferable habit is to ask, for every dependency in a deployment path, which of those three risks you are carrying, and then to instrument the one you are carrying rather than all three.

05

Numbers you can plan against

Dates, counts and cadences, each with the artefact it came from. Every figure below was read from a file or a registry on 24 September 2026.

MetricValueAtContextAs ofSource
Catalogued graph-break reasons586PyTorch mainEntries in the Dynamo registry, keys GB0000 to GB99582026-09-24registry file
Graph-break site refresh3 minmeta-pytorchCron regeneration of the public break documentation2026-09-24site README
Minor release cadence~3 monthsPyTorch15 minor releases from 2.0.0 to 2.14.02026-09-02PyPI history
Deprecation window policy1 releasePyTorch OSS"stable features will be deprecated for one release before a BC-breaking change"2022RFC-0017
TorchScript deprecated in2.5PyTorchReleased 17 October 2024; marker still in the tree in 20262024-10-17torch/jit/__init__.py
Export strict default flipped2.8PyTorchTrue through 2.7 (2025-04-23), False from 2.8 (2025-08-06)2025-08-06v2.8.0 source
Downstream reaction lag3 to 13 monthsDJL, Lightning, MONAIIssues filed 2024-07-18, 2025-10-16 and 2025-11-14 against a marker landed 2024-10-172025-11-14Lightning #21293
DataPipes lifetime2 yr 9 motorchdata0.3.0 on 2022-03-10 to removal in 0.10.1 on 2024-12-132024-12-13PyPI history
torchdata silence since last release19 monthstorchdata0.11.0 published 2025-02-20, nothing since2026-09-24PyPI history
ExecuTorch to 1.02 yrExecuTorch0.1.0 on 2023-10-11, 1.0.0 on 2025-10-17, 1.5.1 on 2026-09-222026-09-22PyPI history
torchtune shipping life12.5 monthstorchtune0.0.1 on 2024-03-21 to 0.6.1 on 2025-04-07; wind-down announced 2025-07-152025-07-15issue #2883
TorchServe image gap before archive11 monthsTorchServeLast image 2024-09-30, archived 2025-08-072025-08-07Docker Hub
Checkpoint-loader advisories2 of 5PyTorchPublished advisories concerning torch.load, out of five in total2026-09-24advisory list
Time from safe default to first bypass78 daysPyTorchDefault flipped 2025-01-29, Critical advisory 2025-04-172025-04-172.6.0 notes
Caffe2 removal, elapsed4 yr 7 moPyTorchIssue opened 2022-02-08; caffe2/ still builds libtorch on main2026-09-24issue #72536
Satellite repo to archive, after absorption1.5 to 3 yrTorchElastic, functorchIn-tree 1.9 then archived 2023-01-06; in-tree 2022-09-21 then archived 2025-08-212025-08-21pytorch/functorch
Read these carefully

All of the above are measured from files or registry metadata, not claimed by anyone. Three are derived by arithmetic on two dated artefacts: the DataPipes lifetime, the 78 days to first bypass, and the Caffe2 elapsed figure. Four things are unknown and matter more than anything in the table: how many models inside Meta still depend on serialised TorchScript, what fraction of compiled models in production hit a graph break and how often, what the export path costs in engineer time per model family, and whether any of the archived components are still running somewhere. No public artefact answers those, and the corpus cannot be made to.

06

The evidence wall

Every artefact this page rests on, graded. Filter by kind. The full ledger, with one row per claim and the copied quote behind it, ships beside this file as sources.md.

Postmortem PyTorch2026-01

Loading a malicious checkpoint with weights_only=True can result in arbitrary code execution

High severity, CVSS 8.8, affecting every release up to 2.9.1. A crafted checkpoint defeats the allowlisted unpickler through pickle opcode and storage metadata handling.

Carry forwardA hardened parser inside an executable format is defence in depth, never a trust boundary.
github.com/pytorch/pytorch/security/advisories/GHSA-63cw-57p8-fm3p
Postmortem PyTorch2023-2026

The five published security advisories

GHSA-53q9-r3pm-6pq6 (Critical, 2025-04-17) and GHSA-63cw-57p8-fm3p (2026-01-26) both concern torch.load; the others cover a flatbuffer parser, a transitive libuv issue and an Actions expression injection.

Carry forwardWhere a project's advisories cluster tells you which boundary is load bearing.
github.com/pytorch/pytorch/security/advisories
Source PyTorch2025-08

torch/export/__init__.py at v2.7.0 and v2.8.0

The same parameter, two tags apart: strict: bool = True becomes strict: bool = False. The docstring states that the permissive default "will not validate some of the implicit assumptions baked into the graph".

Carry forwardRead defaults at tags, not docs: a default flip is the cheapest place a platform admits a trade-off.
raw.githubusercontent.com/pytorch/pytorch/refs/tags/v2.8.0/torch/export/__init__.py
Source PyTorch2026-09

torch/jit/__init__.py and torch/jit/_script.py

Four occurrences of ".. deprecated:: 2.5 / TorchScript is deprecated, please use torch.compile instead", plus "Lite Interpreter is deprecated. Please consider switching to ExecuTorch."

Carry forwardThe deprecation that matters is the one in the code, because it names the release and ships with the wheel.
raw.githubusercontent.com/pytorch/pytorch/main/torch/jit/_script.py
ADR PyTorch2021-2022

RFC-0017, PyTorch Operator Versioning

States the compatibility promises directly, including "we will not break a serialized torchscript program running in production at Meta" and a one-release OSS deprecation window.

Carry forwardAn internal compatibility promise written around a format is what keeps that format alive long after it is deprecated.
raw.githubusercontent.com/pytorch/rfcs/master/RFC-0017-PyTorch-Operator-Versioning.md
ADR PyTorch2023

RFC-0032, A PyTorch and NumPy compatibility layer

Designs a translation layer so Dynamo can trace NumPy calls, and accepts the fallback in writing: "it's okay to graph break and still call NumPy to execute the function call".

Carry forwardName the escape hatch in the design document; an unnamed fallback becomes an unmeasured one.
raw.githubusercontent.com/pytorch/rfcs/master/RFC-0032-numpy-support-in-dynamo.md
Source PyTorch2021-2022

RFC-0009 pull request, closed without merging after 18 months

The DataLoader redesign proposal. A reviewer pointed at fsspec, s3fs and gcsfs as the existing answer. Never merged; the code shipped in a satellite repository regardless and was removed in December 2024.

Carry forwardAn unmerged design plus shipped code is a governance smell worth checking for in your own platform.
github.com/pytorch/rfcs/pull/15
Source PyTorch2023-06

Issue #103841, asking for the status of TorchScript, FX and Dynamo

A request for a written short, medium and long-term statement on the capture stack. Closed as not planned, sixteen months before the deprecation marker appeared in the code.

Carry forwardIf a platform declines to write down its roadmap for a layer you depend on, read the defaults and the registries instead.
github.com/pytorch/pytorch/issues/103841
Source Hugging Face contributor2025-05

Issue #153599, strict export fails in 2.7 on a model that worked in 2.6

"Unexpected type in sourceless builder transformers.models.bit.configuration_bit.BitConfig", raised on a config access in forward. Passes with strict=False.

Carry forwardPin the capture tool's version and run export over your own model zoo in CI; coverage is not a stable contract.
github.com/pytorch/pytorch/issues/153599
Source Project MONAI2025-11

Issue #8632, TorchScript deprecation

States that TorchScript is fully deprecated in 2.9, and that the replacement cannot capture control flow the same way: only networks without control flow in forward can currently be exported.

Carry forwardCheck expressive range before accepting a migration path, and price the rewrite.
github.com/Project-MONAI/MONAI/issues/8632
Source Lightning AI2025-10

Issue #21293, update from TorchScript to torch.export

A training framework working out what to do with LightningModule.to_torchscript: reimplement, deprecate, or remove and push the work onto users.

Carry forwardEvery wrapper API you expose over a platform primitive is a migration you will own when the primitive is deprecated.
github.com/Lightning-AI/pytorch-lightning/issues/21293
Source Deep Java Library2024-07

Issue #3348, TorchScript is in maintenance mode

A JVM serving stack whose entire PyTorch integration is TorchScript asking what replaces it, three months before the deprecation marker landed in the code.

Carry forwardA non-Python consumer has no fallback interpreter, so a capture deprecation is existential rather than annoying.
github.com/deepjavalibrary/djl/issues/3348
Source PyTorch2025-08

pytorch/serve, archived with a no-patches notice

"This project is no longer actively maintained... there are no planned updates, bug fixes, new features, or security patches."

Carry forwardAn archive notice that disclaims security patches converts the dependency into a known unpatched component.
github.com/pytorch/serve
Source PyTorch2025-07

torchtune issue #2883, the future of torchtune

Active development stopped effective immediately on 15 July 2025, after 150 contributors and 21 recipes, with support limited to critical fixes during 2025.

Carry forwardContributor count does not protect a library whose existence is a strategy line item.
github.com/meta-pytorch/torchtune/issues/2883
Source Meta2023-2026

Nine dated archive banners

TorchElastic 2023-01-06, Tensor Comprehensions 2023-04-28, Glow 2025-07-01, TorchServe 2025-08-07, functorch 2025-08-21, fairseq 2026-03-20, plus torchtune's wind-down, torchdata's silence and FairScale's upstreaming note.

Carry forwardArchiving means two opposite things, absorbed or abandoned, and only the surviving tree tells you which.
github.com/facebookresearch/fairseq
Source PyTorch2026-09

caffe2/CMakeLists.txt on main

2,258 lines, containing add_subdirectory(../aten aten). The directory named for the framework a 2022 issue proposed to remove is where libtorch is built.

Carry forwardA merge that lands foreign code at the root of your build turns removal into a build-graph project, which never gets scheduled.
raw.githubusercontent.com/pytorch/pytorch/main/caffe2/CMakeLists.txt
Source vLLM2026-09

vLLM README

"Automatic kernel generation and graph-level transformations using torch.compile." The serving layer that replaced the first-party server is built on partial capture, not on a serialised graph.

Carry forwardWhere the ecosystem's servers sit tells you which capture path will still be maintained in five years.
raw.githubusercontent.com/vllm-project/vllm/main/README.md
ADR PyTorch2026-09

Governance mechanics, in-repo

"Technical governance is strictly separated from business governance", and a company cannot purchase a board seat to drive direction, only sponsor through the PyTorch Foundation.

Carry forwardRead a platform's governance file before betting on it; who can and cannot buy direction is a risk parameter.
raw.githubusercontent.com/pytorch/pytorch/main/docs/source/community/governance.md
Case study PyPI2018-2026

torch, torchdata, executorch and torchtune release histories

Every date in this guide is checked against upload timestamps: quarterly minors since 2.0, torchdata silent since February 2025, ExecuTorch at 1.5.1, torchtune's last wheel in April 2025.

Carry forwardA package index is the cheapest reliable maintenance signal you can automate a check against.
pypi.org/project/torch
Case study Docker Hub2024-09

pytorch/torchserve image tags

Newest tags are 0.12.0, last updated 30 September 2024, eleven months before the repository was archived.

Carry forwardImage registries go quiet before repositories do; watch the build clock.
hub.docker.com/r/pytorch/torchserve/tags
Case study Maven Central2026-09

The org.pytorch artefact group

pytorch_android and pytorch_android_lite sit beside executorch-android, executorch-android-qnn and executorch-android-vulkan: the mobile handover, visible as artefact names.

Carry forwardRegistry naming is an architecture document nobody edits for marketing reasons.
repo1.maven.org/maven2/org/pytorch
Case study npm, NuGet2018-2026

Two further ecosystems on their own clocks

An executorch npm package at 0.0.7, and TorchSharp on NuGet with 64 versions from November 2018 to 0.107.0 in May 2026: bindings track libtorch, slowly.

Carry forwardNon-Python bindings lag by quarters, so a capture deprecation reaches them last and hurts them most.
api.nuget.org/v3/registration5-semver1/torchsharp/index.json
Vendor PyTorch2025-2026

Release notes for 2.6.0 and 2.8.0, and the export user guide

The primary statements of intent: the weights_only flip, the strict default switch, the ONNX default switch, and the documented difference between partial and full capture.

Carry forwardRelease notes are the only place a platform states a trade-off in its own words; read the deprecation section first.
github.com/pytorch/pytorch/releases/tag/v2.8.0
What is missing, and why

There are no engineering blogs, papers or talks above. That is not an editorial choice: the hosts that carry them refused at this session's egress proxy, including pytorch.org, engineering.fb.com, arxiv.org, dl.acm.org and usenix.org. The corpus is therefore strong on dated fact and weak on stated motive. Where motive appears in this guide it is quoted from a docstring, a release note, an RFC or an issue, and where it is my reading, the sentence says so.

07

Build a miniature, then productionise it

Six rungs. The first three fit an evening; the last three are what the decade above says you will actually need.

Count your own graph breaks

Take a model you own with a data-dependent branch in forward. Compile it and collect the break reports, then look each one up against the published break registry.

Done when: you can name every break by its catalogue entry and say which are in your code and which are in a library.  Teaches: partial capture is a measurable property of your model, not a property of the tool.

Export the same model twice

Export with strict=True and with the 2.8 default. Record what fails, what silently succeeds, and what the two graphs differ on.

Done when: you can state, for your model, which implicit assumptions the permissive path did not validate.  Teaches: the difference between a build error now and an input-dependent failure later.

Rewrite one branch for full capture

Convert the data-dependent branch to a structured control-flow operator and re-export strict. Time how long it took.

Done when: strict export passes and the numerics match eager on two input shapes.  Teaches: what MONAI's issue means in hours per model, which is the real unit of a deprecation.

Cross into a runtime with no interpreter

Take the exported program to an ahead-of-time artefact and load it from a process that never imports Python, then again for an on-device runtime.

Done when: the artefact runs with the framework uninstalled.  Teaches: why full capture exists, and why every layer that demanded it was politically hard to retire.

Attack your own checkpoint path

Load a checkpoint from an untrusted source with the safe default on, then read the two loader advisories and decide whether your pipeline should accept that format at all.

Done when: your loader either rejects the executable format or documents why the risk is accepted.  Teaches: a hardened parser is a mitigation with a patch cadence, not a boundary.

Build the dependency lifecycle check

For each platform dependency in your deployment path, automate three signals: newest artefact in its registry, newest commit, and whether the capability exists in the component that would survive its retirement. Alert on the first two going quiet.

Done when: the check runs weekly and has flagged at least one dependency you did not know had gone quiet.  Teaches: the eleven-month gap between TorchServe's last image and its archive banner, applied to your own stack.

08

Keep hunting

The queries and fetch patterns that produced this page. Most of it came from reading files at tags, not from searching.

Read the tree, at a tag

  • raw.githubusercontent.com/<org>/<repo>/refs/tags/<tag>/<path>
  • grep -n "deprecated" torch/<module>/__init__.py
  • for t in v2.4.0 v2.6.0 v2.8.0; do curl -s .../$t/<file> | grep "default"; done

Lifecycle signals

  • site:github.com "was archived by the owner on" <org>
  • "no longer actively maintained" OR "no planned updates" <project>
  • "has been upstreamed to" OR "is in the PyTorch source tree"

Date it with registries

  • pypi.org/pypi/<package>/json
  • hub.docker.com/v2/repositories/<org>/<image>/tags?page_size=5
  • repo1.maven.org/maven2/<group path>/

Find the argument, not the answer

  • repo:<org>/rfcs is:pr is:closed is:unmerged sort:comments-desc
  • repo:<org>/<repo> is:issue "status" OR "roadmap" closed as not planned
  • "<deprecated feature>" deprecation -site:<vendor>.org in:title
The tree is honest in a way the announcements are not. A default value at a tag, an archive date, and the timestamp on the last published artefact are three facts nobody wrote for an audience.

The transferable lesson of the decade, stated once: do not build a layer that requires total capture of a program you do not control. Make the capture boundary explicit, enumerate what falls outside it, and measure how often that happens in your own workload. Meta got there by elimination, retiring or demoting every component that demanded the whole program, and the two things still standing in 2026 are the tolerant path that names its 586 escapes and the strict path that is now opt-in. If your platform has a layer that keeps being rewritten, the constraint is not in that layer. It is upstream, in the programming model, and the rewrite you are planning will fail for the same reason the last two did.

09

References

  1. PyTorch, torch/jit/__init__.py Source tree, main. Checked 2026-09-24.
  2. PyTorch, torch/jit/_script.py Source tree, main. Checked 2026-09-24.
  3. PyTorch, torch/export/__init__.py Source tree, main. Checked 2026-09-24.
  4. PyTorch, torch/export/__init__.py at v2.7.0 Release tag, 2025-04-23. Checked 2026-09-24.
  5. PyTorch, torch/export/__init__.py at v2.8.0 Release tag, 2025-08-06. Checked 2026-09-24.
  6. PyTorch 2.8.0 release notes GitHub Releases, 2025-08-06. Checked 2026-09-24.
  7. PyTorch 2.6.0 release notes GitHub Releases, 2025-01-29. Checked 2026-09-24.
  8. PyTorch, torch.export user guide Source tree, main. Checked 2026-09-24.
  9. PyTorch, Dynamo graph-break registry Source tree, main. Checked 2026-09-24.
  10. meta-pytorch, compile-graph-break-site Repository README. Checked 2026-09-24.
  11. PyTorch, RFC-0017 Operator Versioning pytorch/rfcs. Checked 2026-09-24.
  12. PyTorch, RFC-0032 NumPy compatibility layer pytorch/rfcs. Checked 2026-09-24.
  13. PyTorch, RFC process README pytorch/rfcs. Checked 2026-09-24.
  14. PyTorch, RFC-0009 DataLoader architecture updates (closed unmerged) Pull request, 2021-01-29 to 2022-07-07. Checked 2026-09-24.
  15. PyTorch, issue #103841 on the status of TorchScript and Dynamo Issue, 2023-06-19, closed as not planned. Checked 2026-09-24.
  16. PyTorch, issue #72536 Remove Caffe2 Issue, 2022-02-08. Checked 2026-09-24.
  17. PyTorch, caffe2/CMakeLists.txt Source tree, main. Checked 2026-09-24.
  18. PyTorch, caffe2/serialize/inline_container.h at v2.14.0 Release tag, 2026-09-02. Checked 2026-09-24.
  19. PyTorch, GHSA-63cw-57p8-fm3p Security advisory, 2026-01-26. Checked 2026-09-24.
  20. PyTorch, published security advisories Advisory list. Checked 2026-09-24.
  21. PyTorch, issue #153599 strict export regression Issue, 2025-05-15. Checked 2026-09-24.
  22. PyTorch, issue #151693 flip the ONNX dynamo default Issue, 2025-04-18. Checked 2026-09-24.
  23. Project MONAI, issue #8632 TorchScript deprecation Issue, 2025-11-14. Checked 2026-09-24.
  24. Lightning AI, issue #21293 Issue, 2025-10-16. Checked 2026-09-24.
  25. Deep Java Library, issue #3348 Issue, 2024-07-18. Checked 2026-09-24.
  26. PyTorch, TorchServe repository Archived 2025-08-07. Checked 2026-09-24.
  27. Docker Hub, pytorch/torchserve tags Registry, newest 2024-09-30. Checked 2026-09-24.
  28. torchtune, issue #2883 the future of torchtune Issue, 2025-07-15. Checked 2026-09-24.
  29. PyTorch, functorch repository Archived 2025-08-21. Checked 2026-09-24.
  30. PyTorch, TorchElastic repository Archived 2023-01-06. Checked 2026-09-24.
  31. PyTorch, Glow repository Archived 2025-07-01. Checked 2026-09-24.
  32. Meta, Tensor Comprehensions Archived 2023-04-28. Checked 2026-09-24.
  33. Meta, fairseq Archived 2026-03-20. Checked 2026-09-24.
  34. Meta, FairScale Repository README. Checked 2026-09-24.
  35. PyTorch, TorchData releases Release notes, 2024-10-21 and 2024-12-13. Checked 2026-09-24.
  36. PyPI, torch release history Registry. Checked 2026-09-24.
  37. PyPI, torchdata release history Registry. Checked 2026-09-24.
  38. PyPI, executorch release history Registry. Checked 2026-09-24.
  39. PyPI, torchtune release history Registry. Checked 2026-09-24.
  40. PyPI, the last torchtune wheel Artefact, uploaded 2025-04-07. Checked 2026-09-24.
  41. Maven Central, org.pytorch group Registry. Checked 2026-09-24.
  42. npm, executorch package Registry. Checked 2026-09-24.
  43. NuGet, TorchSharp registration index Registry, 2018-11-13 to 2026-05-07. Checked 2026-09-24.
  44. PyTorch, governance mechanics Source tree, main. Checked 2026-09-24.
  45. PyTorch, RELEASE.md Source tree, main. Checked 2026-09-24.
  46. vLLM, README Source tree, main. Checked 2026-09-24.
  47. meta-pytorch organisation Organisation page. Checked 2026-09-24.