Compare

Side-by-side on the decisions that recur: process vs thread, threads vs async, mutex vs semaphore, blocking vs non-blocking I/O, container vs VM — with when to choose each.

StackHeap
LifetimeTied to the function call: pushed on entry, popped on returnExplicit (free/delete) or garbage-collected; outlives the call
AllocationMove the stack pointer — a single instructionAllocator search, possibly brk/mmap to the kernel; tens of ns to µs
SizeFixed per thread: ~8 MB main thread on Linux, 1 MB on Windows, often 512 KB–2 MB for worker threadsBounded by address space and RAM; grows on demand
FailureStack overflow → guard page → SIGSEGV (Linux) / STATUS_STACK_OVERFLOW (Windows)Leaks, fragmentation, std::bad_alloc/NULL, OOM killer
Thread safetyPrivate to the thread by constructionShared across threads — the allocator locks or uses per-thread arenas
In managed runtimesJS and Python frames live on a runtime-managed stack; recursion limit ~10k (Node) / 1000 (CPython default)Every object is heap-allocated and GC-managed; escape analysis may stack-allocate in JITs
Choose this whenSmall, fixed-size, call-scoped data — locals, small arrays, iterators — for speed and automatic cleanup.Anything large, dynamically sized, shared between threads, or that must outlive the function that created it.