September 23, 2026 / WordPress Tutorials

WordPress Hosting Requirements: How Much Server You Need

Quick answer

The official WordPress hosting requirements are PHP 8.3 or greater, MariaDB 10.11+ or MySQL 8.0+, and HTTPS. Every host on the market meets that. What actually decides whether your site stays up is capacity: PHP workers, memory per worker, and database CPU, sized against concurrent uncached requests rather than monthly pageviews.

Search for wordpress hosting requirements and you get the same paragraph from twenty different pages: a PHP version, a MySQL version, a note about HTTPS. All correct, all useless, because no host sold in the last five years fails that list. Meeting the requirements is table stakes. It tells you nothing about whether your site will survive a Black Friday hour or a bot crawling your search results.

There are two questions buried in that one phrase. The first is what WordPress technically needs to boot. That has a short official answer and it gets one section here. The second is how much server your particular site needs, which is the question you actually came with, and which almost nobody answers because the honest answer requires arithmetic.

This post does the arithmetic. It also makes a claim you will not like if you have just been told to upgrade your plan: most WordPress sites that are told they need more server are running a cache that is not working.

What are the official WordPress hosting requirements?

WordPress officially requires PHP 8.3 or greater, MariaDB 10.11+ or MySQL 8.0+, and HTTPS on every install, with Apache or Nginx recommended as the web server. That is the whole list, published on the WordPress.org requirements page, and it has not been a meaningful filter on hosting choice for a long time.

ComponentOfficial requirementWhat WordPress will still run onWhat you should actually be on
PHP8.3 or greater7.4+8.3 or 8.4, ideally with OPcache enabled
DatabaseMariaDB 10.11+ or MySQL 8.0+MySQL 5.5.5+MySQL 8.0+ or MariaDB 10.11+ on its own CPU allocation
HTTPSRequired for every installTechnically boots without itTLS terminated at the edge, HTTP/2 or HTTP/3
Web serverApache or Nginx recommendedAnything that speaks PHPNginx or LiteSpeed with a page cache in front of PHP
Requirements and legacy-version notes as published on wordpress.org/about/requirements/.

The PHP version gap most articles skip

WordPress will still run on PHP 7.4, and PHP 7.4 stopped receiving security fixes years ago. Those two facts sit next to each other on the official requirements page, which explicitly warns that the legacy versions have reached end of life and may expose your site to vulnerabilities. Plenty of hosts read the “still runs on” line and stop there.

Check the gap against the source. PHP’s own supported versions page gives each branch two years of active support and two more of security-only fixes. As of the second half of 2026, 8.4 and 8.5 are in active support, 8.3 has moved past its active window, and 8.2 is in security-only maintenance with its end date approaching. Everything older than 8.2 receives nothing from php.net at all.

So the practical floor is not “whatever WordPress boots on”. It is “a branch php.net still patches”. If your host’s control panel still offers 7.4 as the default, that is not a compatibility feature. That is a maintenance signal, and it should weigh on your decision more than the price does. Our comparison of WordPress hosting providers covers who keeps current and who does not.

The PHP settings and extensions that actually break things

Six PHP settings cause the overwhelming majority of “my site is broken” tickets, and none of them appear on the official requirements list. You arrive at these with a symptom, not a setting name, so here they are mapped the way you meet them.

Setting or extensionSymptom you actually seeSane value
memory_limitWhite screen on a page with many blocks, “Allowed memory size exhausted” in the error log, importers dying midway256M for most sites, 512M for WooCommerce and page builders
max_execution_timeBackups, imports and bulk edits stop partway with no error message120s for web requests, higher or unlimited for CLI
upload_max_filesize“The uploaded file exceeds the upload_max_filesize directive” on media upload64M or more
post_max_sizeLarge uploads fail silently even though upload_max_filesize looks fineEqual to or larger than upload_max_filesize
max_input_varsA long menu, a large form or a theme options page silently drops everything past a certain point on save3000 minimum, 5000+ for big menus and form plugins
curl, mbstring, gd or imagick, zip, intlFailed updates, broken thumbnails, mangled accented characters, license checks that never connectAll present; see the hosting handbook list
Extension names as listed in the Make WordPress hosting handbook; values are practical defaults, not official minimums.

