How to Diagnose and Fix Server-Side Core Web Vitals Issues
Quick Summary
Many website owners begin improving Core Web Vitals by compressing images, removing JavaScript, or changing the site's theme. Sometimes that works, but not always. Support teams regularly see cases where several days of front-end optimisation produce almost no improvement in PageSpeed because the real bottleneck is much earlier in the request lifecycle. The server takes too long to generate the page, PHP spends excessive time processing requests, the database is overloaded, Redis is not being used, static assets are served without proper caching, or compression is disabled entirely.
Before making any changes, identify where the delay actually occurs. If Google PageSpeed Insights reports a high Initial Server Response Time and Chrome DevTools shows that most of the request time is spent in the Waiting (TTFB) phase on the Network tab, the problem is unlikely to be in the front end. Start by examining server response time, PHP-FPM performance, database execution, Redis object caching, HTTP cache headers, HTTP/2 or HTTP/3 support, and your SSL configuration. Only after these components have been verified should you move on to optimising images, CSS, and JavaScript.
This approach prevents one of the most common optimisation mistakes. Many administrators spend hours reducing image sizes to improve LCP while the server still needs more than a second just to generate the initial HTML document. Until that delay is removed, most front-end optimisations deliver far less benefit than expected. When working on Core Web Vitals, the first priority should always be making sure the server generates and delivers HTML as quickly as possible. Only then does it make sense to optimise everything the browser loads afterwards.

