When a Second of Downtime Costs a Million
\n\nImagine: you're updating an online store on PHP, uploading a new version via FTP, and at that moment the site goes down for 5 minutes. Five minutes is 300 seconds. During this time, 100 potential customers leave for competitors, and you lose not only money but also reputation. Sound familiar?
\n\nIn today's world, where users don't forgive mistakes, zero-downtime deployment of PHP services is not a luxury but a necessity. But how do you implement seamless deployment if your stack is PHP, Nginx, and several servers? Let's figure it out with real examples.
\n\nWhy PHP is Harder Than It Seems?
\n\nUnlike Node.js or Python, PHP does not support multithreading in the classical sense. Each request is handled by a separate PHP-FPM process. This imposes limitations: you can't just "reload" the code without losing current sessions. However, this same property gives us a superpower — the ability to smoothly switch traffic between versions.
\n\nMain problems during PHP deployment:
\n- \n
- Connection breaks — the user loses form data or session \n
- Dirty caching — old code returns data from outdated cache \n
- Broken migrations — the new database version is incompatible with the old code \n
To avoid these pitfalls, we use proven strategies. And yes, zero-downtime deployment is not magic, but a clear plan.
\n\nStrategy #1: Blue-Green Deployment
\n\nThe most reliable method is to keep two full copies of the application: "blue" (current) and "green" (new). Nginx acts as a load balancer.
\n\nHow It Looks in Practice
\nLet's say you have two servers: app1.example.com (blue) and app2.example.com (green). Both run PHP-FPM. Currently, blue is active. You deploy the new version to green, test it, and then switch Nginx to green.
Example Nginx configuration for switching:
\n\n# nginx.conf\nupstream php_backend {\n # First active blue\n server app1.example.com:9000 weight=1; # blue\n server app2.example.com:9000 weight=0; # green (disabled)\n}\n\nserver {\n listen 80;\n server_name myshop.com;\n\n location ~ \\.php$ {\n fastcgi_pass php_backend;\n include fastcgi_params;\n fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n }\n}\n\n\nAfter deploying to green, change the weights:
\n\n# After deployment — switch traffic\nupstream php_backend {\n server app1.example.com:9000 weight=0; # blue (disabled)\n server app2.example.com:9000 weight=1; # green (active)\n}\n\n\nReload Nginx without downtime: nginx -s reload. All current connections terminate gracefully, and new ones go to green. Zero-downtime PHP deployment is achieved!
Pros and Cons
\nPros: full fault tolerance, you can quickly roll back (just restore the weights).
\nCons: requires twice the resources (servers or containers).
Strategy #2: Rolling Update (Gradual Update)
\n\nIf your budget is limited, use rolling update. The idea: update PHP servers one by one without turning off the others. Users don't notice downtime because Nginx redirects requests to live servers.
\n\nImplementation on PHP-FPM
\nSuppose you have 3 servers with PHP-FPM. We sequentially take them out of rotation, update the code, and bring them back.
\n\nStep 1: Remove the server from the load balancer (graceful shutdown):
\n\n# On the server being updated\nsudo systemctl stop php8.1-fpm\n# Nginx will stop sending requests to this server since it's unavailable\n\n\nStep 2: Update the code (via git pull, rsync, or Docker).
\n\nStep 3: Start PHP-FPM again:
\n\nsudo