Skip to content

Everything for WordPress, web development — and beyond

💡 How to reduce server load and speed up WordPress with Memcached

💡 How to reduce server load and speed up WordPress with Memcached

A WordPress site without caching resembles an engine that warms up from scratch at every traffic light. A visitor lands on a page, PHP assembles it from the ground up, hitting the database 30 to 60 times. Ten visitors simultaneously means three hundred queries. Fifty visitors create an avalanche that makes the server drop connections faster than you can finish typing a command in the console.

The problem is not WordPress itself. Dynamic page assembly is inherently wasteful by default; nearly every CMS works this way. The solution has been proven through years of operation on high-load projects: object caching in RAM via Memcached. A properly configured Memcached layer transforms a server that chokes on fifty concurrent users into a machine that handles hundreds without a single millisecond of hesitation in response time.

We will walk through the complete setup cycle: from installing the daemon to a load test that shows the difference in numbers. All commands have been tested on Ubuntu 22.04/24.04 and AlmaLinux 9, and are compatible with PHP 8.2-8.5.

💡 Quick overview:

  • Install the Memcached daemon and bind it to localhost for security
  • Compile the PHP memcached extension via PECL for your PHP version
  • Place the object-cache.php drop-in from Automattic into the wp-content directory
  • Install Batcache and configure advanced-cache.php for page caching
  • Check response headers via browser DevTools
  • Run a load test with k6 and compare results before and after

What is Memcached and why does your WordPress need it

Memcached is a daemon that stores data and objects in the server's RAM. Unlike file-based caching (WP Super Cache, W3 Total Cache, WP Rocket), which writes ready-made HTML to disk, Memcached operates one level lower: database query results, assembled menus, widgets, and site settings settle in RAM and can be retrieved in microseconds without reassembly.

In practice, the picture looks like this. A typical WordPress page without caching makes 30 to 60 queries to MySQL. With 50 concurrent visitors, the database receives one and a half to three thousand queries, and the CPU goes into failure mode. Memcached intercepts the overwhelming majority of these queries at the RAM level: the database rests, the CPU stays free, and the server responds instantly.

Technically, Memcached operates on key-value pairs. The key is a hash of the SQL query; the value is the serialized result. When WordPress assembles the same page again, it first asks Memcached, "Do you have this key?" and almost always receives a ready answer without a single disk access.

The technology emerged in 2003 within LiveJournal as a solution to extreme database load problems. Today, WordPress.com, Wikipedia, Twitter, and thousands of high-load projects run on Memcached. It is mature, stable, and predictable: exactly what production needs.

Installing the Memcached daemon

We will cover two main scenarios: Ubuntu (22.04/24.04) with apt and AlmaLinux / Rocky Linux 9 with dnf. Adapt the commands to your distribution.

On Ubuntu:

1sudo apt update && sudo apt install memcached libmemcached-tools -y

On AlmaLinux / Rocky Linux 9:

1sudo dnf install memcached libmemcached -y

After installation, the daemon starts automatically. Verify:

1systemctl status memcached

By default, Memcached listens on port 11211 on all network interfaces. This is a security hole: your cache is accessible to anyone who can reach that port from outside. Therefore, bind the daemon to localhost first.

Open the configuration file (/etc/memcached.conf on Ubuntu, /etc/sysconfig/memcached on AlmaLinux) and ensure that the line -l 127.0.0.1 is present and not commented out. Restart the daemon:

1sudo systemctl restart memcached

Building the PHP extension via PECL

The daemon alone will not speed up WordPress; you need a PHP client that teaches PHP to communicate with Memcached. Install the memcached extension (note: specifically memcached with the letter d, not memcache). The latter was removed from PHP starting with version 8.0 and should not be used.

On Ubuntu, first install the build tools. Substitute your PHP version: php8.4-dev, php8.3-dev, or php8.2-dev:

1sudo apt install php8.4-dev php-pear libmemcached-dev pkg-config make gcc -y

Then build the extension:

1sudo pecl install memcached

On AlmaLinux / Rocky Linux 9, the set is similar:

