How PHP Works with Extensions Under the Hood

Suppose you enable 5 extensions in your PHP configuration—such as curl, redis, mysqli, and others. When PHP-FPM boots up, it reads the php.ini file, identifies these 5 enabled extensions, goes to their physical file paths, and loads them into your server's physical RAM.

Important Note: These extensions are loaded into Shared Memory. Because they are loaded in read-only mode, tens or hundreds of individual PHP worker processes can read from this single memory space at the exact same time without duplicating the files.

However, if you enable hundreds of PHP extensions that you do not actually use anywhere in your application, they will still consume your system resources because the operating system is forced to load every single one of them into memory.

The Catch with Multiple PHP Versions

There is a major catch if you run multiple PHP versions on the same machine (for example, PHP 7.4, PHP 8.2, and PHP 8.4) and enable the same 10 extensions across all of them. Even if you enable the exact same curl extension in all three versions, the Operating System does not compare the underlying code.

Instead, the OS looks strictly at the file paths. Because each PHP version stores its extensions in a unique, isolated directory path, the kernel treats them as completely separate programs. It will load the extension three separate times into physical memory. Running multiple PHP versions simultaneously will consume a lot of your server's resources.

Conversely, if you host 100 different domains on your VPS and configure all of them to use the same PHP version (such as PHP 8.4), the extensions are loaded only once. That single, shared set of extensions is efficiently shared across all the PHP worker processes handling those 100 domains.


How PHP Processes Your Code: Traditional vs. Modern Routing

1. The Traditional Way (File-Based Routing)

In the early days of web development, a request would come in for a specific file name, like /blog.php. The web server (like Apache) would pass this path straight to PHP-FPM. The PHP-FPM worker process would execute a single disk Input/Output (I/O) operation to read that specific file, interpret the code, and instantly respond back to the user. It was very simple and required just one file system check.

2. The Modern Way (Clean URL Routing)

Modern frameworks use clean, hidden paths like /user/add. In this setup, the workflow becomes much more complex:

  • The web server receives the request for /user/add.
  • It asks the Linux kernel to check the hard drive via an I/O operation.
  • The kernel responds that no such file or folder exists.
  • Instead of failing, the web server rewrites the URL internally to index.php/user/add.
  • The web server passes this updated path to PHP-FPM.
  • The PHP-FPM worker process must now execute an I/O operation to read index.php.
  • Inside index.php, the code triggers more disk reads to open routing configuration files, boot up the framework engine, and finally locate your specific UserController and its add() function.

Without optimization, this modern approach results in 3 or more disk I/O operations and repetitive code interpretation for every single request, slowing down your application.


Enter OPcache: The Zero-I/O Engine

To solve the performance cost of modern routing, we use the OPcache extension—a core optimization module that comes natively with PHP.

When you enable OPcache, it completely changes the execution lifecycle. The first time your framework files are accessed, OPcache compiles the raw text code into compiled bytecode and stores it directly inside a dedicated memory bucket in your RAM.

Because of this, all future requests trigger zero disk I/O operations for your code files. The PHP worker process completely skips reading the hard drive, instantly looks up the routes directly inside the RAM-cached bytecode, and responds to the user in a fraction of a millisecond.

  • Note on Static Files: OPcache strictly ignores static files like images, CSS, or JavaScript. It only optimizes and loads files ending in .php.
  • Note on Web Servers: Because OPcache is purely a PHP extension living inside PHP-FPM, it has no direct relationship with your web server. Whether you choose Apache, Nginx, Caddy, or any other server, OPcache will work exactly the same way behind the scenes.

What happend when change in any php file - With OPCache

we have two options, to load change code into memory,

1. First one is Automatic way

apache
opcache.validate_timestamps = 1
opcache.revalidate_freq = 2 ; Checks the disk every 2 seconds

When you change the file

  • A web request hits PHP-FPM.
  • The PHP engine quickly asks the Linux kernel: "Has the modified timestamp (mtime) of this file on the hard drive changed since I last cached it?"
  • If it detects that you modified the file, OPcache instantly destroys the old bytecode in RAM, reads the updated file from the disk, compiles it into fresh bytecode, and saves it to the RAM bucket.

2. Second one is Manual way (Production way)

apache
opcache.validate_timestamps = 0

When this is set to 0, PHP completely seals its memory bucket. It never looks at the hard drive timestamps again. If you open your terminal, modify a file, and hit save:

  • Absolutely nothing will change on your live website.
  • The server will continue running the old code version stuck in the RAM bucket forever, completely blind to your file updates.
linux
sudo systemctl reload php8.4-fpm
after restart php, your change code loaded into memory again

How Gracefully PHP do restart work - (0 Downtime)

  • They do similar like a Docker do, like old request serve by php worker process through old bytes and that OPCache extension transform the new code and loaded into memory alongside with older one.
  • Now, after the new code loaded into memory now new request serve through new bytes codes
  • when older request work is successsfully completed they gradually remove older bytes code, that's why 0 downtime, happen