DEV Community

Aditi Deshmukh
Aditi Deshmukh

Posted on

How Recursion Actually Works

When I first learned recursion, it honestly felt like magic.
A function calling itself again and again? I could write it, but I didn’t really get how it worked behind the scenes.

*If you’ve ever felt that too — don’t worry. In this post, we’ll break down recursion step-by-step and see how the stack plays a hidden but crucial role.
*

---

What Is Recursion?

Recursion is when a function calls itself to solve a smaller version of the same problem.

Every recursive function needs two things:

1.Base case — the condition that stops the recursion
2.Recursive case — the part where the function calls itself again

Example: Finding Factorial Using Recursion

function factorial(n) {
  if (n === 1) {
    return 1; // Base case
  } else {
    return n * factorial(n - 1); // Recursive call
  }
}

console.log(factorial(5)); // Output: 120``
Enter fullscreen mode Exit fullscreen mode

Behind the Scenes: The Stack in Action

_Each time a function runs, it’s placed on a call stack — a memory structure that follows Last In, First Out (LIFO).
So, the last function called is the first one to finish.
_

Step   | Function Call  | What Happens
-------|----------------|-------------------------
1      | factorial(5)   | Calls factorial(4)
2      | factorial(4)   | Calls factorial(3)
3      | factorial(3)   | Calls factorial(2)
4      | factorial(2)   | Calls factorial(1)
5      | factorial(1)   | Base case → returns 1

Enter fullscreen mode Exit fullscreen mode

Now the stack unwinds:

Step   | Returning To   | Calculation
-------|----------------|----------------
6      | factorial(2)   | 2 × 1 = 2
7      | factorial(3)   | 3 × 2 = 6
8      | factorial(4)   | 4 × 6 = 24
9      | factorial(5)   | 5 × 24 = 120

Enter fullscreen mode Exit fullscreen mode

Finally, the stack is empty — result: 120

Why the Stack Matters
The stack lets recursion pause each call until the next one finishes.
Imagine stacking plates in a cafeteria:
you add one plate per call, and when done, remove them from the top — one by one.

That’s exactly how recursion “returns” values.

Final Thoughts

Recursion isn’t magic — it’s just functions + a stack working together beautifully.
Once you understand that each call patiently waits on the stack, recursion becomes one of programming’s most elegant tools.

If recursion ever confuses you, just picture that stack of plates — it’ll click .

Thanks for reading!
If you enjoyed this post, follow me for more beginner-friendly programming blogs.

Top comments (1)

Collapse
 
queelius profile image
Alex Towell

Great post! The stack visualization really helps see what's happening.

But I'm wondering about something: does recursion always make problems smaller?

When Recursion Makes Things Bigger

In symbolic math, recursive steps often grow the expression:

// Expanding (x + y)²
function expand(expr) {
if (isFullyExpanded(expr)) return expr;

if (expr.type === 'square' && expr.inner.type === 'sum') {
  // (x + y)² → x² + 2xy + y²  (BIGGER!)
  return expand(x² + 2xy + y²);
}
Enter fullscreen mode Exit fullscreen mode

}

The expression gets larger through intermediate steps. Is this still recursion? Or am I mixing up different concepts?

Maybe Recursion Is Really About Search?

What if the pattern isn't "solve a smaller problem" but: "explore a state space until you reach a goal"?

  • Factorial: Search through decreasing integers until you hit 1
  • Symbolic expansion: Search through expression transformations until fully expanded
  • Proof search: Explore inference rules until you reach an axiom
  • Backtracking: Search a tree until you find a solution

In this view:

  • The "base case" is: "Did we find what we're searching for?" (not "is the problem size 1?")
  • The stack is: memory for exploring paths through possibility space
  • "Smaller" is just one direction of search, but not required

Am I Thinking About This Wrong?

The pedagogical definition ("function calls itself on smaller input") works beautifully for factorial and Fibonacci, but feels incomplete.

Is recursion actually controlled exploration using the call stack? Or am I overcomplicating something simple?

Would love to hear your thoughts!