Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Laravel Cache Tags with Redis vs Memcached

By Kokil Thapa | Last reviewed: September 2026

Laravel cache tags with Redis vs Memcached is not an academic choice—it determines whether you can invalidate a whole slice of application cache without flushing everything or hard-coding key lists. On production Laravel applications I maintain, tagged caching keeps category pages, permission snapshots, and API response fragments consistent after a single model update. The catch: not every cache driver supports tags, and Redis and Memcached behave differently once traffic, clustering, and persistence enter the picture. This guide walks through how Laravel implements tags on each backend, what breaks in real deployments, and which option I reach for on Laravel 13 with PHP 8.3 or higher.

If you are new to application-level caching in Laravel, start with the fundamentals in Redis caching for Laravel PHP applications before layering tags on top. Tags solve a specific problem—group invalidation—not raw speed alone.

What are Laravel cache tags and why do you need them?

Cache tags let you label cached entries and flush every entry sharing a label in one call. Without tags, you either maintain a manual registry of keys or call Cache::flush(), which evicts unrelated data and spikes database load on the next request wave.

A typical pattern on an eCommerce or directory site:

  • Tag product listing fragments with products and per-category tags like category:12.
  • Tag user permission caches with user:45 and roles.
  • Tag CMS block output with page:about so a content edit clears only affected pages.

Laravel exposes tags through the same facade regardless of driver:

use Illuminate\Support\Facades\Cache;

Cache::tags(['products', 'category:12'])->put(
    'products.category.12.page.1',
    $html,
    now()->addHours(6)
);

Cache::tags(['products', 'category:12'])->flush();

Under the hood, Laravel stores tag metadata separately from the cached value. When you flush a tag, the framework resolves all keys associated with that tag and deletes them. That indirection costs a little memory and CPU compared to plain key-value caching, but it saves hours of brittle key-tracking code. For architectural context on where caching sits in a modern stack, see modern Laravel architecture best practices.

Laravel Cache Tags — Concept OverviewTag: productsGroup labelTag: category:12Finer scopeCached valuesHTML, arrays, JSONKey: products.category.12.page.1Registered under both tagsKey: products.featured.homeRegistered under products onlyCache::tags(['category:12'])->flush() clears scoped keys only
Laravel cache tags group keys under labels so you invalidate related entries without flushing the entire store.

Does Memcached support Laravel cache tags like Redis?

Yes—both Redis and Memcached are among the drivers Laravel documents as supporting tags, along with array (tests) and DynamoDB. File and database drivers do not support tags; attempting Cache::tags() with them throws a runtime exception.

The API surface is identical. The differences show up in operations, limits, and infrastructure:

CriteriaRedis (8.10)Memcached (1.6.x)
Tag support in Laravel 13Yes — first-class production choiceYes — works on single node; cluster caveats
PersistenceRDB snapshots, AOF optionalPurely volatile (data lost on restart)
Tag flush cost at scaleModerate; SCAN-friendly workflowsModerate; large tag sets can lag
Multi-node / clusterRedis Cluster with known hash-slot rulesClient-side hashing; tag metadata must stay coherent
Beyond cachingQueues, locks, broadcasting, sessionsCaching only
Typical hosting costSlightly higher RAM footprintLean for simple object cache
Verdict for tagged Laravel appsRecommended defaultLegacy or specialised Memcached-only stacks

On a legal-tech portal where document lists and permission caches must invalidate together after an upload, I default to Redis so one infrastructure component also handles Laravel real-time features with Redis and session storage when needed. Memcached remains valid if your platform team already operates Memcached 1.6.x pools and your Laravel app only needs object caching—nothing more.

For deeper persistence and failover trade-offs, read Redis persistence and clustering before committing to a production topology.

How do you configure Laravel cache tags with Redis?

Laravel 13 expects PHP 8.3 or higher. Install the PHP Redis extension or use Predis via Composer—extension-based phpredis is faster under load.

