← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Memory Leak

performance PHP 5.0+ Intermediate
debt(d7/e5/b5/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints list xdebug, blackfire, and phpstan — these are specialist tools, but memory leaks in long-running workers typically manifest only under sustained load or after many iterations, meaning they are often not caught until runtime testing or production monitoring. phpstan cannot catch runtime accumulation patterns; xdebug/blackfire require deliberate profiling sessions. The leak is silent in normal short-lived FPM requests and only surfaces in CLI/queue contexts under load, pushing this above d5.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix lists several mitigations (unset() variables, avoid circular refs, use generators, monitor RSS), but these are not single-line fixes. Common mistakes include static caches with no eviction, unremoved event listeners, and circular references — each requires identifying the offending pattern across potentially many places in a worker's lifecycle. It is not a single-call swap (e1/e3) nor a full architectural rework (e7+), but a meaningful refactor within the affected worker component(s).

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). The applies_to scope is limited to cli and queue-worker contexts (not all PHP), which reduces reach compared to a universal concern. However, within those contexts, the risk shapes every design decision: caching strategies, event-listener patterns, and object lifecycle management must all be considered. Any developer working on long-running PHP processes carries this mental overhead continuously, making it a persistent tax on those work streams.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field states exactly the trap: developers believe PHP's garbage collector prevents all memory leaks. This contradicts how GC is understood in other languages and in PHP's own short-lived request model — the GC does handle circular refs in short scripts, so the assumption feels justified. The leap to long-running workers where static properties, event listeners, and growing caches accumulate is non-obvious and contradicts the developer's prior correct experience with PHP, placing this at t7.

About DEBT scoring →

Also Known As

PHP memory leak memory growth circular reference leak

TL;DR

Memory allocated during execution that is never released, causing PHP processes to grow until they exhaust available memory or are restarted.

Explanation

PHP processes under PHP-FPM are recycled after a configurable number of requests (pm.max_requests), which masks memory leaks in normal web serving. However, in long-running processes (CLI scripts, job workers, Fibers, ReactPHP) leaks accumulate indefinitely. Common PHP causes include: circular references not collected by the cyclic garbage collector (fixed in PHP 5.3+), accumulating event listeners, large global arrays, and caching without eviction. Use memory_get_usage() or Xdebug's memory profiler to diagnose, and unset() large variables and circular structures when done.

Common Misconception

PHP's garbage collector prevents all memory leaks. PHP's GC handles circular references but long-running processes (workers, CLI scripts) can still accumulate memory via static properties holding references, event listeners not removed, and growing caches with no eviction policy.

Why It Matters

In long-running PHP processes (queues, daemons, FPM workers) memory leaks cause worker memory to grow until the OS kills the process — interrupting in-flight work and triggering restarts.

Common Mistakes

  • Circular references between objects — PHP's garbage collector handles most but not all cyclic structures.
  • Growing static arrays or caches with no eviction — each request adds entries that never get freed.
  • Event listeners registered but never removed — the listener holds a reference keeping the listened-to object alive.
  • Not using weak references for observer patterns — strong references in event systems are a common leak source.

Code Examples

✗ Vulnerable
// Circular references prevent garbage collection before PHP 5.3 cycle collector
class Node {
    public ?Node $parent = null;
    public array $children = [];
}
$parent = new Node();
$child  = new Node();
$child->parent    = $parent;       // child → parent
$parent->children[] = $child;      // parent → child  (cycle)
unset($parent, $child);            // cycle collector must clean up
✓ Fixed
// Use WeakReference to break cycles
class Node {
    public ?\WeakReference $parent = null;
    public array $children = [];
}
$parent = new Node();
$child  = new Node();
$child->parent = \WeakReference::create($parent); // won't prevent GC
$parent->children[] = $child;

// Retrieve: $child->parent?->get()

// In long-running scripts (queues, CLI): track memory
if (memory_get_usage(true) > 200 * 1024 * 1024) {
    gc_collect_cycles();
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 79
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 6 pings T 6 pings F 1 ping S 9 pings S 6 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Scrapy 28 Google 7 Amazonbot 7 Perplexity 6 Ahrefs 6 SEMrush 5 Unknown AI 3 Qwen 1 Bing 1 Meta AI 1
crawler 63 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
In long-running workers: unset() large variables after use, avoid circular references, use generators for large datasets, monitor RSS memory
📦 Applies To
PHP 5.0+ cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Long-running CLI/queue worker with growing RSS memory; circular object references; array accumulation in loops
Auto-detectable: ✓ Yes xdebug blackfire phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: High Context: File Tests: Update
CWE-401

✓ schema.org compliant