Node Cache: Overview and Setup#

What Node Cache is and is not#

Node Cache is:

  • a local APCu -> SQLite cache topology;

  • persistent across PHP-FPM or application-worker restarts when the local SQLite file survives;

  • compatible with normal Cache reads, writes, tags, batches, deferred writes, metrics, and remember();

  • fail-open by default for APCu and SQLite runtime failures.

Node Cache is not:

  • a shared cache between servers or containers;

  • a distributed lock, queue, counter, rate limiter, or session store;

  • a substitute for an authoritative database;

  • an immediate global-revocation mechanism for security-sensitive data.

For cross-node invalidation while retaining local cached values, use Cluster Cache.

Topology and request lifecycle#

The topology is deliberately simple:

PHP request / worker
       |
       v
Cache facade (PSR-6 / PSR-16 / tags / remember)
       |
       v
APCu L1, when enabled and available
       |
       | miss
       v
SQLite L2 on this node's local disk
       |
       | miss
       v
application resolver / authoritative source

Read lifecycle#

  1. APCu is checked when enabled.

  2. On an APCu miss, SQLite is checked.

  3. A SQLite hit is promoted to APCu with its remaining TTL.

  4. A miss returns the caller’s default, or remember() resolves the value.

  5. Expired rows are misses. They are left for bounded maintenance rather than being deleted on every read.

Write lifecycle#

  1. A normal write is persisted to SQLite first.

  2. A successful SQLite write is copied to APCu when APCu is available.

  3. A delete or namespace clear is attempted across both layers.

  4. Tagged entries and tag-version metadata are local to this node.

With the default failOpen: true, an L2 failure can fall back to an L1 write so the request can continue. This is a resilience choice: the L1-only value is lost when that PHP/APCu process is restarted. Set failOpen: false when a storage failure must be surfaced to the application instead.

Requirements and filesystem placement#

Node Cache requires ext-pdo with the SQLite driver. APCu is optional. APCu is used only if all of the following are true:

  • apcuEnabled is true (the default);

  • the APCu extension is loaded;

  • APCu is enabled for the executing PHP SAPI.

Put the SQLite database in a writable directory that is local to the node, outside the repository and web root. SQLite creates companion -wal and -shm files, so the directory—not merely the database file—must be writable by the application account.

Do not use NFS, SMB, a synchronized folder, or another network/shared filesystem for the Node Cache SQLite file. The factory rejects symlinked and world-writable cache directories as a safety measure.

Recommended layout:

/var/cache/my-application/
    node-cache.sqlite
    node-cache.sqlite-wal
    node-cache.sqlite-shm
    locks/                 # optional, used by remember() file locks

Configuration and bootstrap#

Create one NodeCacheConfig for each application node. The SQLite path and lock directory should be local; the namespace names the logical cache within that database.

use Infocyph\CacheLayer\Node\NodeCache;
use Infocyph\CacheLayer\Node\NodeCacheConfig;

$config = new NodeCacheConfig(
    sqliteFile: '/var/cache/my-application/node-cache.sqlite',
    namespace: 'catalog',
    lockDirectory: '/var/cache/my-application/locks',
    busyTimeoutMs: 1_000,
    apcuEnabled: true,
    failOpen: true,
);

$cache = NodeCache::create($config);

Configuration reference#

sqliteFile

Required path to the SQLite database. It must not contain a NUL byte.

namespace

Logical cache partition inside the SQLite database. It defaults to default and is sanitized before use. Use a stable, application-specific name such as catalog or billing.

lockDirectory

Optional directory for the file lock provider used by remember(). Leave it null to use the library default, or point it at a local writable directory for an explicit deployment layout.

busyTimeoutMs

SQLite busy timeout in milliseconds. The default is 1,000. Increase it cautiously only when legitimate local write contention is observed; it does not make a shared/network filesystem safe.

apcuEnabled

Enables APCu L1 when the extension and SAPI support it. Set it to false for deterministic SQLite-only behavior, CLI jobs, or troubleshooting.

failOpen

Defaults to true. When true, recoverable layer failures are treated as cache degradation where possible. When false, APCu/SQLite failures propagate to the caller.

lockProvider

Optional LockProviderInterface used by remember(). When omitted, Node Cache uses its local file-lock default. Supply a shared RedisLockProvider or ValkeyLockProvider when multiple application nodes must coordinate one remember() resolver.

use Infocyph\CacheLayer\Cache\Lock\RedisLockProvider;

$config = new NodeCacheConfig(
    sqliteFile: '/var/cache/my-application/node-cache.sqlite',
    namespace: 'catalog',
    lockProvider: new RedisLockProvider($redis, 'catalog:remember:'),
);