During performance investigations at Era.Host, this order of diagnosis often identifies the real cause within minutes, avoiding hours spent optimising resources that were never responsible for the poor Core Web Vitals scores in the first place.
Article plan
- How to Measure TTFB and Determine Whether the Server Is the Problem
- How to Distinguish Network Latency from Slow Page Generation
- How to Improve LCP with Gzip or Brotli Compression
- How to Configure Cache-Control and Expires for Static Assets
- How to Enable Redis Object Cache for WordPress and Other CMS Platforms
- How to Check PHP-FPM and the Database When INP or TTFB Remain High
- How to Enable HTTP/2 and Verify the TLS Handshake
- How to Decide Whether Your Website Needs HTTP/3
- How to Choose a Hosting Package for Better Core Web Vitals
How to Measure TTFB and Determine Whether the Server Is the Problem
If Google PageSpeed Insights reports a slow Initial Server Response Time or poor LCP, don't start by changing your site's theme or compressing images. The first step is to identify where the delay actually occurs. In many cases, the browser spends a second or more simply waiting for the first byte of HTML. At that stage, CSS, JavaScript, images, and fonts have not even started loading. When that happens, the bottleneck is almost always on the server or within the application itself.
Start with Google PageSpeed Insights. If the report includes the recommendation Reduce initial server response time or shows an unusually high Initial Server Response Time, open the same page in Chrome DevTools. Go to the Network tab, disable the browser cache, reload the page, and select the initial HTML request. Open the Timing tab and look at the Waiting (TTFB) phase. This value shows how long the browser waited between sending the request and receiving the first byte of data from the server.
Next, measure TTFB directly with curl. This removes the browser, extensions, and DevTools interface from the equation, making it easier to assess the server itself.
curl -o /dev/null -s -w \
"DNS: %{time_namelookup}\n\
Connect: %{time_connect}\n\
TLS: %{time_appconnect}\n\
TTFB: %{time_starttransfer}\n\
Total: %{time_total}\n" \
https://example.com/
Review each value individually rather than looking only at the total time. time_namelookup measures DNS resolution, time_connect shows how long it takes to establish the TCP connection, time_appconnect measures the TLS handshake for HTTPS, time_starttransfer is the actual TTFB, and time_total is the complete request duration. If DNS, TCP, and TLS complete quickly but time_starttransfer is significantly higher, the delay is happening while the server is generating the page.
Do not limit testing to the homepage. Run exactly the same command against several URLs. Check the homepage, a product category, a product page, the login page, and a dynamic page such as search results or a filtered catalogue. Execute each test several times. If the homepage consistently returns a TTFB of 180–250 ms while product pages take 900–1200 ms, the problem is almost certainly in dynamic page generation rather than the network or hosting infrastructure.
If the numbers vary between tests, repeat the measurements at different times of day. Test during the morning, afternoon, and evening using the same URLs. Large fluctuations in TTFB often point to resource contention, an overloaded database, PHP-FPM process exhaustion, or scheduled background jobs consuming CPU and I/O during specific periods.
While testing, inspect the server logs at the same time. Open the Nginx error log and the PHP-FPM log, then look for messages such as upstream timed out, PHP slow log entries, or warnings that all PHP-FPM workers are busy. If those errors appear while TTFB is high, there is little value in optimising images or front-end assets until the HTML generation delay has been resolved.
The diagnosis is complete once you have measured TTFB using multiple methods and compared several page types. If time_starttransfer remains consistently high in both Chrome DevTools and curl, while static assets load quickly, the bottleneck is usually PHP execution, database performance, server-side caching, or the server configuration itself. Only after reducing that delay should you move on to optimising images, CSS, JavaScript, and the remaining factors that influence Core Web Vitals.
How to Distinguish Network Latency from Slow Page Generation
When a website starts responding slowly, it's easy to assume PHP or the database is to blame. In reality, the delay may occur before the server even begins generating HTML. Slow DNS resolution, a lengthy TCP connection, TLS handshake delays, or poor network routing can add hundreds of milliseconds before the application receives the request. Before optimising the wrong part of the stack, determine exactly where the time is being spent.
Start by measuring the request with curl. Run the following command against the homepage and save the results.
curl -o /dev/null -s -w \
"DNS: %{time_namelookup}\n\
Connect: %{time_connect}\n\
TLS: %{time_appconnect}\n\
TTFB: %{time_starttransfer}\n\
Total: %{time_total}\n" \
https://example.com/
Examine each timing separately. If time_namelookup is unusually high, investigate your DNS provider. If time_appconnect takes significantly longer than expected, inspect your TLS configuration, certificate chain, or SSL settings. If both values are low but time_starttransfer accounts for most of the delay, the server is spending too much time generating the page, and the investigation should move to PHP, the database, or application logic.
The next step is to compare static and dynamic content. Run the same TTFB test against a CSS file, an image, and the HTML page.
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\n" https://example.com/style.css
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\n" https://example.com/images/logo.webp
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\n" https://example.com/
Now compare the results. If the CSS file and image begin downloading almost immediately while the HTML page has a much higher TTFB, the network is performing normally and the delay starts after the request reaches the application. Common causes include slow PHP execution, expensive SQL queries, missing object caching, exhausted PHP-FPM workers, or resource-intensive background jobs.
If both static files and HTML respond slowly, continue with network diagnostics. Run traceroute or mtr from one or more locations if possible.
traceroute example.com
or
mtr example.com
Look for high latency, packet loss, or unstable routing. Repeat the same tests from different geographical locations using remote servers or external testing platforms. If every resource is slow regardless of file type or test location, the issue is more likely to be related to network connectivity, web server configuration, an overloaded physical host, or data centre infrastructure rather than the application itself.
At the same time, inspect the request breakdown in Chrome DevTools. Open the Network tab, select the HTML document, and compare the time spent in DNS Lookup, Initial Connection, SSL, Waiting (TTFB), and Content Download. The browser timeline should closely match the values reported by curl. If both tools indicate that the delay occurs during Waiting (TTFB), your investigation should focus on server-side processing rather than networking.
The diagnosis is complete once you have separated connection latency from page generation time. If static assets consistently respond much faster than dynamic HTML, continue investigating PHP, MySQL or MariaDB, Redis, PHP-FPM, and server-side caching. If every request is slow regardless of content type, resolve the network, TLS, web server, or infrastructure issues before spending time optimising the application itself.
How to Improve LCP with Gzip or Brotli Compression
When Google PageSpeed reports a poor LCP score, many administrators immediately start compressing images or deferring JavaScript. Quite often, the real bottleneck appears much earlier. The browser spends too long downloading the HTML, CSS, and JavaScript because the server either serves them uncompressed or uses an inefficient compression configuration. This is particularly noticeable on mobile devices and slower network connections, where a few hundred extra kilobytes can significantly delay the first screen from rendering.
Start by checking whether compression is enabled at all. If your server uses Nginx, review the configuration and verify that gzip or brotli is enabled. On Apache, make sure mod_deflate or mod_brotli is loaded and active. If compression is configured through .htaccess, confirm that the required directives are present. Compression should be applied to HTML, CSS, JavaScript, SVG, XML, and JSON responses. At the same time, verify that the server is not attempting to compress JPEG, PNG, WebP, AVIF, ZIP, MP4, or other formats that are already compressed. Recompressing these files rarely reduces their size and simply wastes CPU resources.
Once you have updated the configuration, validate it before restarting the web server. For Nginx, run:
nginx -t
If the configuration passes validation, reload or restart the service.
systemctl restart nginx
For Apache, first check the configuration:
apachectl configtest
If no errors are reported, restart Apache.
systemctl restart apache2
Do not stop after restarting the service. Confirm that browsers are actually receiving compressed responses. Open the site in Chrome, launch DevTools, switch to the Network tab, disable the browser cache, and reload the page. Select the HTML document, a CSS file, or a JavaScript file, then inspect the Headers section. Look for the Content-Encoding response header. Text-based resources should display either gzip or br. If the header is missing, the file is still being transferred uncompressed regardless of the server configuration.
Next, compare the amount of data being transferred. In DevTools, examine the Transferred and Resource Size columns. For HTML, CSS, and JavaScript, the transferred size should be noticeably smaller than the original resource size once compression is working. If both values remain almost identical, compression is either disabled or not being applied to the correct content types.
After enabling compression, repeat the same performance tests. Run Google PageSpeed Insights again and measure the page in DevTools using the same URL as before. Compare the loading time for the HTML document, CSS, and JavaScript files. If those resources download more quickly and the LCP score improves without changing images or the site's theme, the bottleneck was data transfer rather than PHP execution or browser rendering.
The configuration can be considered successful if HTML, CSS, JavaScript, SVG, XML, and JSON responses include the Content-Encoding: gzip or Content-Encoding: br header, transferred file sizes are smaller than the original resources, already compressed images and media are excluded from compression, and both PageSpeed Insights and DevTools show shorter download times for the resources that contribute to LCP. At that point, the server is delivering content more efficiently, allowing the browser to render the first screen sooner.
How to Configure Cache-Control and Expires for Static Assets
If Google PageSpeed repeatedly recommends Serve static assets with an efficient cache policy, don't assume the problem lies with your CMS or CDN. In many cases, the browser simply isn't being told how long it can cache CSS, JavaScript, images, fonts, and other static resources. As a result, returning visitors download the same files every time they open a page, while the server continues to process identical requests that could have been avoided.
Start by checking which cache headers your server is already sending. Open your website in Chrome, launch DevTools, go to the Network tab, and perform a full page reload. Select a CSS file, JavaScript file, image, or font, then inspect the Headers section. Look for the Cache-Control and Expires response headers. If they are missing, or if you see values such as no-cache or max-age=0, the browser has no choice but to request those files again on every visit, even if they rarely change.
The next step is to configure caching on the web server itself. For Nginx, add cache rules for static file types. For Apache, configure mod_expires together with mod_headers. If the project relies on .htaccess, make sure the relevant directives are actually being applied. Resources that use versioned filenames, such as style.8f4c21.css or app.2d71.js, can safely be assigned long cache lifetimes. Whenever the file changes, the filename or version string changes as well, causing browsers to download the updated version automatically instead of using an outdated cached copy.
Once the configuration has been updated, validate it before restarting the web server. For Nginx, run:
nginx -t
If the configuration is valid, restart the service.
systemctl restart nginx
For Apache, first verify the configuration.
apachectl configtest
If the test succeeds, restart Apache.
systemctl restart apache2
Now confirm that the changes are actually working. Open DevTools, go back to the Network tab, and load the same page twice. During the second load, check where the browser retrieves the static assets. CSS, JavaScript, images, and fonts should show disk cache or memory cache in the Size or Transferred column. Open the response headers again and verify that the server is returning the expected Cache-Control value with an appropriate max-age.
It is also worth checking the response directly with curl.
curl -I https://example.com/css/style.css
The response should include a valid Cache-Control header and, where applicable, an Expires header. If these headers are missing, browsers will continue requesting the file from the server regardless of any caching settings configured within the CMS.
The configuration can be considered successful if repeat page loads retrieve static assets from disk cache or memory cache, the server consistently returns the expected Cache-Control and Expires headers, and Google PageSpeed no longer reports inefficient browser caching. At that point, repeat visits require significantly less data transfer, page load times improve for returning users, and the server handles far fewer requests for files that have not changed.
How to Enable Redis Object Cache for WordPress and Other CMS Platforms
If Google PageSpeed reports a high Initial Server Response Time, the WordPress dashboard feels sluggish, or TTFB continues to increase despite low traffic, don't assume you need a larger server. In many cases, the real bottleneck is the database. Every page request forces the CMS to execute dozens or even hundreds of identical SQL queries, even though the results rarely change. This is particularly common in WordPress with WooCommerce, OpenCart, Drupal, and other dynamic platforms where menus, product catalogues, configuration data, and user information are repeatedly loaded from MySQL or MariaDB.
Start by confirming that Redis is installed and running. Connect to the server via SSH and check the service status.
systemctl status redis
If Redis is not installed, install it using your Linux distribution's package manager, enable it to start automatically during boot, and verify that the service enters the active (running) state after a reboot.
The next step is to connect your application to Redis. For WordPress, install the Redis Object Cache plugin, open its settings page, and enable object caching. For Laravel, configure Redis in the .env file, clear the configuration cache, and restart the application. For other CMS platforms and frameworks, enable the Redis cache driver in the application's cache configuration and verify that it replaces file-based caching or direct database lookups.
Do not assume the job is finished just because the Redis service is running. A common support issue is a Redis server that is healthy while the application continues querying MySQL because of an incorrect cache driver, a missing PHP Redis extension, connection failures, or object caching simply not being enabled. Until you confirm that the application is actively using Redis, the configuration is incomplete.
Begin the verification from the command line.
redis-cli ping
The expected response is:
PONG
Next, confirm that Redis is actually storing application data.
redis-cli info stats
Review the keyspace_hits and keyspace_misses counters. After browsing several pages, the number of cache hits should steadily increase. If the counters barely change, the application is probably bypassing Redis and continuing to query MySQL directly.
The next step is to compare database activity before and after enabling object caching. On WordPress, this is easy with Query Monitor. Open the same page with Redis disabled and note the number of SQL queries together with the page generation time. Then enable Redis Object Cache, clear the application cache, reload exactly the same page, and compare the results. Repeated database queries should decrease noticeably.
Now measure the page again using Chrome DevTools or curl and compare the TTFB with the previous test. If Redis is working correctly, HTML generation should become more consistent and the Waiting (TTFB) phase should decrease. At the same time, inspect the MySQL or MariaDB slow query log. After object caching has been enabled, repeated slow queries often become far less frequent.
The configuration can be considered successful if the Redis service is in the active (running) state, redis-cli ping returns PONG, keyspace_hits continues to increase during normal browsing, the CMS is demonstrably using Redis Object Cache, the number of SQL queries is lower than before, and TTFB for the same page becomes both shorter and more consistent. At that point, Redis is doing more than simply running as another service on the server. It is actively reducing database load and accelerating the generation of dynamic pages.
How to Check PHP-FPM and the Database When INP or TTFB Remain High
If Redis is already enabled, Gzip or Brotli compression is working, browser caching is configured correctly, and Google PageSpeed still reports a high TTFB or poor INP score, the bottleneck is likely deeper in the server stack. Support engineers often find that PHP workers remain busy for too long, request queues gradually build up, or a handful of expensive database queries block other requests from completing. From the user's perspective, the site simply feels slow, while the real cause lies in the server environment.
Start by checking the PHP-FPM service. Connect to the server via SSH and confirm that the service is running correctly.
systemctl status php-fpm
On Ubuntu, the service name may include the PHP version.
systemctl status php8.3-fpm
If the service is repeatedly restarting or reports a failed status, resolve that issue before continuing. Once PHP-FPM is running normally, inspect its recent log entries.
journalctl -u php-fpm -n 100
Look carefully for recurring messages such as:
server reached pm.max_children
upstream timed out
child exited
Allowed memory size exhausted
Each message points to a different problem. server reached pm.max_children means every PHP worker is busy and new requests are waiting in the queue. upstream timed out indicates that PHP could not finish processing before the web server timeout expired. Allowed memory size exhausted shows that PHP ran out of memory, while repeated child exited messages may indicate crashes or unstable processes.
The next step is to examine the PHP-FPM slow log. If it is not already enabled, configure slowlog and set a sensible request_slowlog_timeout value for the relevant PHP-FPM pool. Restart PHP-FPM, reproduce the slow operation, and inspect the log again. Open the same product page, perform the same catalogue search, or run the same import process that users report as slow. If the slow log repeatedly records the same PHP scripts, the bottleneck is no longer the server itself but the application code or one of its extensions.
Now move to the database. Open the MySQL or MariaDB slow query log and identify the queries consuming the most time. Look for expensive SELECT statements with multiple JOIN operations, large table scans, filesorts, or long-running UPDATE statements during imports. These queries can dramatically increase HTML generation time. Redis may reduce repeated database lookups, but it cannot compensate for poorly optimised SQL that must still be executed.
While reproducing the issue, monitor the server in real time. In one terminal window, run:
top
or
htop
In a second terminal, monitor storage performance.
iostat -x 1
Then monitor memory and process activity.
vmstat 1
Watch several metrics simultaneously while the slow operation is running. If CPU utilisation remains low but iowait becomes consistently high, the server is waiting on storage rather than processing requests. If swap usage starts increasing, the system no longer has enough physical memory for the workload. If one or more PHP processes remain active much longer than the others, the delay is usually caused by slow application code or expensive database queries.
Do not forget to inspect the web server log.
tail -100 /var/log/nginx/error.log
Repeated messages such as upstream timed out, connect() failed, or recurring PHP-FPM connection errors indicate that Nginx is spending an excessive amount of time waiting for the application to respond.
The investigation is complete once you can identify exactly where the delay occurs. If the PHP-FPM slow log consistently records the same scripts, the MySQL or MariaDB slow query log highlights the same SQL statements, pm.max_children is no longer being exhausted, swap remains unused, iowait stays low, and both the Nginx and PHP-FPM logs are free from repeated upstream timed out errors, you have identified the root cause. Only then should you decide whether the next step is optimising application code, improving database indexes, adjusting PHP-FPM settings, or increasing server resources.
How to Enable HTTP/2 and Verify the TLS Handshake
A website running over HTTPS is not necessarily using the connection efficiently. During performance investigations, it is common to find browsers opening multiple separate connections, CSS, JavaScript, and font files loading more slowly than expected, and Google PageSpeed reporting delays related to resource delivery. Before looking for problems in the application, verify that the server is actually using HTTP/2 and that the TLS connection is configured correctly.
Start by checking your web server configuration. If you are using Nginx, open the virtual host configuration and confirm that the HTTPS listener includes the http2 parameter.
listen 443 ssl http2;
If the server runs Apache, verify that the mod_http2 module is enabled and that the configuration contains the following directive.
Protocols h2 http/1.1
After making any changes, validate the configuration before restarting the service. For Nginx, run:
nginx -t
If no errors are reported, restart Nginx.
systemctl restart nginx
For Apache, first validate the configuration.
apachectl configtest
If the test succeeds, restart Apache.
systemctl restart apache2
The next step is to verify that the website is actually serving traffic over HTTP/2. Run the following command:
curl -I --http2 https://example.com
If the connection succeeds, the response should be served over HTTP/2. If the command fails or the server still responds using HTTP/1.1, check whether your installed web server version supports HTTP/2 and confirm that the feature has not been disabled by the TLS configuration.
Now verify the browser's behaviour. Open the website in Chrome, launch DevTools, switch to the Network tab, and enable the Protocol column if it is not already visible. Reload the page and inspect the requests for the HTML document, CSS, JavaScript, fonts, and images. They should all display h2 in the Protocol column. If you still see http/1.1, the browser is not using HTTP/2 despite the server configuration.
At the same time, inspect the TLS certificate. Click the padlock icon in the browser's address bar and confirm that the certificate is valid and trusted. Check that the complete certificate chain is installed correctly. An incomplete chain or certificate configuration issues can increase connection setup time and may even cause certificate validation failures for some clients.
It is also worth measuring the TLS handshake directly with curl.
curl -o /dev/null -s -w \
"TLS: %{time_appconnect}\n\
TTFB: %{time_starttransfer}\n" \
https://example.com/
Review the results carefully. If time_appconnect is significantly higher than expected while the remaining stages complete quickly, investigate the TLS configuration, OpenSSL version, certificate chain, supported cipher suites, and web server settings before looking elsewhere.
The configuration can be considered successful if Nginx or Apache validates without errors, curl --http2 confirms HTTP/2 support, Chrome DevTools shows the h2 protocol for page resources, the TLS certificate is trusted without warnings, and the TLS handshake completes quickly. At that point, you can be confident that HTTPS configuration is not introducing unnecessary latency and that the browser is using modern protocols to download page resources as efficiently as possible.
How to Decide Whether Your Website Needs HTTP/3
If Redis is already configured, PHP-FPM has been tuned, HTTP/2 is enabled, compression is working, and browser caching is correctly configured, yet some users still report slow page loads, don't rush to enable HTTP/3. Support engineers regularly see administrators expecting one new protocol to solve a performance problem when the real bottleneck is still HTML generation or slow database queries. HTTP/3 can reduce the impact of unstable network conditions, but it will not speed up slow PHP execution or compensate for an inefficient CMS.
Start by confirming that HTTP/2 is working correctly. Verify that the server is delivering content over HTTP/2, your TLS configuration is healthy, static assets are cached properly, Gzip or Brotli compression is enabled, and TTFB is already within an acceptable range. If server response time remains high, resolve that issue first. HTTP/3 is worth considering only after the server is generating pages quickly and the remaining delays occur during data transmission across the network.
The next step is to verify whether your infrastructure actually supports HTTP/3. If you use a CDN, open its management console and confirm that HTTP/3 support is enabled. If the website runs directly on a VPS, check the documentation for your web server and verify that your installed version of Nginx, OpenLiteSpeed, or another supported server includes HTTP/3 and QUIC support. At the same time, confirm that UDP traffic is permitted on port 443, as HTTP/3 relies on QUIC rather than TCP.
Once HTTP/3 has been enabled, verify that browsers are actually using it. Open the website in Chrome, launch DevTools, switch to the Network tab, and enable the Protocol column if it is not already visible. Reload the page several times. If the configuration is correct, the HTML document and most resources should display h3 as the protocol. If you continue to see h2 or http/1.1, the browser is still falling back to the previous protocol.
If your version of curl includes HTTP/3 support, perform an additional verification from the command line.
curl --http3 -I https://example.com
If the command succeeds and the server responds normally, HTTP/3 is available. If the connection cannot be established, check your web server configuration, confirm that QUIC support is enabled, and verify that your firewall allows UDP traffic on port 443.
The final evaluation should not be performed only from a wired office connection. HTTP/3 provides its biggest advantages on unstable or high-latency networks. Test the same page over a wired connection, a home Wi-Fi network, and a mobile network. Measure TTFB, total page load time, and overall responsiveness under each condition. If packet loss or fluctuating network quality has less impact, page loads become more consistent, and repeated retransmissions decrease without increasing TTFB, HTTP/3 is delivering a measurable benefit. If performance remains unchanged, the remaining bottleneck is most likely within the application or server rather than the transport protocol.
The deployment can be considered successful if Chrome DevTools reports the h3 protocol, curl --http3 connects successfully, HTTP/2 remains available as a fallback for clients without HTTP/3 support, and testing across mobile and unstable networks shows more consistent page loading without an increase in TTFB. At that point, HTTP/3 is improving content delivery rather than simply being another enabled feature in the server configuration.
How to Choose a Hosting Package for Better Core Web Vitals
After measuring TTFB, tuning PHP-FPM, enabling Redis, configuring HTTP/2 or HTTP/3, and setting up compression and browser caching, it usually becomes clear that website performance depends on much more than the CMS itself. At this stage, further optimisation is often limited by the capabilities of the hosting infrastructure. If your hosting platform does not support current PHP versions, Redis, high-performance NVMe storage, or flexible PHP-FPM configuration, maintaining consistently good Core Web Vitals becomes increasingly difficult regardless of how well the application is written.
Before you choose a hosting package, identify the limitations that are already affecting your project. If PageSpeed consistently reports a high TTFB, PHP-FPM regularly reaches its process limits, the database becomes the main source of latency, or Redis Object Cache is unavailable because of hosting restrictions, disk space is not the real issue. The platform itself has become the bottleneck, and that is what should be evaluated first.
Begin by reviewing the software environment. Confirm that the hosting plan supports current PHP releases and allows timely upgrades without long delays. Check whether Redis Object Cache is available, whether HTTP/2 and HTTP/3 are supported, whether the platform uses NVMe storage, and whether PHP settings can be adjusted when the application requires higher memory limits or longer execution times.
Next, evaluate the resources that have the greatest impact on Core Web Vitals. Do not focus only on CPU cores and RAM. Look at storage performance, database responsiveness, support for object caching, and whether the platform provides enough resources for PHP-FPM to handle concurrent requests efficiently. On dynamic websites, these components have a much greater influence on HTML generation speed and TTFB than raw storage capacity.
It is equally important to examine the operational capabilities of the platform. Check whether automatic backups are included, whether memory, CPU resources, or storage can be upgraded without migrating the website, whether server logs are accessible for troubleshooting, whether current versions of MySQL or MariaDB are available, and whether the hosting environment provides the tools needed to diagnose performance issues without relying on technical support for every investigation.
Before making the final decision, perform a practical assessment. Ask yourself a few questions. Does the hosting plan support Redis? Can you run the latest PHP version? Are HTTP/2 and HTTP/3 available? Does it use NVMe storage? Is there enough RAM for PHP-FPM, the database, and object caching? Can the server be scaled without migrating the project? Are automatic backups included? Can you access the logs and diagnostic tools needed to troubleshoot performance problems? If the answer to any of these questions is no, those limitations are likely to affect your Core Web Vitals as the project grows.
A well-chosen hosting package is defined not by the amount of disk space it offers, but by how effectively its infrastructure supports fast page generation and delivery. A platform that provides modern PHP versions, Redis, HTTP/2, HTTP/3, NVMe storage, a high-performance database environment, reliable backups, and straightforward scalability will help maintain strong Core Web Vitals not only when the site launches, but also as traffic, content, and application complexity continue to increase.


