tech, developers, and the code underneath

issue 229· news·

Python 3.15 and the free-threading endgame

An October release, as always. The question is no longer whether the GIL can go — it is whether the ecosystem follows.

Python ships a major version every October and has since 3.9. This one continues the longest-running structural project in the language's history: making the global interpreter lock optional.

where the project actually stands#

The technical question was settled some time ago — CPython can run without the GIL, and it does. The remaining questions are all about adoption, and they break into three tiers.

The numerical core: done. The array and dataframe ecosystem ships free-threaded wheels. This was the critical path, because it is where Python's CPU-bound workload actually lives.

The mid-tier: in progress. Widely-used libraries with C extensions have mostly been audited, some have not, and the pattern is that maintainers do the work when someone reports a problem.

The long tail: untouched, and it always will be. Thousands of packages will never be explicitly checked. They will be found to work, or not, one bug report at a time.

the risk nobody can size#

The subtle problem is not C extensions — those fail loudly. It is pure Python code that was accidentally thread-safe.

The GIL made many operations effectively atomic. A dictionary mutated from two threads, a counter incremented without a lock, a lazily-initialised singleton — all of these worked by accident. Under free-threading they are races.

Nobody knows how much library code depends on this, because until recently nobody had to know. It will be discovered gradually, as intermittent failures in production that are hard to reproduce and easy to blame on something else.

That is the honest risk assessment, and it is why "the free-threaded build is supported" and "you should run it in production" remain different statements.

who should actually switch#

Yes, if: your workload is CPU-bound and multithreaded, you currently use multiprocessing and pay serialisation and memory-duplication costs, and your dependency tree is one you can audit.

The migration from multiprocessing to threads for that workload is frequently dramatic — not just faster, but simpler, because the serialisation layer disappears.

No, if: your workload is I/O-bound. asyncio was already handling that and free-threading buys you nothing. This describes most web applications.

Test it either way if you maintain a library with a C extension. That work has to happen somewhere and it happens when maintainers do it.

the underrated alternative#

Subinterpreters continue to mature, and they remain the option that gets less attention than it deserves.

Isolated interpreters in one process: much lower overhead than processes, much stronger isolation than threads. For workloads that want parallelism and do not want shared mutable state — which is most workloads — they give you the process model's safety at closer to the thread model's cost, with none of the thread-safety auditing free-threading requires.

For a lot of the cases where people reach for multiprocessing today, this is the better answer and fewer people know it exists.

the release-day routine#

Same as any language with an annual cadence:

  1. Read the "what's new" incompatibilities section, not the feature list.
  2. Check for removed deprecations. Python removes things on a published schedule and the removal is where upgrades break.
  3. Run your test suite on the new version in CI as a non-blocking job well before you switch. Six months of early warning costs a few minutes per build.
  4. Do not skip versions. Two at a time is manageable.

the long view#

Python's answer to being slow and single-threaded was, for two decades, "call C." The last few releases have been the language declining to accept that as the final answer.

Free-threading, subinterpreters, and the specialising interpreter are one coherent project, and it is being executed the slow way — opt-in, with a fallback, without breaking the ecosystem. That is the right call and it is why it is taking years.

The destination is not in doubt. Only the timeline.

— Dom, October 5, 2026

get README in your inbox

One dispatch, no noise. Tech and developer news, plus the occasional long piece on the craft.

subscribe →