Install and verify the Redis extension

sudo apt install php8.5-redis
php -m | grep redis
composer require predis/predis

Set the cache driver in .env

CACHE_STORE=redis

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

Confirm config/cache.php

'default' => env('CACHE_STORE', 'database'),

'stores' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
        'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
    ],
],

Keep cache connections separate from queue connections in config/database.php so a runaway queue worker cannot evict hot cache keys:

'redis' => [
    'client' => env('REDIS_CLIENT', 'phpredis'),

    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => 0,
    ],

    'cache' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => 1,
    ],
],

Smoke-test tagged writes

php artisan tinker

Cache::tags(['demo'])->put('tagged-key', 'hello', 60);
Cache::tags(['demo'])->get('tagged-key');
Cache::tags(['demo'])->flush();

Official reference: the Laravel 13 cache tags documentation lists supported drivers and method signatures. Redis server docs at redis.io cover memory policies that interact with eviction when RAM fills.

Server hardening—firewall rules, memory caps, persistence files—belongs in your deployment checklist alongside application config. For Ubuntu production setups I handle regularly, see Linux system administration for production Laravel hosting.

Tagged Cache Invalidation Flow1. Model saveProduct updated2. ObserverFlush by tag3. RedisKeys removed4. RebuildOn next hitObserver exampleCache::tags(['products','category:'.$id])->flush();Stale risk if flush skippedUsers see old pricesFix: event-driven flushCorrect tag flushOnly related keys dropDB load stays predictable
Model observers or events should flush Laravel cache tags immediately after data changes so the next HTTP request rebuilds fresh fragments.

How do you configure Laravel cache tags with Memcached?

Switching drivers is mostly an environment change—your tagged call sites stay the same. That portability is the main reason teams prototype with array in tests and deploy with Redis or Memcached.

Install Memcached and the PHP extension

sudo apt install memcached php8.5-memcached
sudo systemctl enable --now memcached

Point Laravel at Memcached

CACHE_STORE=memcached

MEMCACHED_HOST=127.0.0.1
MEMCACHED_PORT=11211

In config/cache.php, the Memcached store accepts SASL credentials and custom server weights:

'memcached' => [
    'driver' => 'memcached',
    'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
    'sasl' => [
        env('MEMCACHED_USERNAME'),
        env('MEMCACHED_PASSWORD'),
    ],
    'options' => [
        // Memcached::OPT_CONNECT_TIMEOUT => 2000,
    ],
    'servers' => [
        [
            'host' => env('MEMCACHED_HOST', '127.0.0.1'),
            'port' => env('MEMCACHED_PORT', 11211),
            'weight' => 100,
        ],
    ],
],

Reference the Memcached protocol behaviour in the official Memcached documentation when tuning connection pools.

Operational caveats specific to Memcached

  1. Restarts evict everything. Unlike Redis with optional persistence, Memcached loses tagged metadata and values on process restart—plan warm-up jobs after deploys.
  2. Multi-node consistency. Laravel’s tag implementation stores reference keys. If clients hit different Memcached nodes with inconsistent key routing, tag flushes may miss entries. Use a single pool with consistent hashing or keep tag-heavy workloads on one logical cluster.
  3. Item size limit. The default 1 MB item cap applies to tagged payloads; large HTML fragments may need compression or fragment splitting.
  4. No secondary use. You still need Redis or the database for queues, locks, and sessions—Memcached rarely consolidates infrastructure the way Redis can.

When auditing an existing Memcached deployment, I log tag flush duration during staging load tests before signing off—a slow flush under write-heavy catalog updates is a signal to migrate hot tags to Redis. Performance tuning as a service line is covered under testing and optimization for Laravel applications.

After Tag Flush — Request CycleHTTP requestUser hits category pageCache missTagged key goneRebuildQuery + renderController checks Cache::tags([...])->get()Miss triggers expensive query onceThundering herdMany parallel missesUse Cache::lock()Warm after flushQueue job preloadsStable response times
The next HTTP request after a Laravel cache tag flush misses once, rebuilds from the database, and repopulates the tagged store.

