Scaling Apache: Moving from Prefork to Event MPM with PHP-FPM
Stop letting idle keep-alive connections choke your Apache server. Learn how to switch from the legacy prefork MPM to the event MPM and integrate PHP-FPM for high-concurrency scalability.
29 Jul 2026, 04:59 UTC

The Keep-Alive Bottleneck
When a web server handles a request, it often keeps the connection open (Keep-Alive) to allow the browser to request images, CSS, and JS without renegotiating a TCP handshake. In the legacy prefork Multi-Processing Module (MPM), each connection—even an idle one—occupies an entire process. If you have 150 processes and 150 users are idling on a keep-alive connection, your server is effectively \"full,\" and the 151st user will experience a timeout or a long queue, despite the CPU and RAM being nearly idle.
The solution is to decouple the connection from the worker. By switching to the event MPM and offloading application logic to a separate process manager, you can handle thousands of concurrent connections with a fraction of the memory overhead.
How the Event MPM Solves Concurrency
The event MPM is an evolution of the worker MPM. While the worker MPM uses threads to handle requests, those threads still stay tied to a connection until it closes. The event MPM introduces a dedicated listener thread that manages the \"keep-alive\" state. When a connection becomes idle, the listener thread takes over, freeing the worker thread to handle a new, active request. The worker thread is only re-assigned to that connection when new data actually arrives.
The PHP Dilemma: Thread Safety
The primary reason many administrators stick with prefork is mod_php. Because mod_php is not thread-safe, it cannot run inside the event or worker MPMs without risking memory corruption or crashes. To gain the scalability of the event MPM, you must move PHP out of the Apache process entirely.
The modern engineering standard is to use PHP-FPM (FastCGI Process Manager). In this architecture, Apache acts as a reverse proxy, passing PHP requests over a socket to a separate PHP-FPM service. This allows Apache to handle the high-concurrency connection management while PHP-FPM manages the execution of the code in its own isolated process pool.
Implementation: Configuring Event MPM and PHP-FPM
This configuration assumes a Unix-like system running Apache 2.4. You must first ensure the event MPM is loaded instead of prefork. This is typically done via the package manager (e.g., a2dismod mpm_prefork && a2enmod mpm_event on Debian/Ubuntu).
Run the following on your server with root or sudo permissions to verify the current MPM:
apachectl -V | grep \"Server MPM\"
Once mpm_event is active, enable the proxy modules:
# Enable proxy and FastCGI modules
a2enmod proxy proxy_fcgi
Add the following to your VirtualHost configuration to route PHP requests to the FPM backend (typically listening on port 9000 or a Unix socket):
# Route all .php files to the PHP-FPM backend
ProxyPassMatch ^/(.*\\.php)$ fcgi://127.0.0.1:9000/var/www/html/$1
To tune the event MPM for your specific hardware, adjust these directives in your mpm_event.conf file:
# Max number of simultaneous requests that can be served
MaxRequestWorkers 400
# Number of threads created by each child process
ThreadsPerChild 25
# Factor to increase the number of keep-alive connections
# that can be handled beyond MaxRequestWorkers
AsyncRequestWorkerFactor 2
Trade-offs and Limitations
While the event MPM is superior for high-traffic sites, it introduces a layer of complexity. You are now managing two separate services (Apache and PHP-FPM) instead of one. If the PHP-FPM service crashes, Apache will return a 503 Service Unavailable error, even if the web server itself is healthy.
Additionally, because Apache is now proxying requests, you may need to configure ProxyPreserveHost On to ensure the PHP application receives the correct domain name in the HTTP headers.
Verifying the Result
To confirm the transition was successful, use apachectl -M to ensure proxy_fcgi_module is loaded. You can then test the concurrency limit using a tool like ab (Apache Benchmark). Compare a prefork setup against an event setup using a high number of concurrent connections (-c flag) and keep-alives enabled. You should observe that the event MPM maintains lower memory usage and higher throughput under heavy connection loads.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.