That's not quite right. Imagine some (horrid) code like:
$conn->query('SELECT * FROM giant_table ORDER BY foo LIMIT 1');
require 'old.php';
such that there's a significant interval between the request being spawned and it later including another file. The duration of the query is the opportunity for 'old.php' to go away, which would cause a 500 error.
The difference is that you can have 2 ports listening at once and can close the first once it's drained of connections.
There's no fundamentally safe way to upgrade a bucket-of-files PHP app without tooling complex enough to rival another language's deployment.
I don't believe thats how PHP works (atleast not anymore). When the request is made the code is first compiled to opcodes and only after that's done the opcodes are run. In most production environments these opcodes are even cached so even if you delete the project it will run.
In any case you would have to hit some few milisecond window in this opcache generation to break single request but even that might be unlikely thanks to how filesystems read files?
So if there's a 10 second gap between the start of execution and the 'require' line being reached and evaluated, then any incompatible changes to the file being required within that 10 seconds will cause an error.
The difference is that you can have 2 ports listening at once and can close the first once it's drained of connections.
There's no fundamentally safe way to upgrade a bucket-of-files PHP app without tooling complex enough to rival another language's deployment.