> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meow.style/llms.txt
> Use this file to discover all available pages before exploring further.

# Workers

> Parallelism via node:worker_threads — implemented as cooperative V8 isolates on meow's event loop.

meow supports `node:worker_threads` for offloading work to separate JavaScript
contexts. The API is the standard Node one — `Worker`, `parentPort`, `workerData`,
`postMessage`, `terminate` — so existing worker code and libraries like
`jest-worker` run unmodified.

<Note>
  Workers are a [`node-compat`](/concepts/modes) feature: `node:worker_threads` is
  part of the Node surface and is withdrawn in `strict-web`.
</Note>

## The cooperative-isolate model

Under the hood, meow's workers are **distinct V8 isolates that interleave
cooperatively on the same OS thread**, driven by the runtime's event loop — not
OS threads.

This is a deliberate design choice. V8 isolates can't move between OS threads, so
rather than pay the context-switching tax of true OS threads, meow spawns each
worker as a task on the main thread's executor. They share nothing but the message
channel, get genuine memory isolation, and interleave without thread overhead —
ideal for the bursty, message-driven parallelism that bundlers and test runners use.

<Frame caption="Each worker is its own V8 isolate with its own heap; they cooperate on one OS thread and communicate only through serialized messages.">
  ```text theme={null}
  Main isolate  ──postMessage──▶  Worker isolate
       ▲                               │
       └──────────  message  ──────────┘
  ```
</Frame>

## Example

<CodeGroup>
  ```typescript main.ts theme={null}
  import { Worker } from "node:worker_threads";

  const worker = new Worker(new URL("./worker.ts", import.meta.url), {
    workerData: { n: 42 },
  });

  worker.on("message", (result) => {
    console.log("worker said:", result);
    worker.terminate();
  });

  worker.postMessage("start");
  ```

  ```typescript worker.ts theme={null}
  import { parentPort, workerData } from "node:worker_threads";

  parentPort?.on("message", (msg) => {
    const answer = workerData.n * 2;
    parentPort?.postMessage(answer);
  });
  ```
</CodeGroup>

## What's supported

| Feature                                                 | Status                          |
| ------------------------------------------------------- | ------------------------------- |
| `new Worker(specifier, { workerData })`                 | ✅                               |
| `worker.postMessage()` / `worker.on("message")`         | ✅ (structured-clone serialized) |
| `parentPort.postMessage()` / `parentPort.on("message")` | ✅                               |
| `workerData`                                            | ✅                               |
| `worker.terminate()`                                    | ✅ (terminates the isolate)      |
| Error propagation worker → host                         | ✅ (surfaces as an `Error`)      |
| Nested workers (a worker spawning its own worker)       | ⚠️ inert for now                |

Each worker reuses the project's resolver and module graph, so imports resolve
exactly as they do on the main isolate, and inherits the run's
[determinism](/concepts/determinism) configuration.

<Tip>
  Because workers share the event loop rather than the CPU, they're perfect for
  I/O-bound and message-driven concurrency. For CPU-bound hashing and tarball work,
  meow already offloads to background OS threads internally — you don't need a
  worker for that.
</Tip>

<Card title="Next: environment variables" icon="key" href="/runtime/environment">
  Every MEOW\_\* variable and how process.env behaves per mode.
</Card>
