TL;DR: Python 3.14’s free-threaded build is a separate interpreter,
python3.14t, installed as an optional component. To see whether a running interpreter has the GIL off, callsys._is_gil_enabled()after your imports.
Python 3.14 came out in October 2025, and What’s New in Python 3.14 says its free-threaded build is “now supported and no longer experimental,” though still optional. The regular build remains the default, and whether that will change is still undecided. On the free-threaded build, several threads can run Python bytecode at the same time within one interpreter, while the regular build has the global interpreter lock, the GIL, which lets only one thread execute bytecode at a time.
The free-threaded build is its own interpreter, CPython compiled with the --disable-gil configure option, and it installs next to the regular one. On Windows, the Python install manager adds it with py install 3.14t, and the macOS installer from python.org has it as a separate option under Customize, not installed by default. With uv, uv venv --python 3.14t creates an environment on it. The free-threaded executable always has a python3.14t alias, but whether python or python3.14 also points at it depends on the install method.
Importing a C extension
Running python3.14t -VV prints a version string with “free-threading build” right after the version number. In 3.13 the same string said “experimental free-threading build”. The string says what was compiled, but not whether the running interpreter has the GIL off. That has its own check, sys._is_gil_enabled(), which should return False on the free-threaded build before any packages are imported. After startup, importing a C extension can change that answer to True. When that happens CPython prints a RuntimeWarning that names the module:
The global interpreter lock (GIL) has been enabled to load module '<name>', which has not declared that it can run safely without the GIL. To override this behavior and keep the GIL disabled (at your own risk), run with PYTHON_GIL=0 or -Xgil=0.
“Has been enabled” reports something already done. Until this import the interpreter had been running without the GIL, through every pure-Python module it loaded and every extension that declared it could run without one. In CPython’s import code, a C extension import goes through the same steps each time while the GIL is off: CPython turns the GIL on for the load, stopping the other threads while it does, runs the extension’s init function, and then checks what the module declared. If the module declared that it doesn’t need the GIL, CPython turns the GIL back off. If it didn’t, the GIL stays on, and this time CPython marks it as permanent. From then on, calls to turn the GIL on or off do nothing until the interpreter shuts down. CPython prints the warning only when it makes the GIL permanent, so the module it names is the first undeclared extension the interpreter imported. Later undeclared extensions load without a warning of their own.
The declaration the warning mentions is a slot, Py_mod_gil, in the extension’s module definition. An extension that supports running without the GIL adds one line, {Py_mod_gil, Py_MOD_GIL_NOT_USED} (single-phase modules declare it with PyUnstable_Module_SetGIL() instead). When that line is missing, “the import machinery defaults to Py_MOD_GIL_USED.” Py_MOD_GIL_USED is the value for a module that “may access global state without synchronization.” Extension code that predates the slot doesn’t have the line, and neither does an extension that happens to be thread-safe but was never marked. Because CPython looks only at the declaration, it treats the two alike. The py-free-threading FAQ traces that default to “the long history of extensions assuming the GIL locks concurrent access to extension internals.”
PYTHON_GIL=0 and -Xgil=0, the two settings named in the warning, keep the GIL off and skip the check at import. If both are set, the command-line option takes precedence. PEP 703, the proposal the build comes from, gives the reason the override exists: extensions that aren’t thread-safe “can still be useful in multi-threaded applications” when they are used from a single thread or behind a lock.
C extensions need to be built specifically for the free-threaded build. Those builds carry a t suffix, so a wheel for this interpreter has the tag cp314t. The free-threaded build doesn’t currently support the stable ABI, which means a project that ships one abi3 wheel for several regular Python versions still needs a separate wheel for 3.14t. Building that wheel and adding the Py_mod_gil line are separate steps, though. A package can publish a cp314t wheel whose module never declares the slot, and that wheel installs on 3.14t normally but can still turn the GIL on when it is imported. The py-free-threading tracking page and Free-threaded wheels both track which popular packages support free threading, and the Free-threaded wheels site marks a package dark green when it offers wheels with an ABI tag ending in t.
Speed and memory
What’s New puts the penalty on single-threaded code at “roughly 5-10%, depending on the platform and C compiler used.” The free-threading HOWTO gives the average overhead on the pyperformance benchmark suite as ranging “from about 1% on macOS aarch64 to 8% on x86-64 Linux systems.”
The free-threaded build also typically uses more memory than the regular build. PEP 779, written in March 2025 before 3.14 was released, put the increase at “about 15-20%” as a geometric mean over pyperformance.
The HOWTO says that while not all software will benefit automatically, “programs designed with threading in mind will run faster on multi-core hardware.” Whether that outweighs the overhead comes down to your own program, timed on the regular build and on python3.14t, with sys._is_gil_enabled() checked at the end of the run so that the free-threaded numbers come from an interpreter that had the GIL off.

