• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » High-Throughput Caching Strategies: Scaling MySQL for Magento 2 Application APIs

High-Throughput Caching Strategies: Scaling MySQL for Magento 2 Application APIs

Leveraging Redis for Magento 2 API Caching: A Deep Dive

Magento 2’s reliance on API calls for dynamic content retrieval, especially in headless or complex integrations, presents a significant scaling challenge. High-throughput scenarios demand aggressive caching strategies to offload the primary MySQL database. Redis, with its in-memory data structure store capabilities, is the de facto standard for this purpose. This post details advanced Redis caching configurations and PHP implementations for Magento 2 API endpoints.

Optimizing Redis Configuration for API Caching

A default Redis configuration is rarely sufficient for high-volume API caching. Key parameters to tune include:

  • maxmemory: Crucial for controlling memory usage. Set this to a value that allows for your cache data plus operating system overhead.
  • maxmemory-policy: For API caching, allkeys-lru (Least Recently Used) is often a good starting point, evicting older, less accessed keys to make space for new ones.
  • tcp-backlog: Increase this to handle a higher number of incoming connections during peak loads.
  • timeout: Set to 0 to prevent idle connections from being closed prematurely, which can be beneficial for persistent API connections.

Here’s an example redis.conf snippet:

# redis.conf
maxmemory 10gb
maxmemory-policy allkeys-lru
tcp-backlog 512
timeout 0
appendonly no # For caching, persistence is often not required and can impact performance
save "" # Disable RDB snapshots if appendonly is no

After modifying redis.conf, restart the Redis server:

sudo systemctl restart redis-server

Implementing Custom API Caching Logic in Magento 2

Magento 2’s caching infrastructure can be extended to support custom API caching. This typically involves creating a custom module that intercepts API requests, checks the Redis cache, and, if a cache miss occurs, fetches data from the database, caches it, and then returns it.

We’ll focus on caching responses for a hypothetical API endpoint that retrieves product details by SKU. This involves creating a plugin (interceptor) for the relevant repository method.

Plugin Structure and Cache Key Generation

First, define the plugin in your module’s di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Api\ProductRepositoryInterface">
        <plugin name="antigravity_cache_product_api"
                type="Antigravity\Cache\Plugin\ProductRepositoryPlugin"
                sortOrder="10" />
    </type>
</config>

Next, create the plugin class (e.g., Antigravity/Cache/Plugin/ProductRepositoryPlugin.php). The core logic will be in the afterGetById or afterGet method, depending on how your API retrieves products. For SKU-based retrieval, we’ll assume a custom method or adapt get.

Cache Key Generation Strategy

A robust cache key is essential. It should uniquely identify the requested resource and any relevant context (e.g., store view, customer group). For product retrieval by SKU, a good key might look like:

namespace Antigravity\Cache\Plugin;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product;
use Magento\Framework\App\Cache\Frontend\Pool;
use Magento\Framework\Serialize\SerializerInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\CacheInterface; // Use Magento's Cache interface for abstraction

class ProductRepositoryPlugin
{
    const CACHE_TAG = 'PRODUCT_API_CACHE';
    const CACHE_LIFETIME = 3600; // 1 hour

    /**
     * @var CacheInterface
     */
    private $cache;

    /**
     * @var SerializerInterface
     */
    private $serializer;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @param CacheInterface $cache
     * @param SerializerInterface $serializer
     * @param LoggerInterface $logger
     */
    public function __construct(
        CacheInterface $cache,
        SerializerInterface $serializer,
        LoggerInterface $logger
    ) {
        $this->cache = $cache;
        $this->serializer = $serializer;
        $this->logger = $logger;
    }

    /**
     * Generate a cache key for product retrieval by SKU.
     *
     * @param string $sku
     * @param int|null $storeId
     * @return string
     */
    private function generateCacheKey(string $sku, ?int $storeId = null): string
    {
        $storeId = $storeId ?? \Magento\Store\Model\StoreManagerInterface::DEFAULT_STORE_ID;
        // Example: PRODUCT_API_CACHE::sku_123::store_1
        return self::CACHE_TAG . '::sku_' . $sku . '::store_' . $storeId;
    }

    /**
     * Intercepts the get method to check/set cache.
     *
     * @param ProductRepositoryInterface $subject
     * @param string $sku
     * @param bool $editMode
     * @param int|null $storeId
     * @param array $attributes
     * @return Product
     */
    public function afterGet(
        ProductRepositoryInterface $subject,
        Product $result,
        string $sku,
        bool $editMode = false,
        ?int $storeId = null,
        array $attributes = []
    ): Product {
        $cacheKey = $this->generateCacheKey($sku, $storeId);
        $cacheData = $this->cache->load($cacheKey);

        if ($cacheData) {
            $this->logger->debug("Cache hit for product SKU: {$sku}");
            return $this->serializer->unserialize($cacheData);
        }

        $this->logger->debug("Cache miss for product SKU: {$sku}. Caching data.");
        $serializedProduct = $this->serializer->serialize($result);
        $this->cache->save($serializedProduct, $cacheKey, [self::CACHE_TAG], self::CACHE_LIFETIME);

        return $result;
    }
}