1sudo dnf install php-devel php-pear libmemcached-devel make gcc -y
2sudo pecl install memcached

After building, the extension must be registered in PHP. Create an INI file:

1echo "extension=memcached.so" | sudo tee /etc/php/8.4/mods-available/memcached.ini
2sudo phpenmod memcached

On AlmaLinux, the path will be different: /etc/php.d/memcached.ini.

If you are working in Plesk Obsidian, the command to reload PHP handlers after installing the extension:

1plesk bin php_handler --reread

Verify that the extension loaded:

1php -m | grep memcached

The output should contain memcached. If empty, check the path to the INI file and restart PHP-FPM: sudo systemctl restart php8.4-fpm.

Connecting WordPress to Memcached

The daemon is installed; the PHP extension is loaded. Now you need to connect WordPress to Memcached at the application level.

The de facto standard today is the official drop-in from Automattic: wp-memcached on GitHub. It is written by the same developers who maintain Batcache and WordPress.com, and it works correctly with PHP 8.x (including 8.4 and 8.5).

Copy the object-cache.php file from the repository into the /wp-content/ folder of your site. WordPress will automatically detect it and start using Memcached as the object cache backend, without additional plugins.

If the Memcached port differs from the default (11211), add the following to wp-config.php:

1$memcached_servers = array(
2 array( '127.0.0.1', 11211 )
3);

Page caching: Batcache

Object caching is half the battle. The other half is caching ready HTML pages so that PHP does not run at all for anonymous visitors. This is where Batcache comes in, a plugin from Automattic that stores generated pages in the same Memcached.

The principle is simple. A visitor arrives at the site; Batcache checks whether there is a ready HTML copy of this page in Memcached. If there is and it has not expired, it serves it instantly, bypassing the entire PHP and MySQL chain. If not, or if the visitor is logged in, the page is generated anew and simultaneously saved to the cache for subsequent visits.

Installation:

Download the archive from wordpress.org, extract it, and upload the advanced-cache.php file to the root of /wp-content/. Then open wp-config.php and add the line that enables caching:

1define( 'WP_CACHE', true );

Send the batcache.php file to /wp-content/plugins/ and activate the plugin in the admin panel.

Inside advanced-cache.php, there are about a dozen settings under comments. The most useful: max_age (page lifetime in seconds, default 300 or 5 minutes), seconds (interval between regenerations of the same URL), and unique (do not cache different User-Agents separately). For most sites, the default values work; adjust them only when you understand why.

An important nuance: make sure that define( 'WP_CACHE', true ) appears BEFORE the line require_once ABSPATH . 'wp-settings.php' in wp-config.php. If placed after, caching will not activate, and WordPress will silently ignore it.

Video: installation and configuration from start to finish

Theory is the foundation, but console commands are best seen once. This video covers the full cycle of setting up object caching for WordPress with Redis and Memcached, from installing the daemon to verifying the result:

Verifying that Memcached is working

The best test is a practical one. Add a custom header in advanced-cache.php so you can visually see whether the page was served from cache or generated anew.

Find this line in advanced-cache.php:

1var $headers = array();

Replace it with:

1var $headers = array( 'memcached' => 'activated' );

Now open DevTools in your browser (F12), go to the Network tab, and reload the page several times. In the Response Headers, you will see a field memcached: activated, meaning Batcache worked and the page went to the client directly from RAM.

An additional method involves the server command line. View the daemon statistics:

1echo "stats" | nc 127.0.0.1 11211

In the output, look for get_hits and get_misses. If get_hits grows when you refresh site pages in the browser, Memcached is reliably serving cached objects.

Load testing: numbers, not impressions

Memcached shows its true value under pressure. The original test on a server with 1 core and 512 MB of memory produced an impressive contrast: without Memcached, the server crashed after 15 seconds with 50 concurrent users; with Memcached, it held 400+ users for 50 seconds without a single error. This is not magic but physics: when the CPU does not spend cycles reassembling the same pages, it serves new visitors.

For self-testing today, modern tools are used. One of the most convenient is k6 from Grafana (open source, runs with a single command). A basic test:

1k6 run --vus 100 --duration 30s http://your-site.com/

