APCu — In-Process User Cache
debt(d7/e3/b3/t7)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints list only Blackfire and Xdebug (profilers), and automated detection is marked 'no'. Misuse — such as deploying APCu in a multi-server environment expecting shared state, or not checking the success parameter of apcu_fetch() — won't be caught by compilers or linters. You'd only discover the problem through careful code review, runtime testing, or observing inconsistent cache behavior in production. Not quite d9 because profiling tools like Blackfire can reveal the redundant computation or cache miss patterns.
Closest to 'simple parameterised fix' (e3). The quick_fix is straightforward: swap apcu_store/apcu_fetch calls for Redis/Memcached calls when multi-server is needed, or add TTL parameters and success-flag checks. These are localized changes within the caching layer, typically touching a few files but not requiring architectural rework. If APCu is used behind a cache abstraction (PSR-6/16), it could even be e1, but commonly it's a small refactor in one component.
Closest to 'localised tax' (b3). APCu is typically used as a caching layer within a single component or service layer. It applies to web and CLI contexts but its reach is limited — it doesn't define system architecture. If you need to replace it (e.g., moving to multi-server), the change is contained to wherever cache calls are made. It doesn't impose a persistent tax on unrelated work streams.
Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field is critical: developers coming from Redis/Memcached expect APCu to be shared across all requests and all servers. The term 'shared memory' in APCu's description further misleads — it IS shared memory within a single server's PHP-FPM pool, but NOT across servers. Additionally, apcu_fetch() returning false for both cache misses and legitimately cached false values is a classic gotcha that contradicts typical get/fetch semantics. These traps seriously contradict expectations from similar caching concepts.
Also Known As
TL;DR
Explanation
APCu (APC User Cache) provides a key-value store in shared memory segments accessible to all PHP-FPM worker processes on a single server. With no serialisation over a network socket, APCu reads are extremely fast — nanoseconds vs microseconds for Redis. Ideal for: parsed application configuration, compiled route tables, permission trees, and any rarely-changing but frequently-read data. Limitations: data is local to one server (multi-server deployments need a distributed cache for shared state) and all data is lost on PHP-FPM restart. Use apcu_store(), apcu_fetch(), apcu_exists(), and apcu_delete(). Check memory usage with apcu_sma_info().
Diagram
flowchart TD
REQ[PHP Request] --> CHECK{APCu cache<br/>has key?}
CHECK -->|HIT| RETURN[Return cached value<br/>O of 1 microseconds]
CHECK -->|MISS| DB[(Database or API)]
DB --> STORE[Store in APCu<br/>shared memory]
STORE --> RETURN
subgraph Shared Memory
W1[Worker 1] & W2[Worker 2] & W3[Worker 3]
W1 & W2 & W3 <-->|all share| MEM[(APCu<br/>in-process cache<br/>per server)]
end
INFO[No network hop<br/>Same process memory<br/>Lost on restart]
style RETURN fill:#238636,color:#fff
style MEM fill:#1f6feb,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Using APCu in a multi-server environment expecting shared state — APCu is per-server, not distributed; use Redis for that.
- Not setting a reasonable TTL — stale data lives forever without expiry.
- Not checking apcu_fetch() return value — it returns false for a cache miss, which is falsy and can be confused with a cached false value; use the success parameter.
- Caching objects that hold database connections or file handles — those are not serializable.
Avoid When
- Multi-server deployments — APCu is per-process/per-server and does not share data across nodes.
- Storing large objects — APCu memory is shared with PHP workers and exhausting it crashes requests.
- Data that must be consistent across all servers — use Redis or Memcached for shared cache.
- CLI scripts — APCu in CLI uses a separate memory pool isolated from the web server processes.
When To Use
- Single-server applications or worker processes where shared-memory cache is sufficient.
- Caching config, translations, or compiled data that is identical across requests on the same server.
- Ultra-low-latency caching — APCu is faster than Redis because there is no network roundtrip.
- OPcache extension companion — APCu caches user data while OPcache caches compiled bytecode.
Code Examples
// Miss detection bug — cached false indistinguishable from cache miss:
$result = apcu_fetch('key');
if (!$result) { // Wrong — also triggers when cached value is false or 0
$result = expensiveQuery();
apcu_store('key', $result, 300);
}
// Correct:
$result = apcu_fetch('key', $success);
if (!$success) {
$result = expensiveQuery();
apcu_store('key', $result, 300);
}
// APCu — in-process shared memory cache (same server, same PHP-FPM pool)
// Install: pecl install apcu; extension=apcu.so in php.ini
// Store & retrieve
apc_store('config:theme', 'dark', 3600); // TTL in seconds
$theme = apc_fetch('config:theme', $success);
if (!$success) { /* cache miss */ }
// Atomic increment — race-condition-free counters
apc_inc('page_views:home');
// Clear specific key or all
apc_delete('config:theme');
apc_clear_cache();
// Good for: PHP-computed config, feature flags, hot lookup tables
// Not good for: session data, shared across multiple servers (use Redis instead)