The Make WordPress hosting handbook is the primary source here. It lists only json and mysqli as strictly required, then names curl, dom, exif, fileinfo, hash, imagick, intl, mbstring, openssl, xml and zip as highly recommended, plus one caching extension from apcu, memcached, opcache or redis. Treat “highly recommended” as required in practice: plugins assume them.

Watch out

max_input_vars fails without an error. A menu with 90 items saves the first 60 and drops the rest, and WordPress reports success. If a large menu, a WooCommerce attribute set or a form builder keeps losing entries on save, this is the cause roughly every time.

Memory is the one setting you can raise from WordPress itself. Add this to wp-config.php above the “That’s all, stop editing” line. The first constant covers front-end requests, the second covers admin and cron, which need more. Both are documented in the wp-config.php API reference.

define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

One caveat: WordPress cannot exceed the PHP memory_limit your host sets. If PHP is capped at 128M, setting 512M in wp-config achieves nothing. Check the real value in Tools then Site Health then Info then Server before you assume the constant worked.

Cached and uncached requests are completely different workloads

A cached page and an uncached page cost your server amounts that differ by two or three orders of magnitude, which is why monthly pageviews are a near-useless sizing input. A cached hit is a file read or a memory read: the web server returns bytes it already has and PHP never wakes up. An uncached request boots PHP, loads WordPress core, initialises every active plugin, runs dozens of database queries, renders a template, then throws it all away.

Two sites with identical traffic graphs can therefore sit at completely different points on the load curve. The only number that sizes a plan is concurrent uncached requests. Everything else is vanity.

What makes a request uncacheable:

  • Logged-in users. Any session cookie normally bypasses the page cache entirely, so a membership site can have a 0% hit ratio on its most-visited pages.
  • Carts and checkout. Cart contents, shipping calculations and totals are per-visitor by definition.
  • Search. Every ?s= query is a fresh full-text database query, which is exactly why crawlers hitting search URLs flatten small servers.
  • Personalised content: geo-targeted blocks, “recently viewed”, A/B tests, dynamic pricing.
  • POST requests. Comments, form submissions, add-to-cart, and admin-ajax calls never come from cache.
  • Admin work. Every wp-admin page load is an uncached PHP request, and a bulk product edit is dozens of them.

PHP workers: the arithmetic that actually sizes your plan

A PHP worker is one PHP-FPM process that can handle exactly one request at a time, from first byte of the request to last byte of the response, and your uncached concurrency is simply the number of workers divided by your average uncached response time. Hosts often bury this number, or express it as “you may have up to N concurrent PHP processes”. It is the single most important line on a plan page.

The formula: uncached requests per second = workers / average response time in seconds.

Worked example, stated assumptions, no measurements involved. Take a plan with 4 PHP workers. On a well-tuned blog where an uncached page renders in 250ms, each worker completes 4 requests per second, so 4 workers absorb 16 uncached requests per second. That is comfortable for almost any editorial site, because the cached traffic never touches PHP at all.

Now the same 4 workers on a WooCommerce store where checkout, cart fragments and account pages average 1.5 seconds. Each worker now completes 0.67 requests per second, so the same plan supports about 2.7 uncached requests per second. The pageview count has not changed. The capacity has fallen by a factor of six, purely because the requests got slower and stopped being cacheable.

Six times slower responses means six times less capacity on identical hardware. Response time is a capacity multiplier, not a user-experience nicety.

When demand exceeds that number, requests queue. Queueing is invisible at first: pages just feel slower, because time in the queue is added to every response. Push further and the queue hits its limit, and the web server returns 502 or 504 while your server CPU sits at a modest percentage, which is the detail that confuses everybody. You are not out of CPU. You are out of workers.

