In part 1, we built the core stack/microtask/macrotask model. In part 2, we saw how the browser and Node implement that model differently — rendering interleaved with tasks in the browser, libuv's phase-based loop in Node.

Both of those posts share an unspoken assumption: your callbacks are fast. A few milliseconds, do their thing, return, let the loop move on. But what happens when that assumption breaks? What happens when you genuinely need to do slow, CPU-bound work — and there's no I/O to wait on, no callback to defer, just raw computation that has to happen?

That's what this post is about. No amount of clever queue ordering saves you here. You need actual parallelism, and in Node, that means worker_threads.

The problem worker_threads solves

Everything from parts 1 and 2 works because the actual JS execution — the code inside your callbacks — is assumed to be short. The event loop is brilliant at making single-threaded JS feel concurrent when the bottleneck is I/O: waiting on a database, a file read, a network response. While you wait, the thread is free to do other things.