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

Recursion Patterns

Algorithms PHP 5.0+ Intermediate
debt(d7/e5/b3/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7); phpstan can flag some recursive patterns but stack overflow on deep input typically only surfaces at runtime with real data.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5); quick_fix says convert recursion to iteration with explicit stack — that's a meaningful refactor of the algorithm, not a one-line change.

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

Closest to 'localised tax' (b3); recursive functions are typically scoped to specific traversal/parsing components rather than load-bearing across the whole system.

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

Closest to 'notable trap (documented gotcha)' (t5); misconception that recursion is elegant/performant — PHP lacks tail-call optimisation and naive recursion is exponential, a gotcha most devs learn after hitting it.

About DEBT scoring →

Also Known As

tail recursion recursive function call stack

TL;DR

Functions that call themselves with smaller inputs — powerful for tree traversal, divide-and-conquer, and mathematical sequences, but requiring careful base cases and stack depth management.

Explanation

Recursion requires a base case (terminates) and a recursive case (reduces toward base case). Patterns: linear recursion (factorial), tail recursion (optimisable to iteration), tree recursion (Fibonacci naive), mutual recursion (two functions call each other). PHP's default stack depth handles ~few thousand recursive calls; deep recursion needs iteration or explicit stack. Memoisation converts exponential tree recursion to linear. Understanding recursion is prerequisite for tree traversal, graph algorithms, and divide-and-conquer.

Diagram

flowchart TD
    CALL[Function call] --> CHECK{Base case?}
    CHECK -->|yes| RETURN[Return directly<br/>no recursion]
    CHECK -->|no| SMALLER[Recurse with<br/>smaller input]
    SMALLER --> CALL
    subgraph Stack Frames
        F1[fib 5]
        F2[fib 4]
        F3[fib 3]
        F1 --> F2 --> F3
    end
    subgraph Tail Recursion
        TR[Last operation is<br/>the recursive call]
        TR -->|optimised by compiler| LOOP[Converted to loop<br/>no stack growth]
    end
    OVF[Stack overflow] -.->|too many frames| SMALLER
style RETURN fill:#238636,color:#fff
style OVF fill:#f85149,color:#fff
style LOOP fill:#238636,color:#fff

Common Misconception

Recursion is always elegant and performant — naive recursion without memoisation is often O(2ⁿ); PHP does not optimise tail calls, so deep recursion risks stack overflow.

Why It Matters

Tree traversal, directory scanning, JSON parsing, and syntax tree processing are all naturally recursive — understanding the patterns prevents stack overflows and exponential time complexity.

Common Mistakes

  • No base case or wrong base case — infinite recursion causing stack overflow.
  • PHP default stack depth ~few thousand calls — recursing over large directory trees without iteration risks fatal errors.
  • Exponential recursion without memoisation — fib(40) makes ~1 billion calls without memoisation.
  • Passing large data structures by value in recursive calls — each stack frame copies the data.

Code Examples

✗ Vulnerable
// No memoisation — exponential O(2ⁿ):
function fib(int $n): int {
    if ($n <= 1) return $n;
    return fib($n-1) + fib($n-2); // fib(5) calls fib(3) twice, fib(2) thrice...
}
fib(40); // ~1 billion function calls — takes seconds
✓ Fixed
// Memoised — O(n) with tail recursion alternative:
function fib(int $n, array &$memo = []): int {
    if ($n <= 1) return $n;
    return $memo[$n] ??= fib($n-1, $memo) + fib($n-2, $memo);
}

// Iterative for deep sequences — no stack risk:
function fibIter(int $n): int {
    [$a, $b] = [0, 1];
    for ($i = 2; $i <= $n; $i++) [$a, $b] = [$b, $a+$b];
    return $b;
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 101
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping S 0 pings M 0 pings T 1 ping W 1 ping T 2 pings F 0 pings S 3 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 1 ping W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 1 ping S 1 ping M
PetalBot 1
Google 1
Scrapy 12 Amazonbot 10 Perplexity 9 SEMrush 7 PetalBot 6 Google 4 Ahrefs 4 ChatGPT 4 Claude 3 Bing 3 Brave Search 3 Unknown AI 2 Twitter/X 2 Meta AI 1 Applebot 1
crawler 66 crawler_json 5
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
Traversal algorithms Traversal is the process of visiting every element in a data structure exactly once, following a specific order or strategy to access each node or item.

Traversal is the foundation of nearly every algorithm that processes collections—searching, sorting, pathfinding, and serialization all depend on visiting elements in a controlled order. Mastering traversal patterns unlocks your ability to work with any data structure.

💡 Always check for null/None before accessing children, and always track visited nodes in graphs.

Ask Codex about Traversal →
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Add a depth limit parameter to every recursive function and convert deep recursion to iteration with an explicit stack when processing user-controlled input
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
Recursive function processing user-supplied input depth without limit; PHP stack overflow on deep nested data
Auto-detectable: ✓ Yes phpstan xdebug
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-674


✓ schema.org compliant