This is why a bot crawling /?s= URLs at 5 requests per second can take down a store that handles its human traffic without complaint. Those requests are uncacheable, slow, and database-heavy, and they hold workers hostage while real customers queue behind them.

How much hosting each type of WordPress site actually needs

Sizing follows from the dominant workload, not the traffic total, so the useful way to read this table is to find the row whose workload description matches yours and then look at the constraint column. That constraint is the resource to buy more of. Everything else on the plan page is noise.

Site profileDominant workloadReal constraintTier that fitsFirst thing that breaks
Personal blogAlmost entirely cached readsNone, realistically; bandwidth at mostCheapest shared plan with current PHPNothing, until a plugin adds an uncached widget to every page
Business or brochure siteCached reads plus contact form POSTsMemory per worker (page builders are heavy)Shared or entry cloud, 256M+ memoryWhite screen on the page-builder editor
Content site with real trafficHigh cached volume, spikyCache hit ratio and edge bandwidthEntry cloud plus a CDNOrigin swamped when the cache purges after a publish
Membership or LMSLogged-in, so effectively 100% uncachedPHP workersMid cloud, 8+ workers, object cache mandatory504s at course-release time while CPU looks idle
Small store (under ~50 orders/day)Mixed; catalogue cached, cart and checkout notPHP workers and database CPUMid cloud with Redis object cacheCheckout timing out during a promotion
Busy storeSustained uncached writes and order queriesDatabase CPU, then disk I/ODedicated database resources or managed WooCommerce tierAdmin order screens crawling while the shop front stays fine
Multisite networkMany small sites, many cron jobs, huge table countDisk I/O and database connectionsVPS or dedicated with tuned MySQLRandom slow queries and connection-limit errors at cron o’clock
Profiles are illustrative categories, not benchmark results. Match your workload shape, not your pageview count.

Note what is missing from the constraint column: raw CPU cores. Cores matter for the busy-store and multisite rows, and barely anywhere else. If you are being upsold on vCPUs for a membership site, the person selling has not read the workload. Our breakdown of what managed WordPress hosting actually buys you is the place to weigh whether the premium is worth it for your row.

Your database is a more likely culprit than your server size

A WordPress database gets slow in five predictable ways, and all five are free to fix while a bigger plan is not. Every uncached page load pays these costs on every request, which is why database bloat feels exactly like insufficient hardware.

  • Autoloaded options. Every option marked for autoload is pulled into memory on every single request. Plugins that store license blobs, cached API responses or entire settings trees here can push the autoload payload into megabytes.
  • Post revisions. Unlimited by default. A long-running editorial site can hold more revision rows than real posts.
  • Orphaned postmeta. Deleted posts and removed plugins leave meta rows behind, and postmeta is usually the largest table in the database.
  • Transients that never expire. Without a persistent object cache, transients land in wp_options, and expired ones are only cleaned opportunistically.
  • Plugin log tables. Security scanners, form submissions, redirect logs and analytics plugins write unbounded tables that nobody ever prunes.

Check the autoload payload first, because it has the best ratio of effort to reward. Run this over WP-CLI, adjusting the table prefix if yours is not wp_:

wp db query "SELECT COUNT(*) AS autoloaded_rows,
  ROUND(SUM(LENGTH(option_value))/1024/1024, 2) AS autoload_mb
  FROM wp_options WHERE autoload NOT IN ('no','off','auto-off');"

# then find the worst offenders
wp db query "SELECT option_name, ROUND(LENGTH(option_value)/1024, 1) AS kb
  FROM wp_options WHERE autoload NOT IN ('no','off','auto-off')
  ORDER BY LENGTH(option_value) DESC LIMIT 20;"

Anything under roughly 300KB of autoloaded data is unremarkable. Past about 1MB you are paying a real cost on every uncached request, and the second query will usually name one or two plugins responsible for most of it. Flip those options to non-autoloaded or remove the plugin. Neither action costs a hosting upgrade.

Before you upgrade: capacity problem or caching problem?

