09/25/2012 11:33 pm ET Updated Oct 23, 2012

Deploying PHP: mod_php? CGI/suExec? FastCGI?

Flickr: walknboston

PHP is undoubtedly one of the most widely deployed scripting engines and languages used on the web today. Powering sites small and large (e.g., Facebook), PHP offers an easy to learn syntax familiar to anyone who has worked with C-inspired languages and a powerful collection of features for rapidly building modern applications. When deploying PHP, it is important to take into consideration the various ways in which PHP can be invoked by the web server.

PHP itself is written in C as an interpreter and compiled to a binary that is then executed in the user space of the operating system, just as any other application would be. Typical deployments configure PHP to be executed by the web server in one of three ways: mod_php (for Apache, or similar for other web servers), CGI (often with suExec), or FastCGI.

The Apache web server supports the use of an Apache module that facilitates loading each web server process with a PHP interpreter built in. Each web server worker process -- the process actually servicing incoming web requests -- will natively process PHP code. No process forking or invocation of an external program is required to parse PHP code. The benefit to this approach is that the speed and performance of PHP requests is substantially superior to other methods. By not having to request the OS to create a new process and to initialize the PHP runtime, responses are much faster.

The downside to this approach, however, is that all PHP requests are served by and executed as the user of the web server. If a server is hosting multiple users' sites, this means that User A will, by design, have at least read, and often write access to all other users' web files. Another downside to this approach is the size of each Apache worker process is much greater, for each process must load all of the PHP interpreter and any associated libraries in memory. To allow a web server to facilitate many request concurrently, Apache will spawn many worker processes depending on traffic to handle requests. The additional memory used and load time to spawn a new worker process can sometimes be substantial.

If a web server is only servicing requests for one website or web user, the mod_php approach may be and often is the best approach, particularly is a great number of requests are to PHP scripts. If a large portion of requests are for static content, but otherwise the site being served is PHP, it could be beneficial to offload static content to a CDN or a set of non-PHP enabled servers, thus offloading the need to service non-PHP requests to other web servers.

Common Gateway Interface (CGI) is a standard (1) method for allowing web servers the ability to execute programs and return the output as web content. This method was an early way to allow the creation of dynamic content, facilitating communication about the particular web request to an external program, that is still widely used today. An administrator can define any number of script interpreters (Perl, PHP, Python, Ruby, etc.) and compiled/binary applications (C programs, etc.) to be accessed by the web server based on the extension of a file or a set of rules.

CGI execution also facilitates the implementation of an Apache feature called suExec. When enabled, this allows specific CGI requests to be executed as another administratively-defined user, different than the user of the web server itself. This means scripts and applications executed by the web server can be constrained by the operating system limitations of a given user for things such as file permissions, restricting access to the files and operations that can be performed by a given script. Effectively, this quarantines CGI requests and allows the time-proven safety of operating system user security to be utilized.

CGI, however, does have negative aspects. Each new request must spawn a separate process. This uses additional memory that would otherwise not be used. Also, due to the work that must be done by the kernel to create a new process, significant overhead and delay in response processing is incurred. Bottom line: CGI is safe but slow.

FastCGI is an attempt to garner the best of both mod_php and CGI. FastCGI is a pool of application processes (e.g., PHP) sitting idle waiting for incoming request. These processes are spawned when the web server starts up. Instead of spawning a new process for each request, as does CGI, the request processing engines are already sitting idle ready to immediately go to work. By having a pool (or multiple pools) of multiple FastCGI processes for each application, requests can be reasonably serviced with no initialization overhead.

FastCGI processes can be configured to execute as specific users other than the web server, so the security benefits of CGI are obtained. By not having to wait for the kernel to spawn new processes, the benefits of mod_php are obtained.

The downside to FastCGI is that utilizing this setup in a multi-tenant (multi-user/multi-site) deployment, separate pools must be setup and created. For large deployments with many pools, this can utilize significant amount of memory on web servers for processes sitting idle doing nothing. Additionally, under heavy load, FastCGI can be configured to spawn more CGI processes to service more requests concurrently. However, spawning new processes incurs the same overhead as found in CGI.

In short, the differences in PHP deployment approaches can be summarized as follows:
mod_php is fast, but unsafe for multi-tenant deployments
CGI is safe, but slow
FastCGI is fast and safe, but has potentially overhead in large-scale multi-tenant deployments