Single binary for CLI and FPM proposal
Under discussion; not accepted. The RFC page (version 0.2, dated 2026-10-08, author Matthieu Napoli) and the official RFC index both list it as under discussion. The proposed version is PHP 8.7. The voting thread reads "tbd". The page's vote widget shows 0/0/0 and "This poll has been closed". That is the wiki template, and no vote has been opened.
Proposal (version 0.2, 8 October)
Version 0.2 reverses the direction of version 0.1. Instead of linking FPM into php, it links the
CLI SAPI into the php-fpm executable:
- there is no configure option. Whenever both the CLI and FPM are built,
php-fpmalso contains the CLI. With--disable-cli, or with FPM disabled (the default), nothing changes.make installstill installs two separate executables; - the
phpexecutable is unchanged, and there is no--fpmoption; php-fpmruns as the CLI when invoked under the namephp, optionally followed by a digit (for examplephp8.7or Alpine'sphp83) through a symlink, hard link or copy. Under any other name it is FPM, unchanged. Names such asphp-cgi,php-config,phpdbgandphpizeare excluded, and so isphp-8.7(from--program-suffix=-8.7), which therefore runs FPM;- in CLI mode
PHP_SAPIiscli, it readsphp-cli.iniand accepts the usual CLI options. A running process cannot switch SAPIs. The RFC says the CLI test suite passes through aphpsymlink tophp-fpm.
PHP_BINARY is the executable's real path (symlinks are resolved). A distribution that wants a
single executable should therefore install it as /usr/bin/php, with php-fpm as a symlink to it.
Then PHP_BINARY runs the CLI in both modes, while FPM is still started as php-fpm, so service
files, process titles and graceful reload (SIGUSR2, which re-executes through the symlink) keep
working. Tools that read /proc/<pid>/exe see php for FPM processes. The opposite layout
(php as a symlink to php-fpm) makes PHP_BINARY start FPM; the RFC says this will be
documented in UPGRADING.
Listed backward-incompatible changes, only for builds with both SAPIs: php-fpm invoked as
php/php8.7 now runs the CLI, php-fpm grows by about 150 KB in a minimal build, and FPM's C
function zif_apache_request_headers is renamed zif_fpm_request_headers (the PHP functions
apache_request_headers() and getallheaders() are unchanged). There is now a single primary
vote needing a 2/3 majority; the secondary default-on vote of version 0.1 is gone. The RFC lists no
open issues. It cites the PHP 8.6 change that made the CLI available to the embed SAPI
(PR #21385), which FrankenPHP uses, as the model.
The RFC also records two rejected alternatives: a php-fpm --cli option (it would touch FPM's
argument parsing, and some letters such as -F mean different things in the two SAPIs), and a
shared libphp.so (a much larger build and packaging change that adds dynamic linking at start).
Version 0.1 (6 October)
Version 0.1 proposed an --enable-cli-fpm configure option that linked FPM into php, selected
with a leading --fpm argument or a php-fpm* name. It had a secondary simple-majority vote on
whether to enable the option by default. Its implementation,
PR #23558. The RFC now lists that design under
rejected features.
Motivation and evidence
The author measured Bref (PHP on AWS Lambda) builds on PHP 8.5.11, Linux x86-64, by replacing
php-fpm with a symlink to a combined executable. The zipped layer went from 24.3 MB to 19.9 MB
and the unzipped layer from 89.9 MB to 64.5 MB. The median FPM cold start over 50 starts dropped
from 280 ms to 211 ms (difference −70 ms, 95% CI −79 to −59); a control runtime that never starts
FPM showed no difference. The RFC says ARM and other memory sizes were not measured, and that the
gain on hosts with the image on local disk is likely smaller. These are the author's own
benchmarks. The page does not say whether they were repeated with the version 0.2 build.
The new implementation is php-src PR #24192. On 2026-10-08 the GitHub API showed it as open, not a draft and not merged (created 11:39 UTC). PR #23558 was still open as well.
Discussion
The RFC was announced on 6 October. Replies that day were broadly positive and raised these points:
- Tim Düsterhus (132807) noted that code in FPM
using
PHP_BINARYwould get a binary that needs--fpmto start FPM, and asked whether the standalonephp-fpmshould be kept at all. The author (132808) preferred removing it in a separate RFC; Düsterhus (132812) argued for one step. - Ayesh (132811) pointed out
Debian/Ubuntu's separate SAPI packages and that
-Fmeans "execute a file" in the CLI but is an alias of--nodaemonizein FPM, and questioned switching meaning by name or flag. - Another participant raised packaging and service-manager concerns for Linux distributions.
- Larry Garfield (132816) asked whether linking
FPM into
phpprivileges FPM over other SAPIs (FrankenPHP, Swoole, CLI-based async servers). Nicolas Grekas (132819) argued that the FPM binary should embed the CLI instead, as FrankenPHP does. Jakub Zelenka (132821) agreed.
On 8 October the author agreed, opened PR #24192
and published version 0.2. Tim Düsterhus disagreed
with the new direction, arguing that selecting a SAPI by executable name is hard to discover and
surprising: a php-like name that does not match the rule (a custom p symlink, or php-8.7)
would start FPM and possibly bind sockets, with no way out except renaming. Düsterhus also rejected the
view that version 0.1 privileged FPM, and preferred an explicit flag on php (--fpm, or for
example --mode=fpm), by analogy with -S for the built-in server.
On 10 October Marc Henderkes agreed with Düsterhus
and gave three reasons:
php --fpm <fpm-args> is clearer than renaming the binary, php-fpm usually lives in /usr/sbin,
which users should not normally call directly, and php-fpm php-cli <cli-args> is awkward.
Henderkes did not share Garfield's concern about privileging FPM, and preferred a top-level
--fpm flag over --mode=fpm.
Later on 10 October (19:07 UTC) Levi Morrison suggested another
alternative, replying to the version 0.1 announcement:
building the Zend engine as a shared library, libzend.so. Morrison said this used to be possible
to build and assumed it was partly removed for performance. It would also let most extensions link
their symbols against libzend.so instead of leaving them undefined for the executable to provide. Morrison said the
performance cost would need measuring, but would personally prefer this solution if it is viable. The
RFC's rejected alternative is a shared libphp.so with small php and php-fpm executables. The
message does not say how libzend.so would relate to that option, and this page does not treat them as
the same proposal.
As of 22:00 UTC on 10 October the author had not replied to either message. The RFC page was still version 0.2, and PR #24192 was still open, not a draft and not merged (last updated 2026-10-08).
Limitations
This page summarises a version 0.2 proposal that changed fundamentally two days after version 0.1,
with two participants on the list now preferring an explicit --fpm flag on php and a third
suggesting a shared libzend.so instead. The direction, the name-matching rule and the handling of
PHP_BINARY can change before a vote, and nothing here is in released PHP.
Related: support windows.