October 2025, Revisited: Python 3.14, Free-Threading for Real, and What to Do About the GIL
Eric Greene June 11, 2026This post is part of our Three-Year Retrospective series: thirty-six posts, one per month, looking back at what actually mattered in software engineering. This one covers October 2025.
On October 7, 2025, Python 3.14 was released — and yes, the version number is pi, and yes, the release notes leaned into it. The headline was historic: under PEP 779, the free-threaded build of CPython graduated from "experimental" to officially supported. After more than three decades, running Python threads in genuine parallel, without the Global Interpreter Lock, was no longer a science project. It was a build you could choose, with the core team's commitment behind it.
What "officially supported" actually meant
Precision mattered here, and we spent a lot of classroom time on it that autumn. PEP 779 moved free-threading to phase two of the three-phase plan from PEP 703: full official support, but still optional. The default python.org installer was still the GIL build. Free-threaded Python was a separate binary (the t builds), and making it the one-and-only default remained a future, phase-three decision.
The engineering progress under the hood was substantial. In 3.13, the free-threaded build had paid a painful single-threaded penalty; in 3.14, with the specializing adaptive interpreter re-enabled and a long list of optimizations, that penalty dropped to roughly 5–10%. Meanwhile the ecosystem signal turned positive: wheels with free-threaded support were appearing across the scientific stack, and the question for library maintainers shifted from "whether" to "when."
Template strings, deferred annotations, and a friendlier REPL
PEP 750's t-strings were the release's quietest important feature. A t-string looks like an f-string but evaluates to a Template object instead of a str — the static text and the interpolated values arrive separately, so a library can process them before they become a string. The killer applications are the ones where naive f-strings are a bug factory: SQL composition, HTML templating with auto-escaping, structured logging. We told teams to watch for library support rather than reach for raw t-strings, and that's how it played out — the value landed through frameworks adopting them.
from string.templatelib import Template
user = "ada"
query = t"SELECT * FROM users WHERE name = {user}"
assert isinstance(query, Template) # a Template, not a str
print(query.strings) # ('SELECT * FROM users WHERE name = ', '')
print(query.interpolations[0].value) # 'ada' — escapable before joiningThe release also made deferred evaluation of annotations the default (PEP 649/749, ending the from __future__ import annotations era), added syntax highlighting to the REPL, brought zstandard compression into the standard library, and shipped a second, experimental headline: a tail-call-based interpreter offering measurable speedups on supported compilers.
So what should teams have done about the GIL?
The advice we settled on in October 2025, and still stand by: almost nothing, immediately — but with homework. For most Python workloads (web services that are I/O-bound, data pipelines that delegate to C libraries), the GIL was never the bottleneck, and free-threading changes little. The teams with a real stake were the ones with CPU-bound, parallelizable work who had been paying the multiprocessing tax — serialization overhead, duplicated memory, awkward shared state. For them, the homework was: get your dependency list audited for free-threaded wheels, run your test suite on a t build in CI as a non-blocking job, and audit for thread-safety assumptions that the GIL had been silently enforcing. That last item was the sleeper. Plenty of "thread-safe" Python code was merely GIL-safe, and finding out early was much cheaper than finding out in production.
Looking back from June 2026
The measured take aged well. Python 3.14 has been a smooth release in production — the 3.14.x minors arrived on cadence, and adoption tracked the usual curve. Free-threading is still optional, exactly as PEP 779 promised, but the ecosystem moved faster than skeptics expected: by mid-2026, free-threaded wheels are the norm for actively maintained packages with C extensions, and we now regularly see teams running free-threaded Python for specific CPU-bound services while keeping the default build everywhere else. That mixed-estate pattern — choose the build per workload — looks like the bridge the community will walk across for the next couple of years. And t-strings are quietly showing up inside logging and templating libraries, just as designed.
If your team is planning its own GIL homework, Intermediate Python covers the 3.14-era language — t-strings, annotations, and concurrency models included — and High-Performance Python with Cython is where we work through what free-threading does and doesn't change when you need real speed.