WebDevStory
  • Tech
    • Software Testing
    • IT and Management
    • Software Engineering
    • Technology
  • Web
    • JavaScript
    • Web Development
    • Front-end Development
    • React
    • Database Technologies
  • AI
    • AI and Machine Learning
    • AI in Education
    • AI Learning
    • AI Prompts
  • Programming
    • Coding
    • Design Patterns
  • Misc
    • Digital Transformation
    • SEO
    • Technology and Business
    • Technology and Innovation
    • Developer Roadmaps
    • Digital Marketing
  • More
    • Newsletter
    • Support Us
    • Contact
    • Tech & Lifestyle
    • Digital Nomadism
  • Services
No Result
View All Result
WebDevStory
  • Tech
    • Software Testing
    • IT and Management
    • Software Engineering
    • Technology
  • Web
    • JavaScript
    • Web Development
    • Front-end Development
    • React
    • Database Technologies
  • AI
    • AI and Machine Learning
    • AI in Education
    • AI Learning
    • AI Prompts
  • Programming
    • Coding
    • Design Patterns
  • Misc
    • Digital Transformation
    • SEO
    • Technology and Business
    • Technology and Innovation
    • Developer Roadmaps
    • Digital Marketing
  • More
    • Newsletter
    • Support Us
    • Contact
    • Tech & Lifestyle
    • Digital Nomadism
  • Services
No Result
View All Result
WebDevStory
No Result
View All Result
Home Website Optimization

Safely Flush Memcached Object Cache in WordPress (Per Site with WP_CACHE_KEY_SALT)

Mainul Hasan by Mainul Hasan
August 7, 2025
in Website Optimization, WordPress Optimization
Reading Time: 9 mins read
0 0
0
Illustration showing safe Memcached object cache flush for WordPress sites on shared VPS

Supercharge your WordPress performance with smart Memcached cache management using WP_CACHE_KEY_SALT.

0
SHARES
5
VIEWS

We run multiple WordPress sites on a single VPS, all using Memcached for object caching. The problem? Flushing the object cache for one site risks wiping the cache for all others sharing the same memory pool.

In this post, I’ll walk you through:

  • Why object caching is critical for WordPress performance
  • How Memcached behaves in shared VPS environments
  • And how we built a custom plugin to safely flush cache per site using WP_CACHE_KEY_SALT

If you’re managing multiple sites, I hope this guide helps you optimize caching with clarity and confidence.