How do you flush cache by tag safely in production Laravel apps?

Tag design matters as much as driver choice. Treat tags as part of your domain model, not ad-hoc strings scattered through controllers.

Centralise tag names

namespace App\Support;

final class CacheTags
{
    public static function products(): array
    {
        return ['products'];
    }

    public static function category(int $id): array
    {
        return ['products', 'category:'.$id];
    }

    public static function user(int $id): array
    {
        return ['user:'.$id, 'permissions'];
    }
}

Flush from model events

protected static function booted(): void
{
    static::saved(function (Product $product) {
        Cache::tags(CacheTags::category($product->category_id))->flush();
    });

    static::deleted(function (Product $product) {
        Cache::tags(CacheTags::products())->flush();
    });
}

Guard against stampedes with locks

$key = 'products.category.'.$id;
$tags = CacheTags::category($id);

$value = Cache::tags($tags)->get($key);

if ($value === null) {
    $value = Cache::lock('build-'.$key, 10)->block(5, function () use ($key, $tags) {
        return Cache::tags($tags)->rememberForever($key, fn () => $this->renderCategory());
    });
}

On API-heavy projects, pair tagged HTTP caching with the guidance in Laravel API best practices so ETags and application cache layers do not fight each other. For database-heavy rebuild paths, index tuning often matters as much as cache—see PostgreSQL for Laravel developers when PostgreSQL 18 backs your app.

Projects like Nepal Gift Card and Adventure Third Pole Trek rely on predictable cache invalidation because stale inventory or booking availability is a revenue problem, not a cosmetic glitch. Tagged flushes are how you keep that correctness without nightly full clears.

When should you choose Redis over Memcached for Laravel cache tags?

Use this decision frame before provisioning infrastructure on a greenfield Laravel 13 project:

  • Choose Redis when you need tags plus queues, rate limiting, locks, Horizon metrics, or broadcasting; when you want optional persistence; when one managed service should cover multiple Laravel subsystems.
  • Choose Memcached when your organisation already runs a mature Memcached 1.6.x fleet, workloads are strictly read-heavy HTML fragments, and losing cache on restart is acceptable.
  • Avoid tags on file/database drivers—refactor to Redis or Memcached instead of bolting on manual key lists.
  • Re-evaluate during cluster upgrades—Redis Cluster and Memcached pools both need validation that tag flushes reach every referenced key.

Cost-wise, a small dedicated Redis instance on a Rs 3,000–5,000/month VPS slice (~USD 22–37) often replaces separate Memcached plus auxiliary Redis installs, simplifying GitLab CI/CD deploy pipelines I run on shared EC2 infrastructure. Page-speed work still needs front-end and query optimisation—caching alone will not fix N+1 queries; combine tagged caches with speed optimization and technical SEO when public pages must pass Core Web Vitals.

Redis vs Memcached — Decision TreeNeed Laravel cache tags?NoYesfile / database OKRedis or MemcachedRedis — default pickMemcached fleetalready in prodAlso need queues or locks? → Redis consolidates infrastructure
Decision tree for Laravel cache tags with Redis vs Memcached — Redis is the default unless Memcached is already entrenched in your stack.

Enterprise applications with complex domain rules benefit from upfront cache design during planning—enterprise application development engagements should document tag vocabulary alongside database schema. If you inherit a site with mystery flush scripts, support and maintenance is often the fastest path to map existing keys before migrating drivers.

Debugging tag metadata during incidents is easier when you can inspect JSON payloads—keep a JSON formatter handy in staging while comparing cached API responses to live database rows. For public-facing Laravel sites, align cache TTLs with SEO crawl patterns described in SEO setup for Laravel sites.