100 virtual users for 30 seconds. Compare the results with Batcache disabled (comment out WP_CACHE) and enabled; the difference in successful responses and median latency will be measured in orders of magnitude.

For a quick check without installing software, the web tool Loader.io works well; the free tier allows up to 10,000 clients per test, which is more than enough for most sites.

Redis or Memcached: which to choose

The question that inevitably arises is why not Redis? Both are in-memory key-value stores; both work with WordPress via drop-ins. The short answer: for pure caching, Memcached is simpler and faster; for everything else, Redis.

Let us compare the essentials:

Criterion

Memcached

Redis

Data model

Strings only

Strings, lists, sets, hashes, geo data, pub/sub

Multi-threading

Uses all cores out of the box

Primarily single-threaded

Persistence

None (pure in-memory)

RDB/AOF (saves to disk)

WordPress ecosystem

Automattic/wp-memcached + Batcache

Redis Object Cache (400,000+ installs)

Setup complexity

Minimal

Slightly higher

Cache flush on restart

Full (but warms up in minutes)

Can be preserved

For caching WordPress objects, string key-value is more than sufficient. The extra Redis data types are not needed here. On get/set operations, both are limited by network throughput rather than CPU; all else being equal, they are on par. Memcached wins on multi-threading: it uses all CPU cores out of the box, whereas Redis maintains a predominantly single-threaded architecture.

Choose Redis if you are also storing sessions, task queues, or need persistence. For the task of "speeding up WordPress and offloading the database," Memcached delivers results faster and with fewer moving parts.

⁉️🤔 Frequently asked questions

Do I need Memcached on shared hosting?

On most shared hosting plans, Memcached is unavailable: providers do not grant access to the daemon at the server level. However, if your plan includes a VPS or dedicated server, installation takes 10 to 15 minutes and delivers one of the most noticeable speed gains among all WordPress optimizations. Check your plan's capabilities in the control panel or ask hosting support.

Batcache or WP Rocket: which is better?

WP Rocket is a multitool that handles page caching (file-based), CSS/JS optimization, and lazy loading. Batcache is a narrow tool specifically for Memcached page caching. They do not compete; they complement each other: Batcache works at the server level and serves pages without launching PHP, while WP Rocket operates at the application level. In practice, both are often used: Batcache for anonymous visitors, WP Rocket for fine-tuned optimization.

How do I flush the Memcached cache?

The simplest method is to restart the daemon: sudo systemctl restart memcached. The cache will clear completely and start warming up again on subsequent visits. For targeted clearing, use the Query Monitor plugin: it shows the contents of the object cache and allows flushing individual keys. There is also a console option: echo "flush_all" | nc 127.0.0.1 11211.

Why did the site not speed up after installing object-cache.php?

The most common reason is that the PHP extension did not load. Check php -m | grep memcached. If the output is empty, verify the path to the INI file and restart PHP-FPM. The second common reason: object-cache.php was not copied to /wp-content/ or was copied with permission errors (it must be readable by the user running PHP). Third: the Memcached daemon is not running; check systemctl status memcached.

Does Memcached conflict with OPcache?

No, these are different layers. OPcache caches compiled PHP bytecode and speeds up the interpreter startup. Memcached caches application data: database query results. They work at different stages of request processing and complement each other well. In production, using both is recommended.

Can Memcached be used across multiple servers?

Yes, this is one of the primary scenarios. In the $memcached_servers configuration, you can list several IP addresses of Memcached daemons, and the client will automatically distribute keys among them. For WordPress, the object-cache.php drop-in handles this: it supports a server pool out of the box.

Should you install Memcached on your server

Installing Memcached is not a cure-all but one of the most effective steps in WordPress optimization. If your site runs on a VPS or dedicated server and you want it to handle multifold traffic growth without replacing hardware, install it. Ten to fifteen minutes of console work, and the database stops being a bottleneck.

If the site is on shared hosting without access to the daemon, consider Redis (more often provided) or file-based caching via WP Rocket. If you are already on a VPS, open the terminal and follow the steps from the quick overview above. You will see the result in your first load test.