A capacity problem and a broken cache present identically from the outside, which is why so many people buy hardware they did not need. Both look like a slow site under load. The difference is that one costs money every month and the other is usually a configuration line. Establish which you have before you touch the plan page.

Step 1: compare cached and cache-busted TTFB

Time to first byte on a cached URL against a deliberately cache-busted one tells you where the time goes. Run both from the same machine, several times each:

curl -o /dev/null -s -w "cached ttfb: %{time_starttransfer}s\n" \
  https://example.com/

curl -o /dev/null -s -w "busted ttfb: %{time_starttransfer}s\n" \
  "https://example.com/?nocache=$(date +%s)"

If the cached figure is small and the busted figure is large, your cache is working and your PHP layer is slow. If the two are similar and both large, your cache is not serving anything and you have a caching problem wearing a capacity costume.

Step 2: confirm a HIT, do not assume one

A caching plugin being active is not evidence that it is returning cached pages. Read the response headers and look for an explicit hit:

curl -sSI https://example.com/ | grep -i -E \
  'x-cache|cf-cache-status|x-litespeed-cache|x-proxy-cache|age|cache-control|set-cookie'

A cf-cache-status: DYNAMIC or a missing hit header on a page that should be static means PHP rendered that response. A set-cookie on an anonymous page is worse: it usually means something is stamping a cookie on every visitor, and most cache layers refuse to store a response that sets one. That single line can disable caching for your entire audience, which is the failure mode the Cache Inspector in the WPColt toolbox exists to surface, and it is covered in detail in our writeup on diagnosing Cloudflare cache bypasses.

Step 3: check the object cache is connected

A Redis or Memcached object cache that has silently fallen back to the database is one of the most expensive invisible failures in WordPress, because every uncached request quietly returns to hammering MySQL while the plugin still shows as installed. Tools then Site Health then Info then Database will tell you whether a persistent object cache is in use, and our guide to tracking down Redis object cache misses covers the cases where it reports connected and still is not helping.

If you run a full-page reverse proxy in front of a caching plugin, the two layers can also fight each other and cancel out. Our notes on running Varnish alongside WP Rocket cover the combinations that work and the ones that produce a permanent MISS.

When to actually upgrade, and what to try first

Upgrade when you can name a measurable symptom and point at the specific resource it exhausts, and not before. Each trigger below has a cheaper fix that resolves it more often than the upgrade does.

Measurable symptomResource to increaseCheaper fix to try first
502 or 504 errors while CPU sits lowPHP workersCut average uncached response time; block bots hitting search and filter URLs
Cached TTFB fine, busted TTFB over 1.5sCPU clock speed or PHP workersEnable a persistent object cache; audit autoloaded options
Both cached and busted TTFB slowNothing yetFix the cache; this is not a hardware problem
“Allowed memory size exhausted” in logsMemory per workerRaise WP_MEMORY_LIMIT; find the plugin loading everything into memory
Admin slow, front end fineDatabase CPUPrune revisions, orphaned postmeta and plugin log tables
Site fine until you publish, then origin load spikesEdge cache coverageStop full-site cache purges on publish; purge selectively
Checkout times out but catalogue is fastPHP workers plus database CPUDisable cart fragments where unused; move sessions to the object cache
Disk-heavy backups slow the site every nightDisk I/OMove backups off-peak and off-server
Symptom-to-resource mapping. Work the third column before the second.

Mistakes that put people on plans they do not need

Four specific errors account for most over-buying, and each one has a concrete consequence you can check for today.

  • Sizing on monthly pageviews. Consequence: you buy a plan rated for 500,000 visits and still get 504s, because your 30,000 logged-in sessions were the entire workload and nobody counted them.
  • Treating “caching plugin installed” as “caching working”. Consequence: months of paying for capacity to render pages that should have been served from disk. Verify with headers, not with the plugin dashboard.
  • Purging the entire cache on every publish. Consequence: a content site with good hit ratios drops to zero cached pages several times a day, and every purge sends full traffic to PHP. Purge the post, its archives and the homepage instead.
  • Leaving WooCommerce cart fragments running site-wide. Consequence: every page on the site fires an uncached admin-ajax request, so even your cached pages generate PHP work. This alone can double worker consumption on a store.