Key Takeaways

  • Laravel cache tags work on Redis and Memcached, not on file or database drivers—plan your infrastructure accordingly.
  • Redis 8.10 is the default choice for Laravel 13 tagged caching because it also covers queues, locks, and optional persistence.
  • Memcached 1.6.x supports the same tag API but is volatile and sensitive to multi-node routing during tag flushes.
  • Centralise tag strings, flush from model events, and use cache locks to prevent thundering herds after invalidation.
  • Separate Redis logical databases or connections for cache versus queues to avoid cross-traffic eviction.
  • Load-test tag flush duration before peak traffic—slow flushes are a migration signal from Memcached to Redis.

People Also Ask

Can Laravel cache tags work with the file driver?

No. Laravel throws an exception if you call Cache::tags() while the default store is file or database. Switch CACHE_STORE to redis or memcached, or refactor to untagged keys with explicit TTLs if you cannot add a network cache yet.

Do cache tags slow down Laravel?

Tagged writes carry a small metadata overhead compared to plain Cache::put(). Reads are comparable. The performance cost shows up during large tag flushes under write-heavy load—measure in staging, not assumptions. Correctness from targeted invalidation usually saves more database time than metadata costs.

Are Laravel cache tags safe with Redis Cluster?

They can be, but all tag-related keys must land on nodes your client can reach consistently. Test flush operations after enabling cluster mode. Many teams run a non-clustered Redis instance dedicated to cache while clustering queue workloads separately.

Should tests use tagged caching?

Yes—use the array driver in phpunit.xml. It supports tags, resets between tests, and avoids needing Redis running on CI runners. Mirror production tag names in tests to catch typos early.

Ship tagged caching with the right backend from day one

Laravel cache tags with Redis vs Memcached boils down to operational fit: both honour the same application code, but Redis gives Laravel teams one durable, multi-purpose backend while Memcached suits narrow, existing cache farms. On new Laravel 13 builds I specify Redis, document tag vocabulary in the repo, and wire model events before launch so stale fragments never become a production surprise. If you are auditing cache architecture on a live app—or planning a Memcached-to-Redis migration—contact us to review your drivers, flush paths, and deploy pipeline. You can also browse the portfolio for Laravel systems where caching and invalidation were built in from the start, or read more on the blog and home page for related engineering guides.

Frequently Asked Questions

Labels on cached entries that let you flush every key sharing a tag in one call, without evicting unrelated cache data or maintaining manual key lists.

Yes. Laravel 13 documents both Redis 8.10 and Memcached 1.6.x as tag-capable drivers with the same Cache::tags() API. Redis is the practical default because it offers optional persistence, richer tooling, and fewer surprises in clustered setups. Memcached works on a single node but tag metadata can misbehave when clients hit different nodes with inconsistent key routing. Memcached also loses all tagged data on restart, whereas Redis can retain cache through RDB or AOF if configured.

No. Laravel throws a runtime exception if you call Cache::tags() while the default store is file or database. Switch CACHE_STORE to redis or memcached instead.

Choose Redis on greenfield Laravel 13 projects when you need tags plus queues, locks, rate limiting, Horizon, or broadcasting, or when optional persistence matters. Choose Memcached only if your team already runs a mature Memcached 1.6.x fleet, workloads are read-heavy HTML fragments, and losing cache on restart is acceptable. A small dedicated Redis slice at Rs 3,000–5,000/month (~USD 22–37) often replaces separate Memcached and auxiliary Redis installs, simplifying deployment on shared VPS infrastructure.

On Laravel 13 with PHP 8.3 or higher, install php8.5-redis or Predis via Composer, set CACHE_STORE=redis and REDIS_CLIENT=phpredis in .env, and confirm config/cache.php maps the redis store to a dedicated connection. In config/database.php, keep cache on logical database 1 and queues on database 0 so a runaway worker cannot evict hot keys. Smoke-test with php artisan tinker by writing, reading, and flushing a tagged key. Model observers should flush tags immediately after data changes.

