PHP-FPM From the Absolute Basics
We now have:
Browser
↓
DNS
↓
IP
↓
TCP
↓
TLS
↓
HTTP
↓
Nginx
↓
?
The missing component is:
PHP-FPM
This is one of the most important technologies to understand if you want to build and manage WordPress hosting.
1. First: What Is PHP?
PHP is a programming language commonly used for server-side web applications.
WordPress is primarily written in PHP.
For example:
<?php
echo "Hello World";
A PHP program runs on the server.
The browser normally does not receive the PHP source code.
Instead:
PHP source
↓
PHP interpreter
↓
Generated result
↓
HTML
↓
Browser
2. PHP Is Server-Side
Compare:
HTML
<h1>Hello</h1>
The browser receives and interprets the HTML.
PHP
<?php
echo "<h1>Hello</h1>";
The server executes the PHP first.
The browser receives the resulting HTML:
<h1>Hello</h1>
3. Simple Example
Suppose the server contains:
/storage/websites/example.com/public/index.php
with:
<?php
$name = "CresignSys";
echo "<h1>Hello $name</h1>";
The browser requests:
/
The server executes PHP.
The browser receives:
<h1>Hello CresignSys</h1>
It does not normally receive:
$name = "CresignSys";
4. PHP Interpreter
Something must actually execute PHP code.
That component is the PHP interpreter/runtime.
Conceptually:
PHP file
↓
PHP runtime
↓
execution
↓
output
But where does PHP-FPM fit?
5. What Does FPM Mean?
FPM means:
FastCGI Process Manager
So:
PHP-FPM
=
PHP FastCGI Process Manager
It manages PHP worker processes that execute PHP applications.
6. Why Do We Need PHP-FPM?
Nginx is excellent at serving HTTP traffic.
But Nginx is not a PHP interpreter.
Therefore:
Browser
↓
Nginx
↓
PHP-FPM
↓
PHP
Nginx handles the web side.
PHP-FPM manages PHP execution.
7. Nginx and PHP-FPM Have Different Jobs
Nginx
Handles:
HTTP
TLS
routing
static files
connections
headers
reverse proxying
PHP-FPM
Handles:
PHP workers
PHP execution
worker lifecycle
PHP process management
WordPress
Handles:
pages
posts
plugins
themes
users
database queries
application logic
8. The Complete Flow
When somebody visits:
https://templates.cresignsys.com/about/
the simplified flow is:
Browser
↓
TLS
↓
HTTP
↓
Nginx
↓
FastCGI
↓
PHP-FPM
↓
PHP
↓
WordPress
↓
MySQL
Then the result travels back.
9. What Is FastCGI?
FastCGI is a protocol/interface for communicating between a web server and an application process manager.
Conceptually:
Nginx
│
│ FastCGI
▼
PHP-FPM
Nginx sends information about the HTTP request.
PHP-FPM passes it to a PHP worker.
10. Why Not Just Start PHP for Every Request?
Imagine:
Request 1
↓
start PHP
↓
execute
↓
stop PHP
Request 2
↓
start PHP
↓
execute
↓
stop PHP
That would introduce unnecessary process-start overhead.
PHP-FPM keeps a managed pool of workers.
11. Worker Processes
Think of PHP-FPM as a team of PHP workers.
PHP-FPM
│
├── Worker 1
├── Worker 2
├── Worker 3
├── Worker 4
└── Worker 5
Requests can be assigned to available workers.
12. Why Multiple Workers?
Suppose 10 users access WordPress simultaneously.
If only one PHP worker can execute requests:
Request 1
Request 2
Request 3
...
they may wait behind one another.
With multiple workers:
Request 1 → Worker 1
Request 2 → Worker 2
Request 3 → Worker 3
Request 4 → Worker 4
multiple requests can be processed concurrently.
13. But More Workers Isn’t Always Better
This is extremely important.
More workers consume:
RAM
CPU
database connections
file descriptors
Suppose each PHP worker uses significant memory.
If you configure:
100 PHP workers
on a small VPS, you may exhaust RAM.
Therefore:
PHP-FPM worker configuration must match the server’s resources and workload.
14. PHP-FPM Pool
PHP-FPM organizes workers into:
Pools
A pool might look conceptually like:
Pool: www
│
├── Worker
├── Worker
├── Worker
└── Worker
The pool configuration controls how those workers operate.
15. Default Pool
On Ubuntu/Debian systems, a common default pool is:
www
Its configuration is often under something like:
/etc/php/<version>/fpm/pool.d/www.conf
For example:
/etc/php/8.3/fpm/pool.d/www.conf
Your installed PHP version may differ.
16. Find Your PHP Version
Run:
php -v
You might see:
PHP 8.x.x
But remember:
CLI PHP and PHP-FPM can be configured differently.
So also inspect:
systemctl list-units --type=service | grep php
17. Find PHP-FPM Services
Try:
systemctl list-units --type=service | grep fpm
You may see something like:
php8.3-fpm.service
18. Check PHP-FPM Status
For a specific version:
sudo systemctl status php8.3-fpm
Replace 8.3 with your installed version.
You want something similar to:
Active: active (running)
19. PHP-FPM Socket
Nginx needs somewhere to send FastCGI requests.
A common configuration is:
/run/php/php8.3-fpm.sock
This is a Unix socket.
20. Check PHP Sockets
Run:
ls -la /run/php/
You may see:
php8.3-fpm.sock
or multiple versions:
php8.1-fpm.sock
php8.2-fpm.sock
php8.3-fpm.sock
21. Nginx Configuration
You may have something like:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
This creates the connection:
Nginx
↓
Unix socket
↓
PHP-FPM
22. What Is a Unix Socket?
A Unix socket is a local communication endpoint.
Instead of using:
127.0.0.1:9000
Nginx can communicate through:
/run/php/php8.3-fpm.sock
Both processes are on the same server.
23. TCP Alternative
PHP-FPM can also listen on a TCP address.
Conceptually:
Nginx
↓
127.0.0.1:9000
↓
PHP-FPM
This is different from:
Nginx
↓
Unix socket
↓
PHP-FPM
Both are valid architectures.
24. Why Unix Sockets Are Common
For same-machine communication, Unix sockets can be convenient and efficient.
They also avoid exposing PHP-FPM on a network port unnecessarily.
25. PHP-FPM Pool Configuration
A simplified pool might contain:
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 5
This is an educational example, not a recommended production configuration for your particular server.
26. user
user = www-data
means worker processes run under that user.
This connects directly to our previous lesson.
PHP-FPM
↓
www-data
↓
Linux permissions
27. group
group = www-data
sets the worker process group.
Again:
User
+
Group
+
Filesystem permissions
determine what PHP can access.
28. listen
Example:
listen = /run/php/php8.3-fpm.sock
This tells PHP-FPM where to receive FastCGI connections.
Nginx must point to the corresponding endpoint.
29. The Socket Must Match
If Nginx says:
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
but PHP-FPM is listening at:
/run/php/php8.2-fpm.sock
the connection will fail.
This can produce:
502 Bad Gateway
30. Classic 502 Problem
Browser
↓
Nginx
↓
PHP-FPM socket
X
Possible reasons:
PHP-FPM stopped
Wrong socket
Wrong PHP version
Socket permissions
Pool configuration failure
PHP-FPM crashed
31. Check the Socket
Run:
ls -la /run/php/
Then compare it with:
sudo nginx -T | grep fastcgi_pass
This is a very useful diagnostic.
32. Process List
You can inspect PHP processes:
ps aux | grep php-fpm
or:
ps -ef | grep php-fpm
You may see:
root php-fpm: master process
www-data php-fpm: pool www
www-data php-fpm: pool www
www-data php-fpm: pool www
33. Master Process
PHP-FPM usually has a master process.
Conceptually:
PHP-FPM
│
└── Master
│
├── Worker
├── Worker
├── Worker
└── Worker
The master manages the worker pool.
34. Worker Process
Workers perform PHP application work.
For example:
HTTP request
↓
Nginx
↓
PHP-FPM
↓
Worker
↓
WordPress
35. pm
PHP-FPM has different process-management strategies.
Common modes include:
static
dynamic
ondemand
36. Static
With:
pm = static
PHP-FPM maintains a fixed number of workers.
Example:
pm.max_children = 10
means approximately 10 child workers.
37. Dynamic
With:
pm = dynamic
PHP-FPM dynamically manages the number of child processes within configured limits.
It uses settings such as:
pm.max_children
pm.start_servers
pm.min_spare_servers
pm.max_spare_servers
38. Ondemand
With:
pm = ondemand
workers can be created when requests arrive and removed after an idle period.
This can be useful for some low-traffic workloads.
39. pm.max_children
This is one of the most important settings.
Example:
pm.max_children = 10
It limits the number of child processes in the pool.
Conceptually:
Maximum concurrent PHP workers
=
10
40. Why It Matters
Suppose:
RAM = 4 GB
and PHP workers consume significant memory.
If you allow:
100 workers
the system can run out of memory.
Possible result:
RAM exhaustion
↓
swap pressure
↓
slow server
↓
process termination
↓
website failures
41. PHP-FPM and RAM
A simplified model:
PHP worker memory
×
number of workers
≈
PHP memory requirement
This is only an approximation because real memory usage varies.
But it gives you the right mental model.
42. CPU Also Matters
PHP workers consume CPU.
Suppose:
100 requests
all execute heavy WordPress operations.
Then:
PHP
↓
CPU saturation
can occur.
So PHP-FPM tuning is not just about RAM.
43. Database Connections
PHP workers may also interact with MySQL.
If you have:
50 PHP workers
you can potentially have many database interactions occurring concurrently.
Therefore:
PHP-FPM capacity
must be considered together with:
MySQL capacity
44. WordPress Request
Let’s follow one request.
Browser:
GET /about/
Nginx:
Request matches location /
Then:
try_files
↓
index.php
Then:
FastCGI
↓
PHP-FPM
Then:
PHP worker
↓
WordPress
45. WordPress Loads
WordPress may load:
wp-config.php
wp-settings.php
plugins
theme
core files
Then it initializes the application.
46. WordPress Queries MySQL
For example, WordPress may need:
Site settings
Posts
Pages
Menus
Users
Metadata
Plugin settings
So:
PHP
↓
MySQL
↓
results
↓
PHP
47. PHP Generates HTML
WordPress eventually produces:
<html>
<head>
...
</head>
<body>
...
</body>
</html>
Then:
PHP worker
↓
PHP-FPM
↓
Nginx
↓
Browser
48. One Request May Be Expensive
A request can involve:
Nginx
↓
PHP-FPM
↓
WordPress
↓
20+ plugins
↓
Theme
↓
MySQL
↓
External APIs
↓
HTML
That is why a “simple webpage” can involve significant server work.
49. PHP OPcache
PHP has an important performance feature:
OPcache
OPcache stores compiled PHP bytecode in shared memory.
Without OPcache, PHP may repeatedly parse/compile scripts.
Conceptually:
PHP source
↓
compile
↓
bytecode
↓
execute
With OPcache:
PHP source
↓
compile once
↓
OPcache
↓
reuse compiled code
50. Why OPcache Matters for WordPress
WordPress contains a large number of PHP files.
Plugins and themes add more.
OPcache can significantly reduce repeated compilation overhead.
51. Check OPcache
Run:
php -m | grep -i opcache
You can also inspect:
php -i | grep -i opcache
But remember that CLI PHP configuration may differ from FPM.
52. Check FPM PHP Configuration
A PHP-FPM process may use a configuration such as:
/etc/php/8.3/fpm/php.ini
while CLI PHP may use:
/etc/php/8.3/cli/php.ini
Therefore:
CLI PHP
≠
FPM PHP
necessarily.
53. Why This Matters
You might run:
php -i
and conclude:
PHP has this setting.
But your website may be running under PHP-FPM with a different configuration.
For website troubleshooting, inspect the FPM configuration.
54. php.ini
PHP configuration controls many runtime behaviors.
Examples include:
memory_limit
max_execution_time
upload_max_filesize
post_max_size
max_input_vars
date.timezone
55. memory_limit
Example:
memory_limit = 256M
This limits memory available to a PHP request under normal PHP memory accounting.
It does not mean:
Every PHP worker permanently consumes 256 MB.
Actual memory usage varies.
56. max_execution_time
Example:
max_execution_time = 60
This controls how long PHP code is allowed to execute under the relevant PHP semantics.
It is not a universal guarantee that every request will terminate exactly at that time because other layers also have timeouts.
57. upload_max_filesize
Example:
upload_max_filesize = 64M
This limits the size of an individual uploaded file at the PHP level.
58. post_max_size
Example:
post_max_size = 64M
This limits the maximum size of POST data PHP will accept.
It should generally be large enough relative to intended uploads.
59. Multiple Limits Exist
An upload can be restricted by several layers:
Browser
↓
Nginx
↓
PHP-FPM/PHP
↓
WordPress
For example:
Nginx client_max_body_size
PHP upload_max_filesize
PHP post_max_size
WordPress/application limits
The smallest effective limit can become the practical restriction.
60. Nginx vs PHP-FPM
This distinction is important:
Nginx
=
receives HTTP request
PHP-FPM
=
runs PHP
PHP
=
language/runtime
WordPress
=
application
61. PHP-FPM Does Not Equal WordPress
Think:
PHP-FPM
↓
can run
↓
any compatible PHP application
It isn’t specifically a WordPress service.
It can run:
WordPress
Laravel
Drupal
Magento
custom PHP
and many other PHP applications.
62. One PHP-FPM Pool Can Serve Multiple Sites
A basic server might use:
Nginx
│
└── PHP-FPM www pool
├── site1
├── site2
└── site3
This is simple.
But for stronger isolation, separate pools/users can be used.
63. Multi-Tenant Hosting
This becomes important for your hosting platform.
Imagine:
CresignSys Hosting
│
├── Customer A
├── Customer B
├── Customer C
└── Customer D
You don’t necessarily want all customers’ PHP applications running with exactly the same privileges.
A stronger architecture might be:
Customer A
↓
PHP-FPM pool A
↓
user A
Customer B
↓
PHP-FPM pool B
↓
user B
64. Why Separate Users Matter
Suppose:
Customer A
has a vulnerable plugin.
If A’s PHP process runs as:
customerA
then Linux permissions can limit access to:
customerA's files
instead of:
all customer websites
This is an important multi-tenant security principle.
65. Shared www-data Model
A simpler model:
site A → www-data
site B → www-data
site C → www-data
is easier to manage.
But isolation is weaker.
A compromise of one application running under the same account can potentially access files writable/readable by that shared account.
66. Isolated Pool Model
A more isolated model:
site A → php-fpm pool A → userA
site B → php-fpm pool B → userB
site C → php-fpm pool C → userC
gives more control.
It is more complex to configure and manage.
67. This Is Where Hosting Panels Become Useful
Hosting panels automate:
User creation
Website creation
PHP-FPM pools
Nginx configuration
Permissions
SSL
Logs
Databases
Backups
Your CresignSys Hosting Platform is essentially moving toward building these capabilities yourself.
68. PHP-FPM Logs
Check service logs with:
sudo journalctl -u php8.3-fpm
For recent entries:
sudo journalctl -u php8.3-fpm -n 100
Replace the version with yours.
69. Follow Logs Live
sudo journalctl -u php8.3-fpm -f
Then make a website request.
You can observe whether PHP-FPM reports errors.
70. Nginx + PHP-FPM Debugging
If you receive:
502 Bad Gateway
use this sequence:
1. Is Nginx running?
2. Is PHP-FPM running?
3. Does the socket exist?
4. Does Nginx point to the correct socket?
5. Can Nginx connect to the socket?
6. Are socket permissions correct?
7. Does PHP-FPM report errors?
71. Check Service
systemctl status php8.3-fpm
72. Check Socket
ls -l /run/php/
73. Check Nginx Configuration
sudo nginx -T | grep -n fastcgi_pass
74. Check Nginx Errors
sudo tail -f /var/log/nginx/error.log
75. Check PHP-FPM Errors
sudo journalctl -u php8.3-fpm -f
76. This Gives a Complete Diagnostic Chain
Browser
↓
HTTP 502
↓
Nginx
↓
error.log
↓
PHP-FPM
↓
journalctl
↓
socket
↓
Linux permissions
Instead of randomly changing configuration, you identify the failing layer.
77. Test PHP Directly
Create a temporary test file only when needed and remove it afterward:
<?php
phpinfo();
For example:
/storage/websites/example.com/public/test.php
Then visit:
https://example.com/test.php
This shows the PHP environment used by the website.
78. Security Warning
phpinfo() exposes extensive environment information.
Do not leave it publicly accessible.
After testing:
rm /storage/websites/example.com/public/test.php
79. Better: Temporary Diagnostic Endpoint
For production environments, prefer safer diagnostics rather than leaving phpinfo() publicly available.
The principle is:
diagnostic information
↓
temporary
↓
restricted
↓
removed after use
80. PHP Version
Different PHP versions can behave differently.
For example:
PHP 8.1
PHP 8.2
PHP 8.3
PHP 8.4
Applications and plugins may have compatibility requirements.
Therefore a hosting platform must manage PHP versions carefully.
81. Multiple PHP Versions
A server can potentially have:
PHP 8.1
PHP 8.2
PHP 8.3
PHP 8.4
with different FPM services:
php8.1-fpm
php8.2-fpm
php8.3-fpm
php8.4-fpm
Then different websites can use different versions.
82. Example
siteA.com
↓
PHP 8.2 FPM
siteB.com
↓
PHP 8.3 FPM
siteC.com
↓
PHP 8.4 FPM
Nginx determines which PHP-FPM endpoint each website uses.
83. Why Hosting Providers Offer PHP Versions
Customers may have applications that require:
specific PHP version
A hosting platform therefore often offers:
PHP version selector
This is a significant feature for a commercial hosting system.
84. PHP Lifecycle
PHP versions eventually reach:
Active support
↓
Security support
↓
End of life
A hosting platform should avoid encouraging unsupported PHP versions unless there is a specific legacy requirement and appropriate risk management.
85. WordPress Compatibility
WordPress itself, themes, and plugins can have different compatibility requirements.
Therefore changing:
PHP 8.2 → 8.4
should be tested rather than done blindly on production websites.
86. PHP-FPM Is a Process Manager
Remember the full meaning:
PHP
=
language/runtime
FastCGI
=
communication protocol/interface
FPM
=
process manager
Together:
PHP-FPM
=
managed PHP execution through FastCGI
87. Deep Request Architecture
Now our architecture is:
Browser
│
▼
HTTPS
│
▼
Nginx
│
│ FastCGI
▼
PHP-FPM master
│
▼
PHP worker
│
▼
WordPress
│
▼
MySQL
And the filesystem/security layer:
PHP worker
│
▼
Linux user
│
▼
Linux kernel
│
▼
Filesystem
88. The Most Important Concepts
Memorize these:
PHP
=
server-side programming language/runtime
PHP-FPM
=
PHP process manager
FastCGI
=
communication mechanism between Nginx and PHP-FPM
Pool
=
group of PHP workers
Worker
=
process that executes PHP requests
Socket
=
communication endpoint
OPcache
=
compiled PHP bytecode cache
php.ini
=
PHP configuration
pm.max_children
=
maximum child workers for a pool
89. One Complete WordPress Request
Let’s put everything together.
User requests:
https://templates.cresignsys.com/about/
DNS
domain
↓
IP
TCP
client
↓
server:443
TLS
secure channel
HTTP
GET /about/
Host: templates.cresignsys.com
Nginx
server_name
↓
location /
↓
try_files
PHP-FPM
FastCGI
↓
PHP worker
WordPress
load WordPress
↓
plugins
↓
theme
↓
database
MySQL
query
↓
result
PHP
generate HTML
Nginx
send response
TLS
encrypt response
Browser
decrypt
↓
parse HTML
↓
render page
90. The Full Hosting Stack
You can now visualize your server as:
INTERNET
│
▼
DNS
│
▼
IP/Route
│
▼
TCP / QUIC
│
▼
TLS
│
▼
HTTP
│
▼
NGINX
│
┌──────────┴──────────┐
│ │
▼ ▼
Static files FastCGI
│
▼
PHP-FPM
│
┌────┴────┐
▼ ▼
Worker 1 Worker 2
│
▼
WordPress
│
▼
MySQL
│
▼
Filesystem
│
▼
Linux Kernel
│
┌────────┴────────┐
▼ ▼
RAM Disk
This is the core architecture of a traditional PHP WordPress hosting environment.
Lesson 044 Summary
The most important idea:
Nginx receives the web request; PHP-FPM provides managed PHP execution; WordPress is the PHP application.
The relationship is:
Nginx
↓
FastCGI
↓
PHP-FPM
↓
PHP worker
↓
WordPress
↓
MySQL
And PHP-FPM’s resources are controlled through:
workers
pools
memory
CPU
sockets
timeouts
PHP configuration
OPcache
For your own hosting platform, this is the layer where website performance, PHP version selection, resource limits, and multi-tenant isolation become major design considerations.
Next Lesson — 045
MySQL From the Absolute Basics — How WordPress Stores Everything
We will start from:
What is data?
What is a database?
What is SQL?
What is MySQL?
What is a table?
What is a row?
What is a column?
What is a primary key?
What is an index?
Then connect it directly to WordPress:
Browser
↓
Nginx
↓
PHP-FPM
↓
WordPress
↓
MySQL
├── wp_posts
├── wp_users
├── wp_options
├── wp_postmeta
├── wp_terms
└── wp_usermeta
and trace exactly what happens inside MySQL when you create a WordPress page, user, plugin, menu, or post.
Leave a Reply