SAPIs

SAPIs: CLI, PHP-FPM and the Apache Module

A SAPI (Server API) connects the engine to whatever started it: a terminal, an HTTP request or a FastCGI message. Each SAPI reads its own php.ini. This script reports where it runs:

sapi.php: which SAPI runs this script, as whom, and with which php.ini?PHP
<?php
header('Content-Type: text/plain');
printf("%-14s %-28s %-8s pid=%d memory=%s time=%ss\n",
    PHP_SAPI, php_ini_loaded_file(), posix_getpwuid(posix_geteuid())['name'],
    getmypid(), ini_get('memory_limit'), ini_get('max_execution_time'));

Here it is run four ways: from the terminal, through the built-in server (php -S 127.0.0.1:8201), through Apache 129 passing .php files to PHP-FPM via proxy_fcgi, and through Apache with mod_php:

Output of 2
$ php sapi.php
cli            /etc/php/8.5/cli/php.ini     dev      pid=35784 memory=-1 time=0s
$ curl http://127.0.0.1:8201/sapi.php
cli-server     /etc/php/8.5/cli/php.ini     dev      pid=35785 memory=-1 time=30s
$ curl http://localhost/sapi.php        # Apache event MPM + PHP-FPM
fpm-fcgi       /etc/php/8.5/fpm/php.ini     www-data pid=18566 memory=128M time=30s
$ curl http://localhost/sapi.php        # Apache prefork MPM + mod_php
apache2handler /etc/php/8.5/apache2/php.ini www-data pid=35980 memory=128M time=30s

The CLI has no memory limit on Ubuntu 225 and no time limit at all: the CLI SAPI forces max_execution_time to 0 whatever php.ini says. Under FPM the PID is a php-fpm: pool www worker, separate from Apache; under mod_php it is an Apache child, because the interpreter lives inside it.

The SAPIs you will meet on a LAMP server
SAPI PHP_SAPI Runs as Use it for
CLI cli Your login user Scripts, cron, Composer 5,243
Built-in server cli-server Your login user Local development only
PHP-FPM fpm-fcgi The pool's user Production
Apache module apache2handler Apache's user Legacy; needs prefork

PHP-FPM is the production default. A master process manages pools of workers, each with its own user and limits, leaving Apache free to use its threaded event MPM. Ubuntu builds PHP non-thread-safe (the NTS in php -v), so mod_php forces prefork, one process per connection. PHP-FPM via proxy_fcgi wires Apache to FPM; Performance and OPcache tunes the pool. The built-in server is one process that stalls while any request blocks (PHP_CLI_SERVER_WORKERS=4 forks workers on Linux), and the manual says it must never face a public network: bind it to 127.0.0.1.