At work, I maintain a PHP distribution on a non-mainstream platform shipping NTS. No real reason other than that's the way we've always built it; there's no urgency to switch since 99.9% of the users aren't using threaded SAPIs. I can try ZTS builds and see what (or really if it) breaks down for me.
FWIW as an RM, we run the basic tests for a release in both NTS and ZTS, so any low-hanging fruit with CLI/CGI should be caught at least. > On Jul 11, 2026, at 12:52 PM, Marc Henderkes <[email protected]> wrote: > > Hi internals, > > > > > > > > Before I sit down and write a full RFC, I'd like to get a feel for where > people stand on something I've been working toward for a while: deprecating > not passing --enable-zts, and removing the NTS mode entirely in the next > major version. > First a very important clarification: I’m not looking to deprecate the way > FPM or other process managers work. All the existing NTS functionality, > including hard timeouts (which do not yet have ZTS equivalent) can keep > working in a single threaded ZTS run. > > The reasons, listed by importance: > 1. the current split introduces a lot of unnecessary builds and poor > availability (especially for FrankenPHP and other emerging projects that > require thread safety): > OS distributions generally only package NTS > Remi used to ship cli-only ZTS php, but stopped because it meant twice the > maintenance. > Ondrej doesn’t want to take on ZTS builds because NTS is the default, again > citing twice the work > Shivam’s Homebrew does ship both NTS and ZTS, but only extensions for NTS. > PIE exists, but extension providers suffer from the same problems: most > either don’t do prebuilt binaries at all or only do NTS. > I ship ZTS packages only because there’s no other availability for them. In > order not to conflict with users’ regular system packages and their > dependencies, I build everything into a different name. > php-src’s GitHub CI would shrink significantly by getting rid of NTS > Most users don’t even know that a ZTS build with ext-parallel capabilities > exists, if they do, it mostly just confuses them on which to get > Tl;dr: nobody wants to maintain two builds and even having a necessary split > is making things hard. > 2. maintenance cost in php-src itself: ~420 #ifdef ZTS results and ~30 for > #ifndef ZTS from a quick search. > 3. NTS as the default disincentivises any first-class threading story > 4. there’s no significant advantage NTS has. It gets rid of a tiny bit of > mutex locking or per-thread copying, but most of the other cost doesn’t have > to exist. Worst case performance cost of ZTS in php 8.5 was ~5%, will be > ~1.5% in php 8.6, likely ~0.5% after my last open PRs. This doesn’t have to > stay the case - the last bits of performance penalty could be resolved if we > convince the compiler to stop rederiving TLS addresses after function calls. > > Generally, no large code changes are needed. Removing a lot of duplication in > php-src is good. > > Potential blockers > The JIT doesn’t work for ZTS builds on arm64 macOS. > Thread unsafe extensions like ext-imap will continue working in the > single-threaded execution of fpm. The only extension I’m aware of that > doesn’t support ZTS builds at all currently is new relics. > > ZTS jit on arm64 macOS is the only part I couldn’t do myself (don’t have > arm64 apple silicon at hand). Everything else I would implement myself. > > I think it would really benefit the health of php distributions and evolution > in the future. Given the small change surface for extension or build > providers, and users, I would like to land the removal in PHP 9.0. > Best regards, > Marc Henderkes
