Skip to content
Faizul Karim Fahim

PHP Performance Tuning for Small VPSes

Getting slow PHP performance on a small VPS? I'll walk you through the common bottlenecks and the practical steps I take to speed things up: from PHP-FPM configuration to opcode caching, with a focus on what works best for limited resources.

Published 4 min read Web Development
A stylized image of a gear icon overlaid on a PHP code snippet, representing performance optimization.
On this page
  1. PHP-FPM Configuration
  2. Pool Settings
  3. Socket vs. TCP
  4. Opcode Caching
  5. Database Optimization
  6. My setup
  7. What went wrong (gotchas)
  8. Related reading

Slow PHP performance is a common headache, especially when you're running on a small VPS. I see it often on client boxes I usually manage. It’s not always a code problem; often, it’s a configuration issue. I’ll walk you through the common bottlenecks and the steps I take to speed things up, geared towards limited resources, specifically, environments like Ubuntu 24.04 or AlmaLinux 9.

PHP-FPM Configuration

PHP-FPM (FastCGI Process Manager) handles PHP execution. A misconfigured pool can kill performance. I usually start with the basics.

Pool Settings

Here's a simplified example of a PHP-FPM pool configuration. I'll assume you’re using the default pool, often found in /etc/php/8.3/fpm/pool.d/www.conf (adjust the 8.3 part to your PHP version).

[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock;  #Important: Check your socket path!
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 500

request_terminate_timeout = 300

php_admin_value[error_log] = /var/log/php8.3/www-error.log
  • listen: This is critical. Make sure it matches the socket path Nginx (or Apache) is configured to use. Incorrect socket paths are a very common source of errors. You can usually find the correct path in your web server configuration. For example, in Nginx, it might be something like /etc/nginx/sites-available/default.
  • pm: dynamic is often a good choice for VPSes as it adjusts the number of processes based on load. static is simpler but less flexible.
  • pm.max_children: This limits the number of PHP-FPM processes. Start low (around 5) and increase if you see errors or high load. Too many processes can overload your VPS.
  • pm.max_requests: This limits the number of requests a worker process handles before being recycled. Helps prevent memory leaks. 500 is a reasonable starting point.
  • request_terminate_timeout: How long PHP-FPM will wait for a request to finish. Adjust as needed based on your application's longest-running operations.

After making changes, reload PHP-FPM: sudo systemctl reload php8.3-fpm (again, adjust the PHP version).

Socket vs. TCP

PHP-FPM can listen on a Unix socket (like in the example) or a TCP port. Sockets are generally faster and more secure than TCP, so I prefer them. However, make sure your web server is configured to use the same method.

Opcode Caching

Opcode caching drastically improves performance by storing pre-compiled PHP code. OPcache is built into PHP and is almost always the best option.

Check your php.ini file (usually in /etc/php/8.3/cli/php.ini and /etc/php/8.3/fpm/php.ini).

[OPcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.validate_timestamps=0
opcache.revalidate_freq=60
  • opcache.enable: Must be 1 to enable OPcache.
  • opcache.memory_consumption: How much memory OPcache can use. 128MB is usually sufficient for small VPSes. Don't allocate too much; leave memory for other processes.
  • opcache.validate_timestamps: When set to 0, OPcache will not check if the source files have been modified. This is generally safer for production, as it prevents invalidating the cache unnecessarily. Set to 1 during development.
  • opcache.revalidate_freq: How often OPcache checks for file changes (when opcache.validate_timestamps=1). 60 seconds is a good compromise.

Restart PHP-FPM after making changes: sudo systemctl reload php8.3-fpm

Database Optimization

Slow database queries are a huge performance killer. I usually check my database logs first. Make sure you have indexes on frequently queried columns. Use EXPLAIN to analyze query performance. This is especially important if you’re using MySQL/MariaDB.

My setup

On my servers, I keep a close eye on PHP-FPM memory usage with top or htop. I also regularly check the PHP error logs for any unusual activity. I don’t bother with more complex profiling tools unless I’m actively debugging a specific performance issue. I also consistently use the latest stable PHP version; it often includes performance improvements.

What went wrong (gotchas)

  • Forgotten systemctl reload: Changes to php.ini or PHP-FPM pool configurations won't take effect until you reload the services. A classic mistake.
  • Incorrect socket path: Double-check the socket path in both your PHP-FPM configuration and your web server configuration.
  • Insufficient memory: If your VPS is constantly swapping, PHP performance will suffer. Consider upgrading your VPS or optimizing your code.
  • File permissions: Incorrect file permissions can prevent PHP-FPM from accessing files. Make sure the www-data user has read access to your PHP files.

That's the basics of PHP performance tuning for small VPSes. It’s a continuous process, monitor, adjust, and repeat.

Now, check your PHP-FPM logs!

Frequently asked questions

Why is my PHP website slow?

Slow PHP performance can be caused by several things, including inefficient code, a misconfigured PHP-FPM pool, missing opcode caching, or insufficient server resources. I usually start by checking the PHP error logs and using a profiler to identify bottlenecks.

How much RAM do I need for PHP-FPM?

It depends on your workload, but on a 2GB VPS, I rarely allocate more than 512MB to PHP-FPM. Over-allocating can waste resources that could be used elsewhere. Monitor memory usage and adjust as needed.

What's the best opcode cache for PHP?

OPcache is built into PHP since 5.5 and is generally the best choice. It's lightweight and effective for most use cases. I don't bother with alternatives unless I have a very specific, unusual need.

How can I monitor PHP performance?

Tools like New Relic and Blackfire are good, but often overkill for smaller sites. I usually rely on server monitoring tools (like htop) and PHP's built-in profiling tools to diagnose issues.

// keep reading

Related posts

All blog posts
A stylized image of a database server with a magnifying glass over a log file, representing performance analysis.
Web Development 2 min read

MySQL Slow Query Log Analysis for Performance

Finding bottlenecks in your database can be tough, but the MySQL slow query log is a goldmine. I'll walk through how I use it to pinpoint the queries slowing down my servers.

Terminal screen showing successful deployment output on an Ubuntu server
Web Development 4 min read

Zero-Downtime Laravel Deployment on Ubuntu

I configure zero-downtime Laravel deployments on Ubuntu servers using Git, PHP 8.3, and basic shell scripts without complex CI/CD tools.

A stylized illustration of shipping containers layered on top of a server rack, symbolizing Docker containers for web applications.
DevOps 4 min read

Docker for Web Apps: A Practical Guide

Setting up Docker can feel overwhelming, but it’s really worth it for keeping my web apps consistent across environments. I’ll walk through the basics, from your first Dockerfile to running a simple PHP app.