What is thread safe or non-thread safe in PHP?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Thread Safe (TS) and Non-Thread Safe (NTS) are two build variants of PHP that determine how the interpreter handles concurrent execution. Thread Safe PHP includes internal locking mechanisms that allow it to run safely inside multi-threaded web server processes like Apache with mod_php. Non-Thread Safe PHP omits that locking overhead and is designed for environments where each request runs in its own process, such as PHP-FPM with Nginx or Apache with mod_fcgid.
Choosing the wrong variant does not always produce an obvious error. It can cause subtle data corruption under load in one direction, or unnecessary performance overhead in the other. Knowing which variant your server architecture requires is a prerequisite for a reliable PHP deployment.
What Thread Safety Means in PHP
PHP's thread safety mechanism is called TSRM (Thread Safe Resource Manager), also historically referred to as ZTS (Zend Thread Safety). When PHP is compiled with ZTS enabled, every global variable and internal resource is stored in thread-local storage rather than in a single shared location. This prevents one thread from corrupting another thread's state when multiple threads execute PHP code simultaneously inside the same process.
The cost of TSRM is real. Every access to a global resource goes through an indirection layer that looks up the correct thread-local copy. In benchmarks, ZTS builds of PHP typically run 5-15% slower than NTS builds for the same workload, depending on the application.
You do not write different PHP code for TS vs NTS builds. The difference is entirely in how the interpreter manages internal state. Your application code is identical.
When to Use Each Variant
The choice depends entirely on how your web server invokes PHP.
Non-Thread Safe (NTS)
Use NTS when PHP runs as a separate process per request. This is the most common production setup today.
Architectures that use NTS:
- Nginx + PHP-FPM (each FPM worker is a separate process)
- Apache +
mod_fcgidormod_proxy_fcgi - CLI scripts (single process, no threading)
- Docker containers running PHP-FPM
Since each process handles only one request at a time, there is no shared state between concurrent requests, and thread safety is unnecessary. NTS builds are faster because they skip the TSRM overhead.
Thread Safe (TS)
Use TS when PHP runs inside a multi-threaded web server process where multiple requests are handled by threads sharing the same process memory.
Architectures that use TS:
- Apache +
mod_phpon Windows (worker MPM or winnt MPM) - IIS + PHP via ISAPI or the FastCGI handler in some configurations
- Any custom embedding of PHP in a multi-threaded application
On Linux, Apache's prefork MPM spawns separate processes (not threads), so even mod_php with prefork uses process isolation and NTS is safe. The TS requirement mainly applies to Apache's worker or event MPMs with mod_php, and to Windows IIS deployments.
How to Check Your Current PHP Build
The output includes either NTS or ZTS (which means Thread Safe):
You can also check programmatically:
Architecture Comparison
| Architecture | Process Model | PHP Variant | Why |
| Nginx + PHP-FPM | Multi-process (one request per worker) | NTS | No shared memory between workers |
| Apache prefork + mod_php | Multi-process | NTS | Prefork uses processes, not threads |
| Apache worker/event + mod_php | Multi-threaded | TS | Threads share process memory |
| Apache + mod_fcgid | Multi-process (external PHP) | NTS | PHP runs in separate processes |
| IIS + FastCGI (Windows) | Depends on config | TS (recommended) | IIS may use threads internally |
| CLI scripts | Single process | NTS | No concurrency |
PHP Extensions and Thread Safety
Thread safety is not just about the PHP core. Every loaded extension must also be thread-safe for the interpreter to work correctly in a threaded environment. An extension compiled without ZTS support loaded into a ZTS PHP build can cause segfaults or data corruption.
Most popular extensions (PDO, mbstring, json, openssl) support both variants. However, some older or niche extensions have only been tested with NTS. If you depend on such an extension, you are effectively locked into NTS and must use a process-based architecture.
Performance Implications
The performance difference between TS and NTS is measurable but not dramatic for most applications. The overhead comes from TSRM's thread-local storage lookups on every internal global access.
These numbers vary by workload. CPU-heavy applications with many internal state accesses see a larger gap. I/O-bound applications (database queries, API calls) see a smaller gap because the bottleneck is not PHP execution speed.
The practical recommendation: use NTS with PHP-FPM unless your deployment specifically requires a threaded architecture. PHP-FPM is the standard for modern deployments and is what most hosting providers, container images, and cloud platforms configure by default.
Installing the Correct Variant
Linux (Package Manager)
Most Linux package managers install NTS by default. If you use the official PHP packages or Ondrej's PPA, you get NTS.
Windows
On Windows, the PHP downloads page (windows.php.net) provides separate ZIP files for TS and NTS. Choose based on your web server:
- IIS or Apache worker MPM: Download the Thread Safe (TS) version.
- Apache with mod_fcgid or standalone CLI: Download the Non-Thread Safe (NTS) version.
Docker
Official PHP Docker images use naming conventions to indicate the variant:
Check with php -v inside the container to confirm.
Common Pitfalls
- Using the TS build with PHP-FPM. PHP-FPM uses process isolation, so thread safety adds overhead without any benefit. Always use NTS with FPM.
- Using the NTS build with Apache worker/event MPM and mod_php. This can cause random segfaults and data corruption under concurrent load because threads share memory without protection.
- Assuming TS makes your PHP application code thread-safe. TSRM protects PHP's internal state. It does not make your application logic safe for concurrent access to shared resources like files, databases, or caches. You still need proper locking or transactional logic at the application level.
- Mixing TS and NTS extensions. Loading an extension compiled for NTS into a ZTS PHP build (or vice versa) typically causes a startup error or a segfault. Always match the extension variant to the PHP variant.
- Not checking the variant after upgrading PHP. Some upgrade paths or package manager changes can switch the variant silently. Verify with
php -vafter every major upgrade. - Confusing PHP thread safety with application-level concurrency. PHP's request model is fundamentally share-nothing at the application level. Even with TS PHP, each request gets its own variable scope. TS only matters for the interpreter's internal bookkeeping when threads share a process.
Summary
- Thread Safe (TS/ZTS) PHP uses thread-local storage to protect internal state in multi-threaded server environments. Non-Thread Safe (NTS) PHP skips that overhead.
- Use NTS with PHP-FPM, Apache prefork, FastCGI, and CLI scripts. Use TS only with Apache worker/event MPM using mod_php or IIS in threaded mode.
- NTS is faster by roughly 10-15% because it avoids TSRM lookups. Use it unless your server architecture requires threads.
- Check your build variant with
php -vand look forNTSorZTSin the output. - Extensions must match the PHP variant. A TS extension will not load in an NTS build, and vice versa.
- PHP's thread safety is about the interpreter's internals, not your application code. Application-level concurrency (file locks, database transactions) is a separate concern.

