
Symfony:symfony Cache Skill
- 440 installs
- 190 repo stars
- Updated August 6, 2026
- makfly/superpowers-symfony
symfony:symfony-cache is a Claude Code skill that configures Symfony Cache pools, tags, and invalidation so expensive queries and computed responses stay fast under load without serving stale data to PHP API consumers.
About
symfony:symfony-cache is a Symfony Superpowers skill from makfly/superpowers-symfony that implements caching with the Symfony Cache component. The skill configures cache pools in config/packages/cache.yaml, injects CacheInterface into services, sets TTL via ItemInterface expiresAfter, and uses cache tags for targeted invalidation while preventing stampede conditions. reference.md covers composer require symfony/cache, callback-based cache->get patterns, pool adapters, and tag invalidation strategies for Doctrine-heavy Symfony apps. Developers reach for symfony:symfony-cache when API responses or repository queries bottleneck under load and need Redis-backed pools with deterministic invalidation. The skill ships inside the 44-skill superpowers-symfony bundle alongside Messenger and Scheduler async skills for production Symfony 7 deployments.
- Cache pool configuration
- Tag-based invalidation
- Redis and filesystem adapters
- HTTP cache headers synergy
- Warmup and stampede guards
Symfony:Symfony Cache by the numbers
- 440 all-time installs (skills.sh)
- Ranked #1,006 of 4,492 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 11, 2026 (Skillselion catalog sync)
npx skills add https://github.com/makfly/superpowers-symfony --skill symfonysymfony-cacheAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 440 |
|---|---|
| repo stars | ★ 190 |
| Last updated | August 6, 2026 |
| Repository | makfly/superpowers-symfony ↗ |
How do you configure Symfony cache tags and invalidation?
Configure Symfony Cache pools, tags, and invalidation so expensive queries and computed responses stay fast under load without serving stale data.
Who is it for?
Symfony developers optimizing Doctrine query caches and computed API responses with tagged pool invalidation under production load.
Skip if: Teams needing only browser CDN caching or front-end asset optimization without Symfony Cache component configuration.
When should I use this skill?
Symfony API endpoints serve stale or slow cached data and need cache pool, tag, or stampede configuration.
What you get
cache.yaml pool definitions, tagged cache items, invalidation rules, and operational validation evidence for retry scenarios.
- cache.yaml configuration
- Tagged cache invalidation rules
- Operational validation evidence
By the numbers
- Part of the superpowers-symfony bundle containing 44 Symfony expert skills
Files
Symfony Cache (Symfony)
Use when
- Implementing asynchronous workflows with Messenger/Scheduler/Cache.
- Stabilizing retries and failure transports.
Default workflow
1. Define async contract and delivery semantics. 2. Implement idempotent handlers and routing strategy. 2. Configure retries, failure transport, and observability. 2. Validate success/failure replay scenarios.
Guardrails
- Assume at-least-once delivery, not exactly-once.
- Keep handlers deterministic and side-effect aware.
- Surface poison-message handling strategy.
Progressive disclosure
- Use this file for execution posture and risk controls.
- Open references when deep implementation details are needed.
Output contract
- Async config/handlers updated.
- Retry/failure policy decisions.
- Operational validation evidence.
References
reference.mddocs/complexity-tiers.md
Reference
Symfony Cache
Installation
composer require symfony/cacheBasic Usage
Inject Cache
<?php
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
class ProductService
{
public function __construct(
private CacheInterface $cache,
) {}
public function getProduct(int $id): Product
{
return $this->cache->get("product_{$id}", function (ItemInterface $item) use ($id) {
$item->expiresAfter(3600); // 1 hour
return $this->repository->find($id);
});
}
}Delete Cache
$this->cache->delete("product_{$id}");Configuration
# config/packages/cache.yaml
framework:
cache:
# Default cache adapter
app: cache.adapter.redis
system: cache.adapter.system
# Define pools
pools:
cache.products:
adapter: cache.adapter.redis
default_lifetime: 3600
cache.api_responses:
adapter: cache.adapter.filesystem
default_lifetime: 300
cache.sessions:
adapter: cache.adapter.redis
default_lifetime: 86400Cache Adapters
Redis
# .env
REDIS_URL=redis://localhost:6379
# config/packages/cache.yaml
framework:
cache:
app: cache.adapter.redis
default_redis_provider: '%env(REDIS_URL)%'Filesystem
framework:
cache:
app: cache.adapter.filesystemAPCu (In-memory)
framework:
cache:
app: cache.adapter.apcuChained (Multi-tier)
framework:
cache:
pools:
cache.products:
adapters:
- cache.adapter.apcu # Fast, local
- cache.adapter.redis # Shared, persistentCache Pools
Inject Specific Pool
<?php
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Contracts\Cache\CacheInterface;
class ProductService
{
public function __construct(
#[Autowire(service: 'cache.products')]
private CacheInterface $cache,
) {}
}PSR-6 Interface
<?php
use Psr\Cache\CacheItemPoolInterface;
class LegacyService
{
public function __construct(
private CacheItemPoolInterface $cache,
) {}
public function getData(string $key): mixed
{
$item = $this->cache->getItem($key);
if (!$item->isHit()) {
$item->set($this->fetchData());
$item->expiresAfter(3600);
$this->cache->save($item);
}
return $item->get();
}
}Cache Tags
Tags allow invalidating groups of cache items:
<?php
use Symfony\Contracts\Cache\TagAwareCacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
class ProductService
{
public function __construct(
private TagAwareCacheInterface $cache,
) {}
public function getProduct(int $id): Product
{
return $this->cache->get("product_{$id}", function (ItemInterface $item) use ($id) {
$item->expiresAfter(3600);
$item->tag(['products', "product_{$id}", "category_{$categoryId}"]);
return $this->repository->find($id);
});
}
public function getProductsByCategory(int $categoryId): array
{
return $this->cache->get("category_{$categoryId}_products", function (ItemInterface $item) use ($categoryId) {
$item->tag(['products', "category_{$categoryId}"]);
return $this->repository->findByCategory($categoryId);
});
}
public function invalidateProduct(int $id): void
{
// Invalidate specific product
$this->cache->invalidateTags(["product_{$id}"]);
}
public function invalidateCategory(int $categoryId): void
{
// Invalidate all products in category
$this->cache->invalidateTags(["category_{$categoryId}"]);
}
public function invalidateAllProducts(): void
{
// Invalidate all product caches
$this->cache->invalidateTags(['products']);
}
}Configuration for Tag-Aware Cache
framework:
cache:
pools:
cache.products:
adapter: cache.adapter.redis
tags: true # Enable tag supportHTTP Cache
Response Caching
<?php
use Symfony\Component\HttpFoundation\Response;
class ProductController
{
#[Route('/products/{id}')]
public function show(Product $product): Response
{
$response = $this->render('product/show.html.twig', [
'product' => $product,
]);
// Public cache (CDN, proxy)
$response->setPublic();
$response->setMaxAge(3600);
$response->setSharedMaxAge(3600);
// ETag for validation
$response->setEtag(md5($response->getContent()));
return $response;
}
}Cache-Control Headers
$response->headers->set('Cache-Control', 'public, max-age=3600, s-maxage=3600');
// Or using methods
$response->setPublic();
$response->setPrivate();
$response->setMaxAge(3600); // Browser cache
$response->setSharedMaxAge(3600); // CDN/proxy cache
$response->setExpires(new \DateTime('+1 hour'));Cache Attributes
<?php
use Symfony\Component\HttpKernel\Attribute\Cache;
class ProductController
{
#[Route('/products/{id}')]
#[Cache(public: true, maxage: 3600, smaxage: 3600)]
public function show(Product $product): Response
{
return $this->render('product/show.html.twig', [
'product' => $product,
]);
}
}Cache Warmup
<?php
// src/Cache/ProductCacheWarmer.php
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
class ProductCacheWarmer implements CacheWarmerInterface
{
public function __construct(
private ProductRepository $products,
private CacheInterface $cache,
) {}
public function warmUp(string $cacheDir, ?string $buildDir = null): array
{
foreach ($this->products->findPopular(100) as $product) {
$this->cache->get("product_{$product->getId()}", fn() => $product);
}
return [];
}
public function isOptional(): bool
{
return true;
}
}Clear Cache
# Clear all caches
bin/console cache:clear
# Clear specific pool
bin/console cache:pool:clear cache.products
# Clear by tag
bin/console cache:pool:invalidate-tags cache.products productsBest Practices
1. Use tags: For flexible invalidation 2. Set TTLs: Don't cache forever 3. Warm critical caches: Pre-populate on deploy 4. Monitor hit rates: Track cache effectiveness 5. Chain adapters: Fast local + shared persistent 6. Invalidate precisely: Don't clear everything
Skill Operating Checklist
Design checklist
- Confirm operation boundaries and invariants first.
- Minimize scope while preserving contract correctness.
- Test both happy path and negative path behavior.
Validation commands
- php bin/console messenger:consume --limit=1
- php bin/console messenger:failed:show
- ./vendor/bin/phpunit --filter=Messenger
Failure modes to test
- Invalid payload or forbidden actor.
- Boundary values / not-found cases.
- Retry or partial-failure behavior for async flows.
Related skills
How it compares
Pick symfony:symfony-cache over Doctrine fetch-mode tuning when the bottleneck is repeated computed responses needing pool-level tag invalidation.
FAQ
What Symfony Cache features does symfony:symfony-cache cover?
symfony:symfony-cache covers Symfony Cache pool configuration in cache.yaml, CacheInterface injection, TTL via expiresAfter, tag-based invalidation, and stampede prevention for expensive callback-backed cache misses.
When should I use cache tags in Symfony?
Use symfony:symfony-cache cache tags when related entities change and multiple cached keys must invalidate together—for example, product lists and detail pages after a catalog update—without flushing the entire pool.