What Is the Maximum Recursion Depth and How Do You Increase It?
Recursion depth is the number of nested function calls active at one moment, and Python's default maximum is 1000. Past that, CPython raises RecursionError: maximum recursion depth exceeded. You raise the limit with sys.setrecursionlimit(n), but that only changes a counter. The real limit is the memory set aside for the call stack. When the counter is set higher than the stack allows, the process crashes instead of raising an error. Java and C++ have no counter at all; the stack limit is their only limit.
What Recursion Depth Is
Every function call pushes a frame onto the call stack. A frame is a block of memory holding the arguments, local variables, and the return address. A recursive function pushes one frame per nested call and pops them as the calls return. Depth is the height of that stack at its tallest point. A recursive factorial of 500 reaches depth 500. A depth-first search on a path graph with 100,000 nodes reaches depth 100,000, which is where the limit becomes a practical problem.
Python: The 1000 Limit and sys.setrecursionlimit
import sys print(sys.getrecursionlimit()) # 1000 by default def depth(n): return 0 if n == 0 else 1 + depth(n - 1) print(depth(900)) # 900 # depth(1100) raises RecursionError sys.setrecursionlimit(10_000) print(depth(9_000)) # 9000
The limit exists to turn an infinite recursion into a clean exception instead of a crash. Raising it to 10,000 is safe on any normal machine. Raising it to 1,000,000 is not. The interpreter can exceed the C stack, and the result is a segmentation fault with no traceback.
Two details are worth knowing. Since Python 3.11, calls from Python code to Python code no longer use the C stack, so deep pure-Python recursion is safer than it was. Calls that pass through C functions, such as sorted with a Python key, still use it. And the limit is per interpreter, not per thread, so setting it once applies everywhere.
The Real Limit: Thread Stack Size
The hard limit is the stack memory of the thread running the recursion. On Linux the main thread gets 8 MB by default, set by ulimit -s. On Windows the main thread of the Python executable gets about 2 MB. When the recursion needs more than that, the process is killed regardless of what setrecursionlimit says.
The reliable way to run deep recursion in Python is to run it in a thread with a larger stack.
import sys import threading sys.setrecursionlimit(1_000_000) threading.stack_size(512 * 1024 * 1024) # 512 MB for the new thread def main(): print(depth(200_000)) t = threading.Thread(target=main) t.start() t.join()
This pattern is the usual fix for online judges. LeetCode problems such as longest increasing path in a matrix can reach depth in the tens of thousands with a recursive memoized search. The thread approach or an iterative rewrite is what gets a Python submission accepted.
Java and C++
| Language | Default limit | What happens | How to increase |
|---|---|---|---|
| Python | Counter of 1000 frames | RecursionError | sys.setrecursionlimit, then a bigger thread stack |
| Java | No counter; thread stack, usually 512 KB to 1 MB | StackOverflowError | -Xss flag, or new Thread(null, task, "name", stackSize) |
| C++ | No counter; process stack, 8 MB on Linux, 1 MB on Windows | Segmentation fault | ulimit -s, the linker /STACK option, or a thread with a larger stack |
Java throws StackOverflowError at a depth that depends on frame size, typically 10,000 to 20,000 frames for a small method. java -Xss64m Main raises the main thread's stack to 64 MB. The Thread constructor with a stackSize argument does the same for one thread.
C++ has no guard at all. Exceeding the stack is undefined behavior and usually a crash. ulimit -s unlimited before running, or the /STACK:268435456 linker flag on Windows, raises the limit. Compilers also remove some tail recursion at optimization level 2 and above, but relying on that is fragile.
When to Convert Recursion to Iteration
Convert to iteration when the depth can grow with the input size. Tree recursion on a balanced tree has depth log n and is fine. Recursion over a linked list, a path-shaped graph, or a long array has depth n and will fail on large inputs. The conversion is mechanical: keep an explicit stack that stores what the frame would have stored.
def dfs_iterative(graph, start): seen = {start} stack = [start] while stack: node = stack.pop() for nxt in graph[node]: if nxt not in seen: seen.add(nxt) stack.append(nxt) return seen
The iterative version uses heap memory, which is limited only by RAM, so a graph of ten million nodes is no problem. Memoized recursion converts to bottom-up dynamic programming the same way: fill a table in the order the recursion would have returned.
Key Takeaways
- Recursion depth is the number of nested calls; Python stops at 1000 by default with a RecursionError.
sys.setrecursionlimitraises the counter; a bigger thread stack viathreading.stack_sizeraises the real limit.- Java throws StackOverflowError and is tuned with
-Xss; C++ crashes and is tuned with the OS or linker stack size. - When depth grows with input size, rewrite with an explicit stack or bottom-up dynamic programming.
- Recursion patterns and their iterative equivalents are taught in Grokking the Art of Recursion for Coding Interviews.
- Bottom-up conversions are the subject of Grokking Dynamic Programming.
- The tree and graph traversals that reach these limits are covered in Grokking the Coding Interview.

GET YOUR FREE
Coding Questions Catalog

$98

$197

$72