Python 3.9.13 closes the regular maintenance phase
Python 3.9.13 is the branch's final regular bugfix release. Its concurrency repairs arrive as upstream changes both the fixes it accepts and the artifacts it distributes.
A maintained Python branch can continue receiving security fixes while ceasing to receive ordinary bug fixes and binary installers. Python 3.9.13 marks that transition for the 3.9 series. The May 17 announcement calls it the final regular maintenance release and says subsequent upstream releases will accept security fixes and provide source distributions only.
That changes the meaning of staying on the branch. An application can retain its language version, but its dependency on upstream changes. Ordinary correctness repairs no longer have the same route into another maintenance release. The distinction affects the people who package the interpreter as well as the people whose applications run on it.
I choose Python for the libraries available around it, so the interpreter's support phase is part of that choice. An application may have good reasons to retain an older version. Those reasons still need to account for who supplies its interpreter binaries and which classes of defect upstream will repair.
What the final bugfix release still changes
The announcement counts 166 commits since 3.9.12. That is useful evidence against treating a final bugfix release as an administrative marker with no implementation content. The version-specific changelog includes repairs to process pools and queue cleanup, alongside other interpreter and library defects.
One change removes on-demand worker spawning from concurrent.futures.ProcessPoolExecutor when the multiprocessing start method is fork. The changelog explains that forking while threads are running can deadlock child processes. An optimization introduced in the 3.9 series therefore needed a narrower application because of its interaction with process creation.
The condition matters. The release note does not say every start method loses on-demand spawning. It identifies fork as the case with the deadlock risk. Code that accepts a multiprocessing context needs to understand that the context can influence executor behavior even when the public task-submission interface looks the same.
A process pool abstraction cannot make all process-creation semantics disappear. The implementation still chooses when to create workers under the constraints of its start method. Here the maintenance release changes that internal timing to avoid a documented failure mode. An application can benefit without changing the function it submits to the pool.
Resource cleanup includes unsuccessful work
The changelog also identifies a fix for an exception memory leak in ProcessPoolExecutor. That is a separate issue from worker creation. The grouping is useful because both affect an executor's behavior over its lifetime, while one concerns how workers start and the other concerns what failed work retains.
Another entry concerns multiprocessing.Queue. The repair closes the read end of the pipe after the last buffered write to the write end, avoiding BrokenPipeError during garbage collection and explicit queue closure. That description places the problem at the boundary between buffered work and resource shutdown.
These cases show why a bugfix release can matter even when ordinary successful examples remain unchanged. A submitted operation returning a value does not exercise exception retention. A queue transferring a value does not establish that its final buffered writes and cleanup occur in the correct order. The release repairs behavior that becomes visible at different stages of the object's lifetime.
The same maintenance scope extends to test infrastructure. unittest.IsolatedAsyncioTestCase now shuts down its per-test event-loop executor before returning from its run method. The changelog says this prevents executor state from persisting beyond the test. A test boundary has an ownership contract too, and that contract includes background execution resources.
Security maintenance changes the distribution contract
The announcement ties the transition to PEP 596's release schedule. Its stated plan is source-only security releases through October 2025. That is the published support horizon at this point, not a promise of continuing regular bug fixes until then.
For users of upstream installers, the source-only condition is material. A future security correction and a ready-to-install upstream binary are different deliverables. An organization retaining the branch needs a distributor or build process that turns the applicable source into the interpreter it actually runs.
This does not establish the policy of any operating-system vendor or other distributor. Those suppliers can have their own maintenance commitments. The announcement defines the upstream project's deliverables. Confusing them with every downstream support arrangement would make the transition sound either broader or less consequential than the source supports.
I regard the concurrency fixes as a strong reason to distinguish a branch's last regular update from its previous patch. This release contains corrections to how resources behave under failure and shutdown. Remaining on the same feature series does not remove the value of those fixes.
The practical consequence of the transition is a narrower upstream repair policy after a substantial final update. A service depending on ordinary library behavior will retain the behavior supplied by 3.9.13 unless its distributor provides further changes. Security maintenance keeps a specific class of repair available, while decisions about other defects move into the application's version and distribution choices.