Pro tip

Before you compare plans, write down three numbers: your PHP worker count, your average uncached response time, and your cache hit ratio. If you cannot fill in all three, you are not ready to choose hosting. You are ready to instrument. Several of the quick wins in our list of tips to make your website run faster move the second number more than a plan upgrade would.

The verdict on WordPress hosting requirements

Most WordPress sites are over-hosted and under-cached, and the fix is almost never the plan page. The official requirements are a formality that any current host clears. Capacity is the real question, and capacity is decided by concurrent uncached requests, worker count and response time, in that order.

If you run a blog, a brochure site or a content site, buy the cheapest plan on a PHP branch php.net still patches, put a CDN in front of it, and spend the saved money on nothing at all. Your constraint is cache correctness, not hardware. Upgrading before you have confirmed a cache HIT is buying a solution to a problem you have not diagnosed.

If you run a membership site, an LMS or a store, ignore visit allowances entirely and shop on PHP workers and database resources. Insist on a persistent object cache. Ask a prospective host for the worker count in writing, and if they will not give you a number, that is your answer about how much of your workload they have thought about.

And if you are currently being told to upgrade, spend twenty minutes on the diagnosis section above first. Two curl commands and a look at the autoloaded options table resolve this more often than a credit card does.

Frequently asked questions

What PHP version does WordPress require in 2026?

WordPress.org states PHP 8.3 or greater as the requirement, while noting that WordPress will still run on PHP 7.4 and above. That legacy floor is not safe advice: php.net only maintains branches for four years, so aim for 8.3 or 8.4 at minimum and treat anything older than 8.2 as unpatched.

How many PHP workers does my WordPress site need?

Divide your peak concurrent uncached requests by the number of requests one worker can finish per second, which is one divided by your average uncached response time. A blog rendering in 250ms gets four requests per second per worker. A store averaging 1.5 seconds gets 0.67. Most cached sites need very few workers.

Is shared hosting enough for WordPress?

For a blog, a brochure site or a content site behind a working CDN, yes. Those workloads are almost entirely cached reads, so PHP is barely involved. Shared hosting fails on logged-in workloads: membership sites, learning platforms and stores keep PHP busy on every request and need guaranteed worker counts instead.

Why is my site slow when the server CPU is low?

That pattern almost always means PHP worker exhaustion rather than a CPU shortage. Requests queue while waiting for a free worker, so response times climb and eventually the web server returns 502 or 504 errors, all while the CPU graph looks calm. Reduce uncached response time or increase worker count.

How much memory limit does WordPress need?

256M covers most sites and 512M is sensible for WooCommerce or a page builder. Set WP_MEMORY_LIMIT and WP_MAX_MEMORY_LIMIT in wp-config.php, but remember WordPress cannot exceed the PHP memory_limit your host configures. Check the real value under Tools, Site Health, Info, Server before assuming the constant took effect.

Does WooCommerce need more hosting than a normal WordPress site?

Yes, but not because of traffic. Carts, checkout, account pages and admin order screens cannot be cached, so a store with modest pageviews can generate far more PHP and database work than a blog with ten times the traffic. Size on PHP workers and database CPU, and run a persistent object cache.

Why does my WordPress menu lose items when I save it?

That is the max_input_vars limit truncating the POST request. PHP silently discards form fields past the configured limit and WordPress reports a successful save, so the extra menu items simply vanish. Raise max_input_vars to 3000 or higher. The same limit breaks large form builders and theme option panels.

How do I check whether my page cache is actually working?

Read the response headers rather than trusting the plugin dashboard. Request a public page with curl and look for an explicit hit indicator such as x-cache, cf-cache-status or x-litespeed-cache. A DYNAMIC status, a missing hit header, or a set-cookie on an anonymous page means the response came from PHP.