Note: In this example, we’re using Magento’s abstract CacheInterface, which can be configured to use Redis via app/etc/env.php. Ensure your env.php is set up correctly for Redis:

return [
    'backend' => [
        'frontName' => 'cache_backend_redis',
        'redis' => [
            'host' => '127.0.0.1',
            'port' => 6379,
            'password' => '',
            'database' => 0, // Use a dedicated database for Magento cache
            'compress_data' => '1', // Optional: compress data before storing
            'compression_library' => 'gzip', // Or 'lzf', 'lz4'
        ]
    ],
    // ... other Magento configuration
];

Cache Invalidation Strategies

Cache invalidation is as critical as caching itself. For API caching, consider these strategies:

  • Time-Based Expiration: As shown with self::CACHE_LIFETIME, this is the simplest approach. Data is considered stale after a set period.
  • Event-Based Invalidation: Trigger cache purges when relevant data changes (e.g., product update, price change). This can be implemented using observers listening to specific Magento events (e.g., catalog_product_save_after).
  • Tag-Based Invalidation: Magento’s cache system supports tags. When saving cache entries, associate them with relevant tags (e.g., PRODUCT_API_CACHE). To invalidate all product API cache, you can then use $this->cache->removeTag(self::CACHE_TAG);. This is powerful for bulk invalidations.

An observer for product save events:

<!-- etc/frontend/events.xml or etc/adminhtml/events.xml -->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_product_save_after">
        <observer name="antigravity_cache_product_invalidate"
                  instance="Antigravity\Cache\Observer\ProductSaveObserver" />
    </event>
</config>
namespace Antigravity\Cache\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\Event\Observer;
use Psr\Log\LoggerInterface;

class ProductSaveObserver implements ObserverInterface
{
    const CACHE_TAG = 'PRODUCT_API_CACHE';

    /**
     * @var CacheInterface
     */
    private $cache;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        CacheInterface $cache,
        LoggerInterface $logger
    ) {
        $this->cache = $cache;
        $this->logger = $logger;
    }

    /**
     * @param Observer $observer
     * @return void
     */
    public function execute(Observer $observer): void
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getEvent()->getProduct();
        if ($product && $product->getId()) {
            $this->logger->info("Product saved (ID: {$product->getId()}). Invalidating related API cache.");
            // Invalidate all cache entries associated with the PRODUCT_API_CACHE tag.
            // This is a broad invalidation. For more granular control, you'd need to
            // derive the specific cache keys from the product data and remove them individually.
            $this->cache->removeTag(self::CACHE_TAG);
        }
    }
}

Advanced Considerations for High-Throughput APIs

For truly high-throughput APIs, consider these additional optimizations:

  • Redis Cluster/Sentinel: For high availability and scalability, deploy Redis in a cluster or use Sentinel for failover. Ensure your Magento configuration points to the correct cluster endpoints or Sentinel master.
  • Dedicated Redis Instances: Avoid using the same Redis instance for Magento’s full page cache, session storage, and API caching. Dedicate separate instances or databases to prevent cache stampedes and resource contention.
  • Cache Warming: Pre-populate the cache with frequently accessed data. This can be done via cron jobs that periodically fetch and cache popular API responses.
  • API Gateway Caching: If you use an API Gateway (e.g., Nginx, HAProxy, or a dedicated service), leverage its caching capabilities for an additional layer of defense before requests even hit your Magento application.
  • Response Serialization Format: JSON is common, but consider its overhead. For internal services, Protocol Buffers or MessagePack might offer more efficient serialization and deserialization, reducing network bandwidth and processing time.
  • Asynchronous Operations: For non-critical API responses, consider asynchronous fetching and caching. The initial API call might return a “pending” status, with the actual data becoming available shortly after being populated in the cache.

Monitoring and Performance Tuning

Continuous monitoring is essential. Key metrics to track include:

  • Redis Memory Usage: Monitor used_memory and used_memory_rss.
  • Cache Hit Rate: Track the ratio of cache hits to total requests. This is often visible through Redis monitoring tools or by instrumenting your application.
  • Latency: Measure the time taken for API requests, both cache hits and misses.
  • Evictions: Monitor evicted_keys in Redis. A high number indicates that maxmemory is being reached frequently, and you may need to increase it or refine your cache invalidation strategy.
  • Network I/O: Ensure sufficient bandwidth between your application servers and Redis instances.

Tools like RedisInsight, Prometheus with the Redis Exporter, or Datadog can provide valuable insights into Redis performance.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala