Migrating to a Linux VPS does not automatically make a website faster. With a default configuration, TTFB and page generation often improve very little. Real gains come from tuning PHP-FPM, Nginx or Apache, Redis, MySQL or MariaDB, OPcache, and other components involved in request processing.
On shared hosting, most of these settings are fixed or unavailable, so the application has to adapt to the platform instead of the platform being optimised for the application.
For this reason, moving the same project to a VPS rarely produces an immediate speed increase. WooCommerce benefits from PHP-FPM tuning, Redis Object Cache, and database optimisation. Moodle relies on PHP-FPM, OPcache, cron jobs, and MariaDB, while CRM systems and B2B portals are more often limited by PHP workers, SQL performance, or missing object caching.
Once these bottlenecks are removed, TTFB often falls from 700–1000 ms to 150–300 ms, although the exact result depends on the application, traffic, database structure, and code quality.
Before changing server settings, measure TTFB, review CPU, memory, database performance, and logs, then optimise the components responsible for the slowdown instead of changing settings by trial and error.
This is something we regularly see at Era.Host. Hardware upgrades alone rarely improve performance if the software stack remains unchanged. The real advantage of a Linux VPS is full control over the environment, allowing every layer of the stack to be tuned for consistently lower TTFB and faster page generation.
How to Tell When Shared Hosting Has Become the Bottleneck
A website can be well optimised at the CMS level and still slow down during busy periods. You may have removed unnecessary plugins, compressed images, enabled page caching, upgraded PHP, and cleaned up the database, yet TTFB still rises to 800–1500 ms every evening. At the same time, HTTP 503 errors appear, the admin area becomes sluggish, checkout stalls, and your hosting panel reports repeated CPU, RAM, Entry Processes, or I/O limit violations. At this stage, the bottleneck is often the shared hosting platform rather than the website itself.
Start by measuring TTFB correctly. Test the homepage, category pages, product pages, search results, shopping basket, user account pages, and other dynamic content several times throughout the day.
curl -o /dev/null -s -w \
"DNS: %{time_namelookup}\nTCP: %{time_connect}\nTLS: %{time_appconnect}\nTTFB: %{time_starttransfer}\nTotal: %{time_total}\n" \
https://example.com/
If TTFB remains around 200–300 ms in the morning but consistently rises to 800–1500 ms during peak hours, compare the results with a static asset such as an image or CSS file. If static files load immediately while HTML generation is delayed, the bottleneck is usually PHP, the database, or object caching.
Next, review your CloudLinux statistics. Check CPU, RAM, Entry Processes, NPROC, I/O, and IOPS. Occasional spikes are normal, but if the same limits are reached every day, PHP requests begin waiting for available workers and visitors experience progressively longer response times.
Then inspect the logs. Look for upstream timed out, server reached pm.max_children, Allowed memory size exhausted, Maximum execution time exceeded, and HTTP 503 or 504 errors. When these coincide with high TTFB and CloudLinux limit violations, the hosting environment has become the limiting factor rather than a single plugin or script.
Also consider whether your hosting plan provides the tools needed to investigate the problem. Effective optimisation often requires access to the MySQL or MariaDB slow query log, the PHP-FPM slow log, PHP-FPM settings, OPcache, Redis, and Nginx or Apache configuration. Without them, identifying the bottleneck becomes much more difficult.
If console access is available, verify Redis:
redis-cli ping
The expected response is:
PONG
Without object caching, applications repeatedly execute identical SQL queries that could be served directly from memory. On WooCommerce, Moodle, CRM systems, and large B2B platforms, this quickly affects search, product filtering, shopping baskets, user accounts, and the administration interface.
Finally, ask whether you can actually fix the problem. If PHP-FPM limits, database performance, Redis, or web server configuration cannot be changed, optimisation has reached the limits of the hosting platform rather than the application.
The investigation is complete once you have compared TTFB throughout the day, analysed CloudLinux resource usage, reviewed web server and PHP logs, confirmed Redis availability, checked the database and PHP-FPM slow logs, and verified whether Nginx or Apache can be configured. If the root cause is clear but the required settings remain inaccessible, the project has reached the practical limits of shared hosting. At that point, a Linux VPS becomes valuable because it gives you the control needed to remove those bottlenecks rather than simply observe them.
Optimising Nginx and PHP-FPM for Dynamic Websites
Static assets rarely make a website slow. CSS, JavaScript, images, and fonts are usually delivered quickly. The real delay occurs while the server generates HTML. Product pages, shopping baskets, user accounts, and admin dashboards require PHP execution and database queries before the first byte reaches the browser.
Start by confirming that page generation is responsible for the delay rather than network latency or static file delivery.
curl -o /dev/null -s -w \
"TTFB: %{time_starttransfer}\nTotal: %{time_total}\n" \
https://example.com/product/
Then compare it with a static asset.
curl -o /dev/null -s -w \
"TTFB: %{time_starttransfer}\nTotal: %{time_total}\n" \
https://example.com/images/logo.webp
If the image loads immediately while HTML generation is slow, the bottleneck is usually PHP-FPM, the database, or the application.
Next, check whether PHP-FPM has enough available workers.
ps -ylC php-fpm --sort=rss
or
ps aux | grep php-fpm
If running processes regularly reach pm.max_children, new requests are waiting for free workers.
Review the PHP-FPM pool configuration, usually located in:
/etc/php/*/fpm/pool.d/
/etc/php-fpm.d/
Pay particular attention to pm.max_children and pm.max_requests. A low pm.max_children value quickly creates request queues on busy websites, while pm.max_requests helps recycle long-running workers and prevents gradual memory growth.
Estimate the average memory usage of a PHP worker:
ps --no-headers -o rss -C php-fpm | \
awk '{sum+=$1} END {print sum/NR/1024 " MB"}'
Then calculate pm.max_children using the RAM available after MySQL or MariaDB, Redis, Nginx, the operating system, and other services, leaving sufficient free memory for filesystem cache and workload spikes.
Enable the PHP-FPM slow log:
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
After restarting PHP-FPM, requests taking longer than five seconds are recorded together with the code responsible for the delay. This usually identifies the exact plugin, middleware, SQL query, or external API responsible for poor performance.
Also inspect the Nginx error log:
/var/log/nginx/error.log
Messages such as upstream timed out, connect() failed, recv() failed, or upstream prematurely closed connection usually indicate communication problems between Nginx and PHP-FPM. If the Nginx log is clean while the PHP-FPM slow log continues to report slow requests, the bottleneck is more likely to be the application or database.
After making changes, repeat the measurements. Confirm that pm.max_children is no longer exhausted, the slow log records fewer requests, and TTFB remains stable under normal load.
The optimisation is complete when PHP requests no longer queue for workers, the PHP-FPM slow log reports few or no long-running requests, the Nginx log contains no FastCGI communication errors, and TTFB remains consistent. At that point, you can decide whether the next improvement should focus on Redis, the database, or the application itself.
How to Enable Redis Object Cache or Memcached
Many administrators blame MySQL when the database is simply repeating the same work. Every page request retrieves the same settings, menus, widgets, user roles, and other frequently used objects. Under load, the database spends more time repeating identical queries than processing new ones.
Redis and Memcached reduce this workload by storing frequently requested data in memory instead of querying MySQL or MariaDB repeatedly. On WooCommerce, Moodle, Drupal, Magento, Laravel, and large WordPress websites, this can eliminate thousands of repeated SQL queries and significantly reduce database load.
Start by confirming that repeated queries are the problem. On WordPress, use Query Monitor. For other applications, enable the MySQL or MariaDB slow query log. If pages repeatedly execute hundreds of identical queries, object caching is likely to help.
Install Redis.
On Ubuntu:
sudo apt install redis-server
On AlmaLinux or Rocky Linux:
sudo dnf install redis
Verify that the service is running:
systemctl status redis
or
redis-cli ping
The expected response is:
PONG
Next, enable Redis in the application. On WordPress, the Redis Object Cache plugin should display Connected or Connected and enabled. Otherwise, WordPress continues querying MySQL directly.
Confirm that the cache is actually being used:
redis-cli INFO stats
Monitor keyspace_hits and keyspace_misses while repeatedly loading the same page. If keyspace_hits grows much faster, Redis is serving cached data correctly. If not, review the CMS integration or cache configuration.
You should also check memory usage:
redis-cli INFO memory
Very low memory consumption on an active website usually means little data is being cached.
Finally, compare performance before and after enabling Redis. Query Monitor should report fewer SQL queries and lower database execution time, while repeated TTFB measurements should become lower and more consistent.
curl -o /dev/null -s -w \
"TTFB: %{time_starttransfer}\n" \
https://example.com/
Run the test several times because the first request usually populates the cache. If SQL query counts, TTFB, and keyspace_hits remain almost unchanged, the application is probably not using object caching despite Redis being installed.
Memcached can be tested in a similar way, although Redis is generally preferred because of its broader feature set and wider CMS support.
The implementation is complete when Redis responds correctly, the application actively uses cached objects, repeated page requests execute fewer SQL queries, keyspace_hits consistently exceed keyspace_misses, and both TTFB and page generation become faster and more consistent. At that point, the database is no longer repeating the same work for every request.
How to Check the Network Performance of Your VPS
Sometimes a server generates HTML in 150–200 ms, PHP-FPM has no worker queues, Redis is active, and the database responds quickly, yet the website still feels slow. In such cases, the bottleneck is often the network layer. HTML is delivered promptly, while images, CSS, JavaScript, and other static assets download much more slowly than expected.
Start by confirming that the delay occurs during file delivery rather than page generation. Open Developer Tools, switch to the Network tab, disable browser cache, reload the page, and sort requests by duration. If HTML arrives quickly while static assets are delayed, investigate the network rather than PHP or the database.
Check which HTTP protocol is being used.
curl -I --http2 https://example.com
If supported, verify HTTP/3 as well.
curl -I --http3 https://example.com
If HTTP/3 is unavailable, review your Nginx, Apache, or reverse proxy configuration.
Next, confirm that compression is enabled.
curl -I https://example.com
Look for Content-Encoding: gzip or Content-Encoding: br. Without compression, HTML, CSS, and JavaScript consume significantly more bandwidth.
Also review the total page size in Developer Tools. Oversized images, unnecessary JavaScript, or background videos can make pages slow regardless of server performance.
Measure download throughput using a large file.
curl -o /dev/null -s -w \
"Download: %{speed_download} bytes/sec\nTotal: %{time_total}\n" \
https://example.com/testfile.iso
Use a file of at least 200–500 MB. Stable throughput usually indicates a healthy network path, while large fluctuations or repeated stalls suggest bandwidth, storage, or web server problems.
Then inspect network utilisation with:
iftop
or
vnstat
If bandwidth remains close to the interface limit during user complaints, background transfers such as backups or synchronisation may already be consuming most of the available capacity.
It is also worth checking HTTP keepalive, since repeated TCP and TLS handshakes increase page load time when many assets are requested.
Finally, decide whether the project actually needs a CDN. For local audiences, a properly configured VPS often delivers static content almost as quickly as a CDN. For international visitors, however, a CDN can significantly reduce latency by serving assets from nearby edge locations.
The network layer is properly configured when HTML is delivered quickly, HTTP/2 or HTTP/3 and gzip or Brotli are enabled, page size remains reasonable, large files transfer at stable speeds, network utilisation stays below saturation, and static assets load without unnecessary delays. If performance problems remain after these checks, the bottleneck is more likely to be the application, database, or external services than the VPS network itself.
How to Choose a Linux KVM VPS for Better Website Performance
Many people choose a VPS by comparing CPU cores, RAM, and NVMe storage. These specifications matter, but website performance is often limited by software configuration rather than hardware. If you cannot tune PHP-FPM, enable Redis, optimise Nginx, analyse slow query logs, or configure OPcache, adding more CPU or memory may produce little improvement.
Before ordering a VPS, identify what is actually limiting your website. Use previous diagnostics to determine whether delays are caused by PHP-FPM saturation, repeated SQL queries, high TTFB during peak traffic, missing object caching, or hosting restrictions that prevent you from adjusting server settings. These findings are far more valuable than visitor numbers or hardware specifications.
Next, evaluate the platform by the level of control it provides. A suitable VPS should allow you to configure PHP-FPM, Nginx or Apache, Redis or Memcached, OPcache, MySQL or MariaDB, inspect logs, enable slow query logging, and use technologies such as HTTP/2, HTTP/3, and Brotli. If every configuration change depends on technical support, optimisation quickly becomes slow and restrictive.
Think beyond today’s requirements as well. Traffic may increase, developers may introduce Redis, Elasticsearch, Docker containers, scheduled jobs, or newer PHP versions. A well-chosen VPS should support these changes without forcing another migration a few months later.
Diagnostic capabilities are just as important as hardware. Access to PHP-FPM, Nginx, MySQL or MariaDB logs, performance metrics, slow logs, and tools such as htop often contributes more to solving performance problems than additional processor cores.
The selection process becomes much simpler if you follow a logical sequence. First, identify the real bottlenecks affecting performance. Then confirm that the VPS allows you to configure the components responsible for them. Finally, make sure the platform can continue supporting the application as it grows over the coming years without requiring major architectural changes or another migration. This approach is usually far more effective than simply choosing the largest VPS available.
The evaluation is complete when the chosen Linux KVM VPS provides full administrative control over the software stack, supports modern optimisation technologies, offers comprehensive diagnostic tools, and allows resources to scale without significant operational restrictions.
CPU cores and RAM determine how much computing capacity is available, but real website performance depends on how efficiently that capacity is used. The best Linux KVM VPS is therefore not the one with the largest specifications, but the one that gives you complete control over the server environment, making it possible to eliminate bottlenecks, reduce TTFB, and maintain predictable performance as the project grows.