Install memcached and php8.5-memcached, enable the service, then set CACHE_STORE=memcached with MEMCACHED_HOST and MEMCACHED_PORT in .env. Your tagged call sites stay identical to Redis—the driver swap is mostly environmental. config/cache.php accepts SASL credentials and server weights. After deploys, plan warm-up jobs because Memcached is purely volatile and restarts wipe tag metadata. Log tag flush duration during staging load tests before peak traffic; slow flushes under write-heavy catalog updates signal a move to Redis.

Tagged writes add small metadata overhead; reads are comparable. Large tag flushes under write-heavy load cost more—measure in staging, not assumptions.

Centralise tag names in a dedicated class—products, category:12, user:45—not ad-hoc strings scattered through controllers. Flush from model saved and deleted events so the next HTTP request rebuilds fresh data. Guard against stampedes with Cache::lock() around rememberForever rebuilds after a flush miss. Pair tagged caching with sensible TTLs and database indexes on rebuild paths. On projects like Nepal Gift Card, predictable invalidation matters because stale inventory is a revenue problem, not a cosmetic glitch.

They can work, but all tag-related keys must land on nodes your client can reach consistently. Test flush operations after enabling cluster mode—many production teams run a non-clustered Redis instance dedicated to cache while clustering queue workloads separately. Redis Cluster hash-slot rules differ from single-node setups, so validate that tag metadata and referenced keys remain coherent under your topology before signing off during infrastructure upgrades.

Everything is lost. Unlike Redis with optional RDB snapshots or AOF, Memcached is purely volatile—tag metadata and cached values vanish on process restart or deploy. The next request wave triggers cache miss stampedes unless you run warm-up jobs or use Cache::lock() around rebuilds. This is a primary reason I default to Redis on legal-tech portals where permission snapshots and document lists must invalidate predictably after uploads, not disappear unpredictably at restart.

config/database.php should map cache to one logical Redis database—commonly database 1—and queues or default work to another, such as database 0. A runaway queue worker writing heavily to the same connection can trigger memory pressure and eviction policies that delete hot cache keys unrelated to the job backlog. Keeping cache and queue traffic isolated protects tagged fragments serving public pages from being pushed out when Horizon or failed jobs spike write volume.

In practice, a small dedicated Redis instance on a Rs 3,000–5,000/month VPS slice (~USD 22–37) often replaces separate Memcached plus auxiliary Redis installs for queues and sessions. That consolidation simplifies GitLab CI/CD deploy pipelines on shared EC2 infrastructure and reduces operational surface area. Memcached can be leaner for pure object caching, but when tags, locks, and queues share one backend, Redis frequently wins on total infrastructure cost rather than per-megabyte RAM alone.

Memcached applies its default 1 MB item cap to tagged payloads as well. Large HTML fragments—category listing pages, CMS block output—may exceed that limit and fail or reject writes depending on client settings. Split fragments, compress output, or store smaller cache units. Redis does not share that exact 1 MB protocol constraint in the same way, which matters on eCommerce or directory sites caching full rendered category pages under tags like products and category:12.

Yes. Configure phpunit.xml to use the array driver, which supports tags, resets between tests, and avoids requiring Redis or Memcached in CI. Prototype tag vocabulary in tests with the same Cache::tags() call sites you deploy to Redis or Memcached. This catches driver exceptions early—file and database stores throw if you call Cache::tags()—and keeps tag flush logic verified without network cache dependencies on every GitLab CI pipeline run.

Laravel 13 documents tag support on Redis, Memcached, array, and DynamoDB. File and database drivers do not support tags; calling Cache::tags() against them throws a runtime exception. For production tagged caching, Redis 8.10 is the recommended default. Memcached 1.6.x works with identical API calls but carries multi-node routing caveats and no persistence. Use array in tests, then deploy to Redis unless your organisation already operates Memcached at scale.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: