Python 3.14.5 rolls back the incremental garbage collector
Python 3.14.5 landed on 10 May 2026, pulled the incremental garbage collector that shipped in 3.14.0 through 3.14.4, and put the 3.13 generational collector back. Patch releases almost never reverse a major implementation change. The What’s New page names the cause: “due to a number of reports of significant memory pressure in production environments, it has been reverted back to the generational GC from 3.13.”
Recap what the incremental collector promised
CPython collects cyclic garbage with a tracing collector that runs alongside refcounting. Up through 3.13, that collector was generational with three generations. Objects that survived a collection moved up a generation, and the collector visited older generations less often. A full collection of the oldest generation traced every object the program kept alive, which on long-running processes produced multi-hundred-millisecond pauses.
Mark Shannon’s incremental collector, merged for 3.14, attacked those pauses by walking the old generation in pieces. Two generations replaced three. The release notes promised pause time reductions of “an order of magnitude or more for larger heaps.” The design skipped the PEP process, and CPython had already rolled it back once just before 3.13 final before reintroducing it for 3.14.0.
Trace the production memory pressure
The pauses got shorter, but the total garbage in memory did not. In a discussion thread on improving the incremental collector, Tim Peters traced a small program that allocated cyclic structures in a loop. Under the 3.14 collector, no full collection ran until iteration 20,000, by which point about 18,000 trash cycles were sitting in memory waiting to be reclaimed. The steady state held “over 90K trash cycles awaiting collection, but not more than 100K.” On the same workload, PyPy’s collector reclaimed over 100,000 cycles between iterations.
The mechanism: the new collector triggered its incremental work based on a calculation that, in Peters’s words, could “go negative(!) at times.” A web server or long-running pipeline that allocated cyclic objects steadily would keep adding to the heap without ever clearing the backlog, and resident memory would climb.
Neil Schemenauer proposed a fix: trigger a collection every 2,000 net new objects (the same heuristic the generational collector used) and size increments to force a full pass often enough. His patch kept maximum RSS and the trash-cycle count low while preserving the short pauses. The core team and the Steering Council decided that pulling the new collector entirely was the safer move for both 3.14 and 3.15. The 3.14.5 release date was pulled forward from 9 June to 10 May to ship the revert sooner.
Decide whether to upgrade to 3.14.5
Upgrade unless your workload was already validated against the incremental collector and depended on its shorter pauses. That set is small: most programs do not allocate enough cyclic garbage for the pause-time difference to be measurable, but most programs notice when resident memory climbs.
The change is mostly transparent to Python code. gc.collect() still works. gc.collect(1) no longer does an “increment of garbage collection” because there are no increments to perform anymore; the behavior reverts to the 3.13 meaning of collecting generation 1. Anything that introspects generation count via gc.get_count() or gc.get_objects(generation=N) again sees three generations instead of two. Code that tuned the incremental thresholds via gc.set_threshold() should review its arguments; the third threshold is meaningful again.
Watch 3.16 for a second attempt
The incremental collector is not dead. The 3.14.5 announcement and the revert thread both say that a reintroduction for Python 3.16 is on the table, this time through the PEP process. That gives the change a structured review and a public design discussion. Neil Schemenauer’s fix or a successor approach would be reviewed against the workloads that broke the first time.
Learn more
- What’s New in Python 3.14: Garbage collection is the canonical statement on the revert
- Reverting the incremental GC in Python 3.14 and 3.15 is the core team discussion that led to the decision
- Improving incremental gc contains Tim Peters’s analysis and Neil Schemenauer’s proposed fix
- Python 3.14.5 is out! is the release announcement