Cloud Parts

Event loop or threads?

DimensionEvent loopMultithreading
How waiting worksSockets are non-blocking; the loop asks epoll, kqueue or IOCP which are ready and runs other callbacks meanwhileThe thread blocks in read() and the OS scheduler runs another thread
Memory per connectionJust the state the callback needs, kept in heap objectsA whole stack: typically 8 MB of virtual address space on Linux with glibc, 1 MB reserved on Windows (a few KB for goroutines)
Using many coresOne loop per core: Nginx runs a single-threaded worker per core; Redis users run several instancesBuilt in: threads run in parallel (except CPython with the GIL)
CPU-bound workBlocks every connection; hand it to a worker pool (run_in_executor, Node worker threads)Fine: it runs on its own core while other threads carry on
Shared state and locksOne callback runs at a time, so in-memory state needs no locks (but it can change across an await)Any thread can touch shared memory at any moment: locks or atomics, with data races and deadlocks possible
Typical failureOne slow callback (a big JSON.parse, a heavy regex, a synchronous file read) stalls every clientDeadlocks, races that appear only under load, and pool exhaustion when every thread waits on a slow dependency
DebuggingTiming depends only on events, but logic is split across callbacks and stack traces stop at the loop (async/await helps)Sequential code with real stack traces, but timing-dependent bugs are hard to reproduce
ExamplesNode.js (libuv), Python asyncio, Nginx, RedisThread-pool servers in Java, C++ and Rust; Go goroutines and Java virtual threads as cheap threads

Rule of thumb

If connections mostly wait on the network and there are thousands of them, an event loop is cheap and avoids locks. If the work is CPU-heavy, or the code and libraries are blocking, use threads, ideally from a pool. Goroutines and Java’s virtual threads blur the line: you write blocking, thread-per-request code, and the runtime parks a waiting thread and runs another on the same OS thread. Either way, keep slow work off the thread that serves everyone else.

Sources