Table of Contents

    1. Why Object Caching Matters in WordPress

    Object caching temporarily stores the results of complex database queries, WordPress options, or transients in memory so they can be quickly reused. This avoids hitting the MySQL database unnecessarily and significantly reduces load time.

    Why it matters:

    • Faster page loads (especially for dynamic or logged-in requests)
    • Reduced database stress under traffic spikes
    • Essential for scaling WordPress on high-traffic sites

    Memcached vs Redis for WordPress

    FeatureMemcachedRedis
    Data structureKey-value onlySupports advanced types (lists, sets, etc.)
    PersistenceIn-memory only (no persistence)Optional persistence to disk
    Use caseLightweight, fast for object cachingMore flexible, often used in Laravel or apps needing queues
    WordPress fitGreat for object cache (transients, queries)Also great; some plugins prefer Redis

    In many cases, Memcached is faster and simpler to configure — and it’s widely supported by LiteSpeed and cPanel providers.

    2. How Memcached Works in Shared VPS Environments

    Default Port 11211 and Shared Instances

    Memcached by default runs on port 11211. Unless explicitly isolated per app, all websites on the server connect to the same instance. That means:

    • A flush command (flush_all) affects all keys from all sites.
    • There’s no native separation of site-specific data.

    Why You Need to Namespace Your Keys

    WordPress supports namespacing via:

    
      define('WP_CACHE_KEY_SALT', 'yoursiteprefix_');
      

    This is essential. It prepends a unique string to every cache key generated by WordPress, allowing plugins or scripts (like ours) to selectively flush only your site’s cache.

    Without it, you can’t safely delete keys without affecting others.

    Memory Limits: Default vs Optimized

    Default Memcached allocation on many cPanel servers is 64 MB.

    You can monitor it using tools like:

    • getStats() via script
    • WordPress Object Cache Pro
    • Custom scripts with fsockopen or Telnet

    Example output:

    
        Memory Used  : 37 MB
        Memory Limit : 64 MB
        Evictions    : 1.4M (means old data is being overwritten)
        Hit Rate     : 94%
      

    What Happens When Multiple Sites Share the Same Instance

    • Cache collisions (without WP_CACHE_KEY_SALT)
    • Overwrites and evictions
    • Full flushes affect every site
    • Monitoring gets confusing unless you prefix keys and track them separately

    That’s why we decided to build our own flusher plugin tailored to a multi-site VPS scenario.

    3. Building a Custom Cache Flusher Plugin

    💡 The Problem

    WordPress provides a built-in function:

    wp_cache_flush();

    But there’s a catch:

    • It only works via WP-CLI.
    • If used programmatically, it often gets blocked in object-cache.php or flushes everything — not safe for shared environments.

    🔨 Plugin Features

    • Adds a “Flush Object Cache” option under Tools → Flush Object Cache
    • Detects cache backend: Memcached, Redis, APC, or unknown
    • Checks for WP_CACHE_KEY_SALT
    • If defined → flushes only matching keys

    🧪 Technical Highlights

    • Uses Memcached::getAllKeys() when available
    • Uses delete() for each key that starts with the defined salt
    • Handles extensions that don’t support key enumeration (e.g., fallback message)
    • Displays real-time status messages like:
      • ✅ Flushed 318 keys using WP_CACHE_KEY_SALT
      • ⚠️ Salt not defined and no confirmation to flush all cache
      • ❌ Backend not detected

    4. Monitoring Memcached Usage

    Once object caching is active, blindly assuming it’s helping is a mistake. You need visibility into how your Memcached instance is performing, especially if it’s shared among multiple sites.

    We built a lightweight PHP script that outputs useful Memcached stats:

    
      <?php
      /**
       * Memcached Monitor – WordPress-safe PHP script
       * Shows or logs Memcached usage: items, memory, hits, evictions
     */
    
     header('Content-Type: text/plain');
    
     function socf_get_memcached_stats() {
      $sock = @fsockopen('127.0.0.1', 11211);
      if (!$sock) {
        return "❌ Could not connect to Memcached at 127.0.0.1:11211.";
      }
    
      fwrite($sock, "stats\n");
      $stats = [];
    
      while (!feof($sock)) {
        $line = fgets($sock, 128);
        if (strpos($line, 'STAT') === 0) {
          $parts = explode(' ', trim($line));
          $stats[$parts[1]] = $parts[2];
        } elseif (trim($line) === 'END') {
          break;
        }
      }
      fclose($sock);
    
      // Output
      $output  = "✅ Memcached Status:\n";
      $output .= "-------------------\n";
      $output .= "Items Stored       : " . number_format($stats['curr_items']) . "\n";
      $output .= "Memory Used        : " . round($stats['bytes'] / 1024 / 1024, 2) . " MB\n";
      $output .= "Memory Limit       : " . round($stats['limit_maxbytes'] / 1024 / 1024, 2) . " MB\n";
      $output .= "Cache Hits         : " . number_format($stats['get_hits']) . "\n";
      $output .= "Cache Misses       : " . number_format($stats['get_misses']) . "\n";
      $output .= "Evictions          : " . number_format($stats['evictions']) . "\n";
      $output .= "Hit Rate           : " . (
      ($stats['get_hits'] + $stats['get_misses']) > 0
      ? round($stats['get_hits'] / ($stats['get_hits'] + $stats['get_misses']) * 100, 2)
      : 0
      ) . "%\n";
    
      return $output;
    }
    
    // Show or log depending on context
    echo socf_get_memcached_stats();
    

    You can run this script from your browser or cron to monitor performance.

    
      ✅ Memcached Status:
      ----------------------
      Items Stored  : 107,705
      Memory Used   : 37.36 MB
      Memory Limit  : 64 MB
      Cache Hits    : 631,841,892
      Cache Misses  : 35,675,800
      Evictions     : 1,476,500
      Hit Rate      : 94.66%
    

    What These Metrics Mean:

    • Memory Used vs Limit: If usage is consistently close to the limit (e.g., 60 MB of 64 MB), eviction is likely.
    • Hit/Miss Ratio: A high hit rate (90%+) means the cache is effective.
    • Evictions: This shows how many old entries Memcached had to delete to make space. Frequent evictions = not enough memory.
    • Items Stored: Number of keys in cache.

    Tracking Per-Site Usage by Prefix (Salt)

    We extended our script to group keys by WP_CACHE_KEY_SALT prefix and output something like:

    
      <?php
      /**
       * Memcached Site-wise Monitor (with defined salts)
       * Groups keys by exact WP_CACHE_KEY_SALT values.
     */
    
     header('Content-Type: text/plain');
    
     // Define your known salts (must match what's in wp-config.php)
     $salt_prefixes = [
     'webdevstory_'     => 'WebDevStory',
     'site2_'       => 'Site 2',
     'site3_' => 'Site 3',
     'site4_'      => 'Site 4',
     ];
    
     function socf_get_sitewise_memcached_keys($salt_prefixes) {
      $sock = @fsockopen('127.0.0.1', 11211);
      if (!$sock) {
        return "❌ Could not connect to Memcached at 127.0.0.1:11211.";
      }
    
      fwrite($sock, "stats items\r\n");
      $slabs = [];
    
      while (!feof($sock)) {
        $line = fgets($sock, 128);
        if (preg_match('/STAT items:(\d+):number/', $line, $matches)) {
          $slabs[] = $matches[1];
        } elseif (trim($line) === 'END') {
          break;
        }
      }
    
      $site_counts = array_fill_keys(array_values($salt_prefixes), 0);
      $site_counts['Untracked'] = 0;
    
      foreach (array_unique($slabs) as $slab) {
        fwrite($sock, "stats cachedump $slab 200\r\n");
        while (!feof($sock)) {
          $line = fgets($sock, 512);
          if (preg_match('/ITEM ([^\s]+) /', $line, $matches)) {
            $key = $matches[1];
            $matched = false;
            foreach ($salt_prefixes as $salt => $label) {
              if (strpos($key, $salt) === 0) {
                $site_counts[$label]++;
                $matched = true;
                break;
              }
            }
            if (!$matched) {
              $site_counts['Untracked']++;
            }
          } elseif (trim($line) === 'END') {
            break;
          }
        }
      }
    
      fclose($sock);
    
      $output  = "📊 Memcached Key Usage by Site (Salt Matching):\n";
      $output .= "---------------------------------------------\n";
      foreach ($site_counts as $label => $count) {
        $output .= sprintf("🔹 %-20s : %d keys\n", $label, $count);
      }
    
      return $output ?: "No keys found.";
    }
    
    echo socf_get_sitewise_memcached_keys($salt_prefixes);
    
    
      📊 Memcached Key Usage by Site (Salt Matching):
        -----------------------------------------------
      Site 1       : 0 keys
      Site 2       : 429 keys
      Site 3       : 164 keys
      Site 4       : 1273 keys
      Untracked    : 7 keys
    

    This is invaluable when diagnosing:

    • Why a specific site is bloating memory
    • Whether your salt is missing (0 keys = wrong or undefined salt)
    • Sites not benefiting from caching at all

    When and Why Evictions Happen

    Evictions occur when Memcached runs out of memory and starts removing old keys (often the least recently used). Common causes:

    • Multiple high-traffic sites on the same Memcached instance
    • Large WooCommerce or multilingual setups
    • Default memory limit too small (e.g., 64 MB)

    💡 We upgraded our instance to 512 MB after observing high eviction counts and were able to reduce them significantly.

    5. Deciding Which Sites Should Use Object Cache

    Not all websites need object caching — or at least not Memcached/Redis-level caching.

    ✅ When Object Cache Is Helpful

    • WooCommerce stores: Dynamic product and cart pages, session data, etc.
    • Multilingual websites: Lots of options and translation strings cached
    • Membership or login-based sites: Auth checks and custom queries
    • Content-heavy blogs with logged-in users (e.g., WebDevStory)

    In these cases, object caching significantly reduces query load and boosts TTFB.

    ❌ When Object Cache May Not Be Worth It

    • Small static brochure sites
    • Low-traffic blogs with infrequent updates
    • Minimal plugin usage

    For example, we disabled Memcached for a site which is:

    • Static and updated rarely
    • Lightweight in theme and plugins
    • Visited occasionally, mostly by anonymous users

    Using object cache here would just consume space in shared memory and increase complexity.

    💡 Rule of Thumb:

    ScenarioUse Object Cache?
    WooCommerce with 500+ products✅ Yes
    Blog with 50 posts, no login❌ Probably not
    Multilingual portfolio site✅ Yes
    Static info page❌ Skip it
    Membership site✅ Absolutely

    6. Best Practices for Multi-site Memcached Use

    ✅ Always Define WP_CACHE_KEY_SALT

    This is critical. Without it:

    • All keys go into a global pool
    • You lose the ability to flush per site
    • Monitoring tools can’t differentiate usage

    Sample setup per wp-config.php:

    define('WP_CACHE_KEY_SALT', 'webdevstory_');

    🚫 Avoid Full Flush Unless Using Dedicated Memcached

    • Unless you’re on a single-site server: Never flush the entire cache without confirming
    • Use a plugin (like ours) that prevents accidental full flush without salt
    • Full flushes can cause downtime or performance drop across other sites on the same instance

    📊 Use Monitoring to Balance Memory

    Whether through:

    • A custom PHP stats script
    • LiteSpeed cache panel
    • Query Monitor plugin (advanced)

    Regular monitoring helps answer:

    • Should you increase memory?
    • Is one site bloating the cache?
    • Are your hit rates improving?

    🧠 Be Aware of Key Growth and Expiry

    Memcached stores keys in memory until:

    • They expire (default: 0 = never)
    • They’re evicted due to space pressure

    If your plugin or theme stores too many transients or uses long TTLs (wp_cache_set( 'key', 'value', 'group', 3600 )), you may:

    • Waste memory on stale data
    • Trigger unnecessary evictions
    • Hurt performance rather than improve it

    📌 Set sensible expiration times and review what’s being cached if you suspect bloat.

    Final Thoughts

    Object caching can supercharge your WordPress site — but only if managed correctly.

    From small blogs to large WooCommerce stores, the difference between efficient and wasteful caching comes down to:

    • Using Memcached wisely in shared or VPS setups
    • Defining a proper WP_CACHE_KEY_SALT for isolation
    • Monitoring usage and tuning memory limits
    • Having tools to flush intelligently, not blindly

    We learned the hard way: full cache flushes, shared memory conflicts, and missed key prefixes can cost you performance and stability.

    Try Our Simple Object Cache Flusher Plugin

    To help manage this, we built a lightweight plugin with:

    • ✅ Admin button to flush object cache
    • ✅ Selective flush by salt (WP_CACHE_KEY_SALT)
    • ✅ Full-flush confirmation if no salt is defined
    • ✅ Memcached backend detection
    • ✅ Safe UI feedback with hit/miss logging options
    
      <?php
      /**
       * Plugin Name: Simple Object Cache Flusher
       * Description: Adds an admin menu with backend info and a button to flush only this site's object cache (Memcached) using WP_CACHE_KEY_SALT.
       * Version: 1.3
       * Author: Mainul Hasan
       * Author URI: https://www.webdevstory.com/
       * License: GPL2+
       * License URI: https://www.gnu.org/licenses/gpl-2.0.html
       * Text Domain: simple-object-cache-flusher
       * Domain Path: /languages
     */
    
     add_action('admin_menu', function () {
      add_management_page(
      __('Flush Object Cache', 'simple-object-cache-flusher'),
      __('Flush Object Cache', 'simple-object-cache-flusher'),
      'manage_options',
      'flush-object-cache',
      'socf_admin_page'
      );
    });
    
    function socf_admin_page() {
      if (!current_user_can('manage_options')) {
        wp_die(__('Not allowed.', 'simple-object-cache-flusher'));
      }
    
      $cache_backend = __('Unknown', 'simple-object-cache-flusher');
      if (file_exists(WP_CONTENT_DIR . '/object-cache.php')) {
        $file = file_get_contents(WP_CONTENT_DIR . '/object-cache.php');
        if (stripos($file, 'memcached') !== false) {
          $cache_backend = 'Memcached';
        } elseif (stripos($file, 'redis') !== false) {
          $cache_backend = 'Redis';
        } elseif (stripos($file, 'APC') !== false) {
          $cache_backend = 'APC';
        } else {
          $cache_backend = __('Custom/Other', 'simple-object-cache-flusher');
        }
      } else {
        $cache_backend = __('Not detected / Disabled', 'simple-object-cache-flusher');
      }
    
      if (isset($_POST['socf_flush'])) {
        check_admin_referer('socf_flush_cache', 'socf_nonce');
    
        $prefix = defined('WP_CACHE_KEY_SALT') ? WP_CACHE_KEY_SALT : '';
        $deleted = 0;
        $error_msg = '';
    
        if ($prefix && class_exists('Memcached')) {
          $host = apply_filters('socf_memcached_host', '127.0.0.1');
          $port = apply_filters('socf_memcached_port', 11211);
          $mem = new Memcached();
          $mem->addServer($host, $port);
    
          if (method_exists($mem, 'getAllKeys')) {
            $all_keys = $mem->getAllKeys();
            if (is_array($all_keys)) {
              foreach ($all_keys as $key) {
                if (strpos($key, $prefix) === 0) {
                  if ($mem->delete($key)) {
                    $deleted++;
                  }
                }
              }
            }
          } else {
            $error_msg = 'Your Memcached extension does not support key enumeration (getAllKeys). Partial flush not possible.';
          }
        }
    
        if ($deleted > 0) {
          echo '<div class="notice notice-success is-dismissible"><p>' .
          esc_html__('✅ Flushed ' . $deleted . ' object cache keys using WP_CACHE_KEY_SALT.', 'simple-object-cache-flusher') .
          '</p></div>';
        } else {
          echo '<div class="notice notice-warning is-dismissible"><p>' .
          esc_html__('⚠️ No matching keys deleted. Either WP_CACHE_KEY_SALT is not set, or key listing is unsupported. ', 'simple-object-cache-flusher') .
          esc_html($error_msg) .
          '</p></div>';
        }
      }
      ?>
      <div class="wrap">
      <h1><?php esc_html_e('Flush Object Cache', 'simple-object-cache-flusher'); ?></h1>
      <p><strong><?php esc_html_e('Backend detected:', 'simple-object-cache-flusher'); ?></strong> <?php echo esc_html($cache_backend); ?></p>
      <form method="post">
      <?php wp_nonce_field('socf_flush_cache', 'socf_nonce'); ?>
      <p>
      <input type="submit" name="socf_flush" class="button button-primary"
      value="<?php esc_attr_e('Flush Object Cache Now', 'simple-object-cache-flusher'); ?>"/>
      </p>
      </form>
      <p><?php esc_html_e("This will flush the Memcached object cache if available on your server. Tries to delete only this site's keys if salt is defined.", 'simple-object-cache-flusher'); ?></p>
      <?php if ($cache_backend === __('Not detected / Disabled', 'simple-object-cache-flusher')) : ?>
      <p style="color: red;"><?php esc_html_e('No object cache backend detected. You may not be using object caching.', 'simple-object-cache-flusher'); ?></p>
      <?php endif; ?>
      </div>
      <?php
    }
    
    add_action('plugins_loaded', function () {
      load_plugin_textdomain('simple-object-cache-flusher', false, dirname(plugin_basename(__FILE__)) . '/languages');
    });
    

    👉 Check it out on GitHub

    🚀 Before You Go:

    • 👏 Found this guide helpful? Give it a like!
    • 💬 Got thoughts? Share your insights!
    • 📤 Know someone who needs this? Share the post!
    • 🌟 Your support keeps us going!

    💻 Level up with the latest tech trends, tutorials, and tips - Straight to your inbox – no fluff, just value!

    Join the Community →
    Tags: CachingLiteSpeed CacheMemcachedMultisiteObject CacheRedisServer OptimizationVPS HostingWordPressWordPress PerformanceWordPress PluginWP_CACHE_KEY_SALT
    ADVERTISEMENT
    Previous Post

    Top 5 Self-Help Classics Every Tech Professional Should Read

    Related Posts

    Core Web Vitals displayed with wooden letter tiles on colorful paper background
    Website Optimization

    How to Fix WordPress Website Core Web Vitals Issues: Complete Guide

    August 18, 2024

    Leave a Reply Cancel reply

    Your email address will not be published. Required fields are marked *

    Save 20% with Code mainul76 on Pictory AI - Limited-Time Discount Save 20% with Code mainul76 on Pictory AI - Limited-Time Discount Save 20% with Code mainul76 on Pictory AI - Limited-Time Discount

    You might also like

    User interface of a blog application showing a list of posts with titles, authors, and publication dates

    Building a Blogging Site with React and PHP: A Step-by-Step Guide

    February 10, 2024
    JavaScript ES6 features for React development

    Essential ES6 Features for Mastering React

    July 26, 2023
    Word cloud featuring modern software development key terms.

    Modern Software Development Practices, Terms and Trends

    January 23, 2024
    Globe with HTTP Protocol - Understanding JavaScript HTTP Request Libraries

    HTTP Requests in JavaScript: Popular Libraries for Web Developers

    March 5, 2024
    Stylized JavaScript JS logo alongside Advanced text, representing in-depth JavaScript programming concepts

    25 Advanced JavaScript Features You Should Know

    December 28, 2024
    Hands typing on a laptop with API development icons, showcasing technology and integration

    Integrate Dropbox API with React: A Comprehensive Guide

    September 6, 2024
    Fiverr affiliates promotional banner - Get paid to share Fiverr with your network. Start Today. Fiverr affiliates promotional banner - Get paid to share Fiverr with your network. Start Today. Fiverr affiliates promotional banner - Get paid to share Fiverr with your network. Start Today.
    Coursera Plus promotional banner - Save 40% on one year of Coursera Plus. Subscribe now. Coursera Plus promotional banner - Save 40% on one year of Coursera Plus. Subscribe now. Coursera Plus promotional banner - Save 40% on one year of Coursera Plus. Subscribe now.
    Namecheap .COM domain promotional banner - Get a .COM for just $5.98. Secure a mighty domain for a mini price. Claim now. Namecheap .COM domain promotional banner - Get a .COM for just $5.98. Secure a mighty domain for a mini price. Claim now. Namecheap .COM domain promotional banner - Get a .COM for just $5.98. Secure a mighty domain for a mini price. Claim now.
    WebDevStory logo

    Empowering your business with tailored web solutions, expert SEO, and cloud integration to fuel growth and innovation.

    Contact Us

    Hans Ross Gate 3, 0172, Oslo, Norway

    +47-9666-1070

    info@webdevstory.com

    Stay Connected

    • Contact
    • Privacy Policy

    © webdevstory.com

    Welcome Back!

    Login to your account below

    Forgotten Password?

    Retrieve your password

    Please enter your username or email address to reset your password.

    Log In
    No Result
    View All Result
    • Tech
      • Software Testing
      • IT and Management
      • Software Engineering
      • Technology
    • Web
      • JavaScript
      • Web Development
      • Front-end Development
      • React
      • Database Technologies
    • AI
      • AI and Machine Learning
      • AI in Education
      • AI Learning
      • AI Prompts
    • Programming
      • Coding
      • Design Patterns
    • Misc
      • Digital Transformation
      • SEO
      • Technology and Business
      • Technology and Innovation
      • Developer Roadmaps
      • Digital Marketing
    • More
      • Newsletter
      • Support Us
      • Contact
      • Tech & Lifestyle
      • Digital Nomadism
    • Services

    © webdevstory.com