Caching in Pionia

This guide is for Pionia Shop developers who need application-level caching — Moonlight APIs use POST for reads, so HTTP caches do not help; cache expensive product.list results in Redis or filesystem instead.

What you will learn

  • How to pick a cache store in environment/settings.ini
  • How to read and write keys from services with app()->cacheInstance()
  • When GenericService list/retrieve TTL applies to Pionia Shop endpoints
Before you start

How it works

flowchart LR
  Action["product.list action"] --> CM[CacheManager]
  CM --> Hit{Key exists?}
  Hit -->|Yes| Return[Cached JSON rows]
  Hit -->|No| DB[("Porm / tasks table")]
  DB --> Store[Write cache with TTL]
  Store --> Return
  CM --> Backend["filesystem / redis / apcu / database"]

Pionia v3 ships a native PSR-16 cache layer (PioniaCache + CacheManager).

Because Moonlight APIs use POST for reads and writes, HTTP caches do not apply — use application-level caching instead.

Choose a store

environment/settings.ini:

[cache]
STORE=filesystem
TTL=3600

[cache_filesystem]
path=storage/cache

[cache_redis]
host=127.0.0.1
port=6379
prefix=pionia:
StoreSTORE valueBest for
Filesystemfilesystem (default)Single server, no extensions
ArrayarrayTests, per-worker memory
NullnullDisable caching without code changes
DatabasedatabaseShared cache via PDO
APCuapcuRoadRunner / FPM workers on one host
RedisredisProduction clusters

Aliases: file, memory, void, db.

Use in code

app()->cacheInstance()->set('pionia-shop:project:1:tasks', $rows, 300);
$value = app()->cacheInstance()->get('pionia-shop:project:1:tasks');

// Named store
app()->cache()->store('redis')->set('session:ada@pionia.shop', $payload, 900);

CLI

php pionia cache:clear
php pionia cache:prune
php pionia cache:delete my_key

GenericService list/retrieve cache

On services extending GenericService:

public ?int $cacheListTtl = 60;      // seconds, null = off
public ?int $cacheRetrieveTtl = 300;

Cache keys include table, filters, pagination, and request parameters. Use for expensive list/retrieve endpoints; invalidate with recached() on the service when data changes (see Actions).

Custom adapters

Register in a Provider:

public function configureCaching(\Pionia\Cache\CacheManager $cache): void
{
    $cache->extend('memcached', function ($app, array $config) {
        return new MemcachedCacheAdapter(/* ... */);
    });
}

RoadRunner note

Each worker has its own memory. Use Redis, database, or filesystem stores when cache must be shared across workers.

Common mistakes

  • Using array cache with multiple RoadRunner workers — each worker has isolated memory; use Redis or filesystem.
  • Caching without invalidation — call recached() after product.create / product.update or stale lists appear.
  • Expecting CDN/browser cache on POST — only application-level PSR-16 caching applies to Moonlight reads.
  • Forgetting cache:clear after deploy — old serialized payloads can linger in filesystem/Redis stores.

What’s next

Generic services

List/retrieve TTL on Pionia Shop services.

Performance (Porm)

Query-level optimization.

RoadRunner

Shared cache across workers.