fastcgi_finish_request() – Advantages and Pitfalls
Why you should consider using fastcgi_finish_request() sparingly.
PHP-FPM has become the de-facto process manager for PHP, providing more flexibility than the venerable PHP module for Apache (aka
apache2handler). Thanks to it, PHP is no longer coupled with the web server, making it possible to gracefully start and restart PHP workers without impacting the web server itself.
One of the valuable features offered by PHP-FPM is the
fastcgi_finish_request() particular function, which role is to flush the HTTP response data to the client while allowing the application to continue processing potentially time-consuming tasks (i.e., “finishing the request”).
The main advantage of this function is that it emulates an asynchronous process. Indeed, The HTTP response being already received, any instruction triggered after the call to
fastcgi_finish_request() won’t affect them. Such instructions could be sending e-mails, processing some stats, or even generating PDF files.
Furthermore, most frameworks integrate it within their workflows:
- Symfony, using the kernel.terminate event;
- Laravel, using the Terminable middleware.
In short, this core PHP feature allows one to execute some processes in a pseudo-asynchronous way for free! However, this can lead to several pitfalls that may degrade the performance of your application.
The main problem with
fastcgi_finish_request() is that it keeps the PHP worker busy. In other words, your PHP-FPM pool misses one worker that could handle other requests. In the case of high traffic, this may lead to a dog-piling effect in your FPM threads. You would get more incoming requests than what your pool is capable of handling.
Furthermore, depending on how your application is built, filesystem or database locks may not be released, forcing clients to wait for the current PHP worker to finish its job.
New Blackfire Recommendation
While this functionality can be helpful in light cases, you should use it sparingly. Whenever you need to trigger heavier processes, you may consider treating them asynchronously, with the help of message brokers such as RabbitMQ, together with libraries like Symfony Messenger component or Laravel Queues.
In this regard, we defined a recommendation in Blackfire, which would appear if the time spent after
fastcgi_finish_request() reaches a certain threshold.
Give Blackfire a try!
Recommendations are available for all paid plans (Profiler, Premium, and Enterprise plans). Play with the demo or subscribe now!