Skip to content
RungsySign in

Concurrency vs Parallelism

Dealing with many things at once vs doing many things at once — not the same, and the distinction matters.

35 minDifficulty 3/5systems · fundamentalsAI-writtenWritten by a model on 16 August 2026 and not yet read by a person. Checked automatically: schema, the pedagogical rules the hand-written material is held to, and every diagram parsed for real.

Before this

Why this exists

A single chef juggling five dishes at once — stirring one, checking the oven on another, chopping for a third — is dealing with many things AT ONCE without doing them simultaneously; only one hand moves at any instant. Five chefs, each cooking their own dish independently, are doing many things SIMULTANEOUSLY. Both look like "handling multiple dishes" from outside the kitchen, but they're structurally different, and so are concurrency and parallelism.

The mental model

Concurrency is about STRUCTURE: a program composed of multiple independent tasks that can make progress without waiting for each other to fully finish, interleaved in some order. Parallelism is about EXECUTION: multiple tasks physically running at the same literal instant, on multiple CPU cores. A single-core machine can do concurrency (interleaving) but never true parallelism (no second core to run on).

How it works

JavaScript's concurrency model is single-threaded but genuinely concurrent

A JavaScript engine runs one line of code at a time, on one thread — but `async`/`await` and Promises let a program structure many I/O-bound operations to progress concurrently, interleaved by the event loop, without ever running two pieces of JS simultaneously. This is concurrency without parallelism: the illusion of 'many things happening at once' achieved entirely through interleaving, not simultaneous execution.

Parallelism requires genuinely separate execution contexts

Web Workers (in the browser) or worker threads (in Node) run actual JavaScript on SEPARATE threads, with their own memory, enabling true parallelism — two workers really do execute at the same literal instant on a multi-core machine. This is fundamentally different from `async`/`await`, which never leaves the single main thread no matter how many operations are 'in flight' at once.

Concurrency introduces the possibility of race conditions; parallelism makes them worse

Whenever multiple logical tasks can interleave in an unpredictable order — whether via concurrency on one thread or genuine parallelism across cores — shared, mutable state accessed by more than one of them becomes a hazard: the FINAL result can depend on exactly which order operations happened to interleave in, which is the definition of a race condition (see `race-conditions`).

Choosing between them is about what the workload actually needs

I/O-bound work (waiting on a network call, a database query) benefits from concurrency — there's no CPU work happening during the wait, so interleaving other tasks into that idle time is pure gain, with no extra hardware needed. CPU-bound work (heavy computation) benefits from PARALLELISM specifically — interleaving on one core doesn't make the total computation finish faster, only genuinely simultaneous execution on multiple cores does.

The mechanism

In concurrency, tasks take turns making progress on a single execution resource, interleaved in some order that may vary run to run — no two steps genuinely happen at the same instant. In parallelism, separate execution resources (cores) each run a task independently, and two steps genuinely DO happen at the same literal instant, which interleaving alone can never achieve.

flowchart TD
  subgraph Concurrency [One core, interleaved]
    A1[Task A step 1] --> B1[Task B step 1] --> A2[Task A step 2] --> B2[Task B step 2]
  end
  subgraph Parallelism [Two cores, simultaneous]
    C1[Task A - core 1] 
    C2[Task B - core 2]
  end
Diagram source for Concurrency vs Parallelism.

What people get wrong

JavaScript being 'single-threaded' means it can't do concurrency.
Single-threaded and concurrent aren't contradictory — a single thread can structure many tasks to interleave and make progress without blocking on each other, which is exactly what async/await and the event loop achieve, entirely on one thread. This misconception undersells what async JavaScript actually does — the language achieves genuine concurrency (many tasks in flight, interleaved) without ever needing multiple threads.
async/await makes code run in parallel.
async/await structures code to interleave on the SAME single thread — it never runs two pieces of your JavaScript at the same literal instant, which is what parallelism specifically requires; it just avoids blocking that one thread while waiting on I/O. Believing async code is parallel leads to expecting a CPU-bound computation wrapped in async/await to somehow finish faster on multiple cores, when it will run at exactly the same speed as if it were synchronous, since no core-level parallelism is involved.
Parallelism is always strictly better than concurrency because it does things 'actually at the same time'.
Parallelism requires genuinely separate execution resources (multiple cores, multiple threads with real overhead to manage), which is unnecessary and wasteful for I/O-bound work where the 'waiting' isn't consuming CPU anyway — concurrency alone already captures the available gain there for free. Reaching for worker threads or multi-process parallelism for I/O-bound work adds real complexity and overhead without any actual speedup, since the bottleneck was never CPU availability in the first place.

When not to use it

The work is I/O-bound — waiting on network calls, file reads, or database queries.
Concurrency (async/await, Promises) is sufficient and appropriate — the wait time isn't consuming CPU, so interleaving other work into it captures the full available benefit without needing multiple threads or cores.
The work is CPU-bound and genuinely needs to go faster by using more hardware.
Parallelism — worker threads, multiple processes, or distributing the work across machines — since interleaving alone on one core can't make the total computation complete any sooner.

Terms

Concurrency
A program structured as multiple independent tasks that can make progress without waiting for each other, interleaved in some order, regardless of whether they run on one core or many.
Parallelism
Multiple tasks genuinely executing at the same literal instant, which requires multiple physical execution resources (CPU cores).
Event loop
The mechanism that interleaves multiple concurrent tasks on a single thread, giving the appearance of simultaneity without true parallel execution.
Worker thread
A separate thread of execution (with its own memory) that can run JavaScript genuinely in parallel with the main thread, unlike async/await which stays on one thread.

In an interview

Does wrapping a CPU-intensive loop in an async function make it run faster on a multi-core machine?

  • no — async/await provides concurrency (interleaving on one thread), not parallelism (simultaneous execution across cores)
  • the CPU-intensive loop still runs entirely on the single main thread, occupying it fully, regardless of the async wrapper
  • genuine speedup for CPU-bound work requires actual parallelism, e.g. worker threads distributing the computation across multiple cores

Can you recall it?

Why can a single-core machine achieve concurrency but never true parallelism, and what does that mean for a CPU-bound task wrapped in async/await?

Keep track of this

Add Concurrency to your map and Rungsy will schedule reviews so you actually remember it.