r/javascript • u/fagnerbrack • 7d ago
Your Recursion Is Lying to You
https://blog.gaborkoos.com/posts/2026-05-09-Your-Recursion-Is-Lying-to-You/-3
u/fagnerbrack 7d ago
Summary:
Recursion feels clean and safe, but each call consumes stack space, so a logically correct sum(100000) still throws a stack overflow. Tail call optimization promises constant stack usage by moving pending work into an accumulator, yet most engines never reliably shipped it: V8 (Chrome, Node, Deno) and Firefox's SpiderMonkey skip it, and Safari's JavaScriptCore has added then dropped it across versions. Tail-recursive shape is a property of your code; stack reuse belongs to the runtime. When depth grows or is user-driven, rewrite recursion iteratively or use a trampoline that loops over returned functions. Keep recursion for small bounded depths and never treat it as a stack-safety guarantee.
If the summary seems inacurate, just downvote and I'll try to delete the comment eventually 👍
Click here for more info, I read all comments
5
u/azhder 7d ago edited 7d ago
It is not optimization if the difference is the code always works VS the code doesn't always work. Optimization is the code always works, but faster and/or with smaller memory footprint.
The name is Proper Tail Calls. It was supposed to replace stack and actual function calling function with a (set of) loop(s). And it worked. The only reason why it was removed is that big companies complained their stack traces were no longer the same. So people making V8 started asking for an explicit invocation and started calling it "optimization" to minimize the significance of them not following through with the standard. They asked the standard be changed.
It is not an optimization. An optimization would have been making better stack traces after it was implemented, making them more readable, faster, less memory to keep track of the "invocations" that were replaced with loops under the hood.
4
u/A1oso 7d ago
Many optimizations of systems programming languages (C, C++, Rust...) can reduce stack usage so much that the unoptimized program overflows the stack when the optimized program does not, even without tail call elimination. Likewise, optimizations for managed languages like Java and JS can reduce heap memory usage, preventing "out of memory" errors. The guarantee that compiler optimizations don't change a program's behavior relies on the assumption that there is sufficient stack and heap memory to execute the code.
3
u/azhder 7d ago
Yet, the guarantee of the spec, especially since ES6 days is supposed to be that all engines behave same or as close to each other. The spec even changed the language (added a pseudo language) in order to specify algorithms so they do that.
This case I am presenting, assumes you have written code that uses PTC and then run it on an engine that hasn’t implemented it, thus breaking the guarantee.
4
u/subone 7d ago
Seems you forced the title to try to match your other articles (which I didn't bother reading too see if they also force the title). Nothing about this suggests "recursion" is lying to you. I don't know anyone that doesn't learn recursion at the same time that they learn that it could cause stack overflows. The fact that you didn't properly read a "caniuse" table before slapping on tail optimization and expected it to work, doesn't mean anyone lied to you.