Plano — Execução da Sub-trilha Paralelismo (Galho 2)
Leitura de 50 min
Sub-trilha Paralelismo — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Goal: Produzir 12 notas atômicas + 1 MOC em 03-Dominios/Node/Paralelismo/, em PT-BR, todas publish: true, cobrindo Worker Threads (fundamentos, comunicação, SharedArrayBuffer/Atomics, pool), Cluster, child_process (exec/spawn, fork), contexto de produção (PM2/K8s) e decision tree — para um dev senior em prep para entrevista internacional. Ao final, podar a seção correspondente do tronco JavaScript/Backend/Node.js.md e atualizar o MOC central de 03-Dominios/Node/index.md.
Architecture: Sub-trilha sequencial em 5 blocos (Mental model + fundamentos → Worker Threads → Multi-processo → Produção → Fechamento) + 1 MOC com 5 rotas alternativas. Pressupõe galho 1 (Runtime e Event Loop) como pré-requisito; em particular as notas 09 (async/await desmistificado) e 10 (Bloqueio do event loop) são wikilinks frequentes. Cada nota é atômica, segue estrutura híbrida (TL;DR + corpo técnico), com code samples em JS ou TS (Node 22 LTS / 24, worker_threads estável, cluster estável), e seção “Em entrevista” para preparação internacional.
Tech Stack: Markdown + Obsidian Flavored Markdown (wikilinks, callouts, dataview), Quartz para publicação no site público (josenaldo.github.io). Sem código a executar como sistema — code samples didáticos validáveis via node script.js ou node --experimental-strip-types script.ts quando útil. Bibliografia âncora: Node docs (worker_threads, cluster, child_process), MDN (Atomics, SharedArrayBuffer), piscina repo (worker pool de referência), PM2 docs.
⚠️ Restrição absoluta — fabricação
A memória Nunca inventar dados sobre o usuário é regra inegociável. Nenhuma nota pode atribuir ao autor experiências profissionais, projetos, clientes, métricas ou casos não-vividos.
A seção “Na prática” de cada nota usa:
“Padrão observado em libs do ecossistema (piscina, PM2, Express, NestJS)”
“Caso típico em microserviços com CPU-bound (image processing, ML inference, hashing)”
“Armadilha comum reportada na comunidade”
Citações com fonte verificável (docs oficiais, talks identificadas, repos públicos)
Hipotéticos explícitos (“Imagine um endpoint que recebe uploads e calcula bcrypt…“)
Quando faltar contexto factual, PERGUNTAR antes de escrever — nunca preencher com plausibilidade.
File Structure
13 arquivos novos em 03-Dominios/Node/Paralelismo/:
03-Dominios/Node/Paralelismo/
├── Paralelismo.md # MOC (Task 1)
├── 01 - Por que paralelismo em Node.md # Task 2
├── 02 - As 3 ferramentas - Worker Threads, Cluster, child_process.md # Task 3
├── 03 - Worker Threads - fundamentos.md # Task 4
├── 04 - Comunicação entre workers - postMessage e MessageChannel.md # Task 5
├── 05 - Memória compartilhada - SharedArrayBuffer e Atomics.md # Task 6
├── 06 - Pool de workers - pattern de produção.md # Task 7
├── 07 - Cluster - escalando HTTP por CPU.md # Task 8
├── 08 - child_process com exec e spawn.md # Task 9
├── 09 - child_process com fork - Node child com IPC.md # Task 10
├── 10 - Cluster vs PM2 vs Kubernetes - quem orquestra.md # Task 11
├── 11 - Decision tree - qual ferramenta para qual problema.md # Task 12
└── 12 - Armadilhas, regras práticas, cheatsheet.md # Task 13
Final integration (Task 14, 15, 16):
Pass final no MOC inserindo todos os wikilinks + dataview
Poda do tronco 03-Dominios/JavaScript/Backend/Node.js.md (uma seção)
Atualização do MOC central 03-Dominios/Node/index.md + verificação de build do Quartz
Template padrão (definido uma vez, aplicado a todas as 12 notas)
---title: "<título sem prefixo numérico>"created: 2026-05-07updated: 2026-05-07type: conceptstatus: seedlingpublish: truetags: - node - paralelismo - <tag específica: worker-threads, cluster, child-process, atomics, pool, etc>aliases: - <opcional: alternativas naturais de busca>---# <Título>> [!abstract] TL;DR> > <2-4 linhas em PT-BR direto. Define o conceito-chave + a regra prática + por que importa.>## O que é<1-3 parágrafos definindo o conceito da nota. Pressupõe leitura de [[Runtime e Event Loop]] (galho 1) ou consulta paralela.>## Por que importa<O problema que isso resolve no dia a dia. Onde o desenvolvedor "trava" sem esse conhecimento.>## Como funciona<Aprofundamento técnico com code samples em JS ou TS. Mostrar o pattern, depois variações. Edge cases.>## Na prática<Exemplo realista. Sem fabricar experiência do autor — usar "padrão observado em X", "lib Y faz isso", hipotéticos explícitos.>## Armadilhas<Gotchas específicos. O que erra normalmente. Mínimo 2 itens.>## Em entrevista<Frase pronta em inglês para explicar o conceito. Vocabulário-chave (PT → EN). Pergunta típica + resposta defensiva.>## Veja também- [[Outra nota da trilha]] — relação- [[Runtime e Event Loop]] — galho 1 (pré-requisito)- [[Node.js]] — tronco
Variações permitidas
Nota 12 (Armadilhas, cheatsheet): estrutura tópica — lista numerada de armadilhas + tabelas + decision tree compactada. Não tem narrativa “Como funciona”.
MOC (Paralelismo.md): estrutura própria — abertura + Comece por aqui + 5 rotas alternativas + dataview. type: moc.
Critérios de qualidade (rubrica aplicada por nota)
TL;DR em callout [!abstract], 2-4 linhas, compreensível em <30s
2+ wikilinks pra outras notas do galho + 1+ wikilink pra [[Node.js]] (tronco) ou [[Runtime e Event Loop]] (galho 1)
3+ code samples em JS ou TS (notas conceituais 01, 02 podem ter menos se forem síntese)
Seção “Em entrevista” com pelo menos 1 frase pronta em inglês + vocabulário-chave (mínimo 4 termos PT→EN)
Seção “Armadilhas” com pelo menos 2 armadilhas concretas
Esperado: linha referenciando project_tronco_galhos_pattern.md. Se não estiver, registrar e prosseguir (não é bloqueante mas deve ser consultada para coesão com galho 1).
Step 4: Sanity check do tronco — confirmar a seção a podar
Ler 03-Dominios/JavaScript/Backend/Node.js.md e confirmar que existe a seção:
### Worker Threads, cluster, child_process — as 3 formas de paralelismo
Anotar o número da linha exato onde a seção começa e onde termina (próxima ### ou ##). Se o nome estiver diferente, anotar exatamente como aparece.
Criar 03-Dominios/Node/Paralelismo/Paralelismo.md com este conteúdo (a seção “Sobre este galho” tem placeholder a preencher na Task 14):
---title: "Paralelismo"created: 2026-05-07updated: 2026-05-07type: mocstatus: seedlingpublish: truetags: - node - paralelismo - mocaliases: - Worker Threads - Galho 2 - Paralelismo---# Paralelismo> [!abstract] TL;DR> > Galho 2 da trilha Node Senior. Cobre as 3 ferramentas para fugir do single-thread: Worker Threads (CPU-bound em mesmo processo), Cluster (escalar HTTP por CPU), child_process (rodar comando externo ou spawn de Node). Inclui SharedArrayBuffer/Atomics, pool de workers, contexto de produção (PM2 vs K8s), e decision tree. Pré-requisito: galho 1 (Runtime e Event Loop).## Sobre este galho(introdução curta — preencher na Task 14)## Comece por aqui — trilha completa (12 notas)### Bloco A — Mental model e fundamentos1. [[01 - Por que paralelismo em Node]]2. [[02 - As 3 ferramentas - Worker Threads, Cluster, child_process]]### Bloco B — Worker Threads3. [[03 - Worker Threads - fundamentos]]4. [[04 - Comunicação entre workers - postMessage e MessageChannel]]5. [[05 - Memória compartilhada - SharedArrayBuffer e Atomics]]6. [[06 - Pool de workers - pattern de produção]]### Bloco C — Multi-processo7. [[07 - Cluster - escalando HTTP por CPU]]8. [[08 - child_process com exec e spawn]]9. [[09 - child_process com fork - Node child com IPC]]### Bloco D — Produção10. [[10 - Cluster vs PM2 vs Kubernetes - quem orquestra]]11. [[11 - Decision tree - qual ferramenta para qual problema]]### Bloco E — Fechamento12. [[12 - Armadilhas, regras práticas, cheatsheet]]## Rotas alternativas### Rota entrevista internacional01 → 02 → 03 → 05 → 07 → 11. Foco em "explicar os 3 modelos pra entrevistador".### Rota produção01 → 06 → 07 → 10 → 12. Foco em "pôr em produção".### Rota CPU-bound01 → 03 → 04 → 06. Foco em "escapar do bloqueio com Worker Threads".### Rota integração com OS01 → 02 → 08 → 09. Foco em "rodar comandos externos e spawn de Node".## Todas as notas\`\`\`dataviewTABLE status, updatedFROM "03-Dominios/Node/Paralelismo"WHERE type = "concept"SORT file.name ASC\`\`\`## Veja também- [[03-Dominios/Node/index|Node.js (MOC central)]]- [[Node.js]] — tronco (deep dive panorâmico)- [[Runtime e Event Loop]] — galho 1 (pré-requisito)
IMPORTANT: No conteúdo do arquivo, substitua os \“(com backslashes) por triple backticks reais. Os backslashes acima são apenas para escape neste plano. O dataview deve ficar como bloco de código com triple backticks reais e o language tagdataview`.
Step 2: Verificar frontmatter e estrutura
Confirmar:
type: moc
publish: true
12 notas listadas em ordem em 5 blocos (A, B, C, D, E)
4 rotas alternativas presentes (entrevista, produção, CPU-bound, integração com OS) — a “rota completa” implícita é o sequencial 01→12 sob “Comece por aqui”
Dataview com SORT file.name ASC
Wikilinks pro MOC central, tronco, e galho 1
Step 3: Commit
git add "03-Dominios/Node/Paralelismo/Paralelismo.md"git commit -m "feat(node-paralelismo): add MOC skeleton for Paralelismo branch"
Task 2: Nota 01 — Por que paralelismo em Node
Files:
Create: 03-Dominios/Node/Paralelismo/01 - Por que paralelismo em Node.md
Conteúdo-chave do spec (Bloco A):
CPU-bound vs I/O-bound (revisão do galho 1). Sintomas que pedem paralelismo verdadeiro: event loop lag persistente mesmo após otimizações, latência conjunta acima do tolerável, throughput limitado pela CPU. Alternativas a considerar antes de paralelizar: streaming (preview galho 3), paginação, refator do algoritmo, mover trabalho pra background queue. Quando paralelismo é a resposta certa. Conexão direta com galho 1 nota 09.
Step 1: Pesquisa-âncora
Sem WebFetch nessa nota — é síntese do galho 1 + framing do galho 2. Reler:
03-Dominios/Node/Runtime e Event Loop/09 - async-await - o que é, o que não é.md (mito da performance)
03-Dominios/Node/Runtime e Event Loop/10 - Bloqueio do event loop - sintomas e causas.md (sintomas)
para garantir vocabulário e pontes coesos.
Step 2: Criar arquivo + frontmatter
---title: "Por que paralelismo em Node"created: 2026-05-07updated: 2026-05-07type: conceptstatus: seedlingpublish: truetags: - node - paralelismo - mental-model - cpu-boundaliases: - CPU-bound vs I/O-bound - Quando paralelizar---
Step 3: Escrever a nota completa (250-400 linhas)
Cobrir, em PT-BR, em ordem:
TL;DR (callout [!abstract]): Node é single-thread e isso geralmente está certo. Mas há casos onde paralelismo é a única saída: CPU-bound persistente, event loop lag que não cede com otimização, throughput limitado. Antes de paralelizar, considere streaming, paginação, refator. Quando essas falham, há 3 ferramentas (Worker Threads, Cluster, child_process) — escolha depende do problema.
O que é: definição prática. Paralelismo no contexto Node = executar trabalho simultaneamente em outras threads ou processos, fora do event loop principal. Distinto de concorrência (event loop alterna entre tarefas). Cobre: Worker Thread (mesma processo, threads JS separadas), Cluster (múltiplos processos compartilhando porta), child_process (processo independente).
Por que importa: sem o conhecimento, o dev tenta resolver CPU-bound com async/await (não funciona — galho 1 nota 09 mostra), ou aumenta réplicas no orquestrador sem entender por que (caro). Saber as ferramentas + decision tree separa um sênior em decision-making.
Como funciona: revisão CPU-bound vs I/O-bound:
I/O-bound (DB, HTTP, file): event loop + async/await resolvem; paralelismo aqui geralmente não ajuda e pode piorar (mais context switches).
CPU-bound (hash, image processing, compress, ML inference): single-thread bloqueia. Aqui paralelismo é a única solução estrutural.
Code sample minimal: handler com bcrypt.hashSync que trava o servidor sob load. Antes de Worker Thread, tentar: rodar bcrypt async (callback API usa thread pool), aumentar UV_THREADPOOL_SIZE (galho 1 nota 07). Se ainda saturar, Worker Thread.
Na prática: padrão de raciocínio:
Medir primeiro (galho 1 nota 11): event loop lag, percentis de latência, CPU usage. “Tá lento” sem medição é hipótese.
Tentar antes de paralelizar: streaming (galho 3) para dados grandes; paginação para listas; refator do algoritmo; mover pra background queue (BullMQ, etc.); usar API async em vez de sync.
Se paralelismo for inevitável, escolher a ferramenta certa (decision tree em nota 11).
Armadilhas (3+):
Pular pra Worker Thread sem medir — adiciona complexidade sem ganho mensurável
Confundir CPU-bound com I/O-bound — paralelizar I/O via Worker Threads é tipicamente pior que async/await
Achar que “subir UV_THREADPOOL_SIZE” resolve qualquer CPU-bound — funciona apenas para APIs que usam o pool (bcrypt async, crypto.pbkdf2). Trabalho síncrono próprio precisa de Worker Thread.
Em entrevista:
Frase pronta: “Node is single-threaded by design, and that’s the right choice for most I/O-bound workloads. But when you have genuine CPU-bound work — image processing, hashing, ML inference, compression — single-thread becomes the bottleneck. The signal is event loop lag that persists across optimization attempts. The structural fix is parallelism, but Node has three different parallelism tools — Worker Threads for shared-memory threads, Cluster for sharing an HTTP port across processes, and child_process for spawning external commands or isolated Node processes. Choosing the right one matters more than knowing they exist.”
Vocabulário (5+): paralelismo (parallelism), concorrência (concurrency), trabalho de CPU (CPU-bound work), atraso do event loop (event loop lag), pool de threads (thread pool), processo (process), thread (thread).
Veja também:
[[02 - As 3 ferramentas - Worker Threads, Cluster, child_process]]
[[03 - Worker Threads - fundamentos]]
[[11 - Decision tree - qual ferramenta para qual problema]]
[[Runtime e Event Loop]] (galho 1)
[[09 - async-await - o que é, o que não é]] (galho 1 — mito da performance)
[[10 - Bloqueio do event loop - sintomas e causas]] (galho 1 — sintomas)
git add "03-Dominios/Node/Paralelismo/01 - Por que paralelismo em Node.md"git commit -m "feat(node-paralelismo): add note 01 — Por que paralelismo em Node"
TL;DR: Node tem 3 ferramentas para paralelizar: Worker Threads (threads JS no mesmo processo, mensagens ou memória compartilhada), Cluster (múltiplos processos compartilhando porta HTTP), child_process (processo externo independente, IPC opcional via fork). Cada uma resolve um problema diferente — escolher a errada é fonte clássica de complexidade desnecessária.
O que é: os 3 modelos de paralelismo:
Shared-memory model (Worker Threads): múltiplas threads JS no mesmo processo, podem trocar mensagens (clone) ou compartilhar memória (SharedArrayBuffer)
Shared-port model (Cluster): primary fork() processos workers; todos compartilham mesma porta HTTP via round-robin do kernel
Separate-process model (child_process): spawn de processo externo (qualquer comando) ou Node child com IPC. Sem compartilhamento de estado.
Por que importa: confundir os modelos leva a soluções erradas. “Tenho CPU-bound, vou usar Cluster” → cada worker faz a mesma CPU-bound, não paraleliza dentro de uma request. “Quero spawn um Python script, vou usar Worker Thread” → Worker só roda JS.
Como funciona:tabela canônica (esta é a estrela da nota):
Ferramenta
Modelo
Isolamento
Custo criação
IPC
Uso típico
Worker Thread
shared-memory
thread (mesma heap em SAB)
~ms
postMessage / SAB
CPU-bound em handler
Cluster
shared-port
processo
~100ms
IPC built-in
Escalar HTTP por CPU
child_process spawn
separate-process
processo
~100ms
stdio
Rodar comando externo
child_process fork
separate-process
processo
~100ms
IPC built-in
Node child isolado
Code sample minimal de cada um (10 linhas cada): Worker Thread via new Worker, Cluster via cluster.fork(), spawn via spawn('ls'), fork via fork('./worker.js').
Na prática: a regra mental:
“Eu tenho CPU-bound e quero paralelizar dentro do mesmo processo” → Worker Thread
“Eu quero rodar 4 cópias do meu HTTP server em uma máquina” → Cluster (ou orquestrador)
“Eu quero rodar ffmpeg ou outro comando” → spawn
“Eu quero spawn um processo Node isolado” → fork
Armadilhas (3+):
Usar Cluster pra CPU-bound em handler — não ajuda; cada worker tem o mesmo problema
Tentar usar Worker Thread pra rodar comando externo — Worker só executa JS
Achar que fork do child_process e cluster.fork são a mesma coisa — cluster.fork é especialização que compartilha porta
Tomar decisão sem entender o problema (CPU-bound vs HTTP-scaling vs OS-integration)
Em entrevista:
Frase pronta: “Node has three parallelism tools, each solving a different problem. Worker Threads give you multiple JS threads in the same process — shared-memory model with message passing or SharedArrayBuffer. Cluster forks multiple processes that share an HTTP port via kernel round-robin — useful for scaling a web server across CPUs on a single host. child_process spawns external processes — spawn and exec for arbitrary commands, fork for Node children with IPC. The decision rule: CPU-bound → Worker Thread; HTTP scaling → Cluster or orchestrator; external command → spawn; isolated Node child → fork.”
Vocabulário (6+): thread (thread), processo (process), modelo de memória compartilhada (shared-memory model), porta compartilhada (shared port), processo separado (separate process), comunicação interprocess (inter-process communication / IPC), bifurcar (fork), spawnar (spawn).
Veja também:
[[01 - Por que paralelismo em Node]]
[[03 - Worker Threads - fundamentos]]
[[07 - Cluster - escalando HTTP por CPU]]
[[08 - child_process com exec e spawn]]
[[09 - child_process com fork - Node child com IPC]]
[[11 - Decision tree - qual ferramenta para qual problema]]
API básica: new Worker(file, { workerData }), parentPort, worker.on('message'/'error'/'exit'/'online'), worker.terminate(). Custo de criação (~ms vs novo processo ~100ms). isMainThread flag. Modos: arquivo separado vs inline. Quando o Worker termina por conta própria, quando precisa de terminate explícito.
TL;DR: Worker Thread é uma thread JS adicional no mesmo processo Node. Criada via new Worker(file, { workerData }), comunica com main via parentPort. Custo de criação ~ms (vs ~100ms de processo). Eventos: online, message, error, exit. Terminate explícito ou natural quando termina o trabalho.
O que é: uma thread JS isolada (heap separada) que compartilha o mesmo processo Node. Tem seu próprio event loop, seu próprio V8 isolate. Útil pra trabalho CPU-bound porque não bloqueia a thread main.
Por que importa: alternativa às soluções “à força bruta” (subir réplicas no orquestrador). Worker Threads dão paralelismo real dentro de um processo, mantendo o footprint pequeno.
Como funciona: code samples:
Modo arquivo separado (main.js + worker.js):
// main.jsimport { Worker } from 'node:worker_threads';const w = new Worker('./worker.js', { workerData: { input: 42 } });w.on('message', (msg) => console.log('result:', msg));w.on('error', console.error);w.on('exit', (code) => console.log('worker exited', code));// worker.jsimport { parentPort, workerData } from 'node:worker_threads';const result = workerData.input * 2;parentPort.postMessage(result);
Modo inline (mesmo arquivo via isMainThread):
import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';if (isMainThread) { const w = new Worker(__filename, { workerData: { input: 42 } }); w.on('message', console.log);} else { parentPort.postMessage(workerData.input * 2);}
threadId: worker_threads.threadId (0 no main, sequencial nos workers).
Na prática: padrão observado:
Modo arquivo separado é mais comum (separação clara, fácil testar)
Modo inline economiza arquivos mas dificulta tooling (linter, types)
worker.terminate() é forçado — usa SIGKILL semanticamente; preferir cooperação via mensagem 'shutdown'
unref() permite o processo main sair sem esperar o worker (útil pra workers que fazem trabalho de fundo não-crítico)
Armadilhas (3+):
Esquecer de tratar evento 'error' — error handler default vai pra unhandledException (e fatal em Node 22+)
terminate() pode deixar trabalho não-finalizado (escrita parcial em arquivo, mensagem perdida); preferir cooperative shutdown
workerData passa por structured clone — funções, classes, refs DOM falham (preview da nota 04)
Confundir Worker Thread com Web Worker do browser — APIs parecidas mas não idênticas (importScripts não existe, etc.)
Em entrevista:
Frase pronta: “A Worker Thread is an additional JS thread in the same Node process — separate V8 isolate, separate event loop, separate heap. You create one with new Worker(filePath, { workerData }). The worker communicates with the main thread via parentPort.postMessage, and the main thread listens with worker.on('message'). Lifecycle events are online, message, error, exit. Workers cost about a millisecond to create, versus around 100 milliseconds for a process — so they’re cheap enough for per-request use, though pooling is the production pattern.”
Vocabulário (5+): thread de trabalho (Worker Thread), thread principal (main thread), porta-pai (parentPort), dados do worker (workerData), terminar (terminate), isolado V8 (V8 isolate), thread leve (lightweight thread).
Veja também:
[[01 - Por que paralelismo em Node]]
[[02 - As 3 ferramentas - Worker Threads, Cluster, child_process]]
[[04 - Comunicação entre workers - postMessage e MessageChannel]]
[[05 - Memória compartilhada - SharedArrayBuffer e Atomics]]
[[06 - Pool de workers - pattern de produção]]
[[Node.js]] (tronco)
Step 4: Verificar rubrica (standard, code samples mínimo 4 dado o tema operacional)
Create: 03-Dominios/Node/Paralelismo/04 - Comunicação entre workers - postMessage e MessageChannel.md
Conteúdo-chave do spec:
Algoritmo de clone estruturado. transferList para passar ArrayBuffer/MessagePort sem cópia. MessageChannel para canais bidirecionais isolados do parentPort. Tipos do worker_threads.
TL;DR: Workers comunicam via postMessage, que clona o payload (algoritmo de clone estruturado). Para evitar cópia de buffers grandes, use transferList — o ArrayBuffer é movido (referência transferida; original fica detached). MessageChannel cria canais bidirecionais separados do parentPort.
O que é: o protocolo de mensagens entre Worker e main, e entre Workers entre si.
Por que importa: copiar 100MB via clone estruturado a cada mensagem é caro. transferList é o mecanismo zero-copy. MessageChannel é como você arquiteta múltiplos workers se comunicando entre si.
Como funciona:
Algoritmo de clone estruturado — tipos suportados:
Não suportados: funções, símbolos (parcial), DOM nodes, classes (perdem prototype), getters/setters
Code sample: o que é clonado, o que falha:
// OKw.postMessage({ name: 'Ada', born: new Date('1815'), tags: new Set(['math']) });// FALHAw.postMessage({ greet: () => 'hi' }); // Throws: function not cloneableclass Foo {}w.postMessage(new Foo()); // Clona dados, mas perde prototype
transferList para zero-copy:
const buf = new ArrayBuffer(100_000_000);w.postMessage(buf, [buf]);// buf no main agora está detached: buf.byteLength === 0
MessageChannel para canais bidirecionais:
import { Worker, MessageChannel } from 'node:worker_threads';const { port1, port2 } = new MessageChannel();const w = new Worker('./worker.js');w.postMessage({ port: port2 }, [port2]); // transfer port2 to workerport1.on('message', (m) => console.log('from worker:', m));port1.postMessage('hello worker via dedicated channel');
Tabela: o que é clonado vs movido vs falha.
Na prática: padrões:
transferList essencial pra processamento de imagem, audio, ML inference (buffers grandes)
MessageChannel permite N workers comunicando entre si sem passar pelo main (broker pattern)
JSON.stringify + JSON.parse é frequentemente mais rápido que structured clone pra payloads pequenos com tipos simples (arrays de números, strings)
Armadilhas (3+):
Esquecer transferList em buffers grandes — cópia de 100MB acontece silenciosamente
Tentar enviar funções ou classes — clone falha em runtime, descobre só sob load
Usar MessageChannel sem fechar port — vaza file descriptor; sempre port.close() no shutdown
Achar que MessagePort é serializável em log/JSON — não é, é um handle de comunicação
Em entrevista:
Frase pronta: “Communication between Worker Threads goes through postMessage, which uses the structured clone algorithm to deep-copy the payload. That means most JS values work — primitives, plain objects, Maps, Sets, Buffers — but functions and class instances don’t survive. For zero-copy of large buffers, the second argument is transferList: the ArrayBuffer is moved instead of copied, leaving the original detached on the sender side. For multi-worker architectures, MessageChannel creates a dedicated bidirectional channel that you can transfer to a worker, letting workers talk to each other without going through main.”
[[05 - Memória compartilhada - SharedArrayBuffer e Atomics]]
[[06 - Pool de workers - pattern de produção]]
[[Node.js]] (tronco)
Step 4: Verificar rubrica (standard)
Step 5: Commit
git add "03-Dominios/Node/Paralelismo/04 - Comunicação entre workers - postMessage e MessageChannel.md"git commit -m "feat(node-paralelismo): add note 04 — Comunicação entre workers"
Task 6: Nota 05 — SharedArrayBuffer e Atomics
Files:
Create: 03-Dominios/Node/Paralelismo/05 - Memória compartilhada - SharedArrayBuffer e Atomics.md
Conteúdo-chave do spec: Concorrência real em JS. SharedArrayBuffer (visível em múltiplos workers, sem clone). Atomics para operações atômicas: Atomics.load/store/add/sub/compareExchange. Atomics.wait / Atomics.notify para sincronização. Race conditions canônicas. Casos legítimos. Restrições de segurança.
Nota especial: o spec do galho diz que essa nota não tem limite artificial de tamanho. Concorrência com memória compartilhada é tema profundo e merece a profundidade que pedir. O alvo é cobrir o panorama completo (estados, todas as ops do Atomics, wait/notify, race conditions canônicas, quando preferir mensagens) — não comprimir.
Step 3: Escrever a nota completa (sem limite — alvo 500-700 linhas se o tema pedir)
Cobrir, em PT-BR:
TL;DR:SharedArrayBuffer (SAB) é um buffer visível simultaneamente em múltiplos Workers — diferente de ArrayBuffer (clonado ou transferido). Acesso direto cria race conditions; use Atomics para operações atômicas e Atomics.wait/notify para sincronização. Casos legítimos: matrizes grandes em ML/imagens, contadores compartilhados, semáforos. Quando possível, preferir mensagens.
O que é: SAB e Atomics. SAB = ArrayBuffer que vive em memória compartilhada entre workers. Atomics = objeto global com operações atômicas sobre TypedArray que apontam pra SAB.
Por que importa: alternativa zero-copy + multi-worker pra trabalho pesado em buffers (matrizes, áudio, video frames). Bem usado, é a solução mais eficiente; mal usado, produz race conditions difíceis de reproduzir.
Como funciona:
Criando e compartilhando SAB:
// mainconst sab = new SharedArrayBuffer(1024); // 1KB compartilhadoconst view = new Int32Array(sab);w.postMessage({ sab }); // SAB não precisa estar no transferList — não é movido
Race condition canônica (incremento não-atômico):
// workerview[0]++; // RUIM — read + increment + write não atômicos// 2 workers fazendo isso → resultado incorreto
Atomics para operações atômicas:
Atomics.load(view, idx) — leitura atômica
Atomics.store(view, idx, val) — escrita atômica
Atomics.add(view, idx, val) — incremento atômico, retorna valor antigo
Atomics.notify(view, idx, count) — acorda até count workers em wait naquele índice
Atenção: Atomics.wait SÓ funciona em workers, NÃO no main thread (lança em main thread)
Padrões canônicos:
Contador atômico (counter compartilhado)
Spinlock primitivo (não recomendado em prod — preferir mensagens)
Producer-consumer com SAB + wait/notify
Na prática: quando SAB+Atomics é justificado:
Matrizes grandes em ML inference paralelizada (imagem dividida em tiles)
Streams de áudio/vídeo onde frames são compartilhados entre threads de processamento
Contadores de progresso visíveis em tempo real do main
Quando preferir mensagens: na maioria dos casos. SAB+Atomics é “concorrência baixo nível em JS” — fácil errar.
Armadilhas: (4+ armadilhas concretas):
Acessar SAB sem Atomics — race conditions silenciosas
Atomics.wait no main thread → throws (só funciona em workers)
Esquecer que Int32Array index é em índices, não bytes (view[1] é byte 4-7)
SAB cresce até byteLength fixo — não dá pra resize. Provisionar com folga
Confundir Atomics.add (retorna ANTIGO) com convenção pré/pós-incremento
Race condition em sequência de duas operações atômicas — atomicidade individual não compõe
Em entrevista:
Frase pronta: “SharedArrayBuffer is a buffer that’s visible simultaneously across multiple Worker Threads — unlike a regular ArrayBuffer, which is cloned or transferred. Once you have shared memory, you have race conditions, so reads and writes need Atomics — Atomics.load, store, add, compareExchange, and so on. For coordination, Atomics.wait and Atomics.notify give you a primitive condition variable, but wait only works inside Workers, not the main thread. The legitimate use cases are tight: large matrices in ML or image processing, shared counters, semaphores. For most application code, message passing is simpler and the right default.”
Vocabulário (6+): memória compartilhada (shared memory), operação atômica (atomic operation), condição de corrida (race condition), comparar-e-trocar (compare-and-swap), aguardar e notificar (wait and notify), variável de condição (condition variable), spinlock.
Veja também:
[[03 - Worker Threads - fundamentos]]
[[04 - Comunicação entre workers - postMessage e MessageChannel]]
[[06 - Pool de workers - pattern de produção]]
[[Node.js]] (tronco)
Step 4: Verificar rubrica (standard, code samples mínimo 5 — tema é operacional e race conditions só ficam claras com código)
Step 5: Commit
git add "03-Dominios/Node/Paralelismo/05 - Memória compartilhada - SharedArrayBuffer e Atomics.md"git commit -m "feat(node-paralelismo): add note 05 — SharedArrayBuffer e Atomics"
Task 7: Nota 06 — Pool de workers
Files:
Create: 03-Dominios/Node/Paralelismo/06 - Pool de workers - pattern de produção.md
Conteúdo-chave do spec: Reusar workers, queue, bounded concurrency, piscina como referência, lifecycle, graceful shutdown.
---title: "Pool de workers: pattern de produção"created: 2026-05-07updated: 2026-05-07type: conceptstatus: seedlingpublish: truetags: - node - paralelismo - worker-threads - pool - piscinaaliases: - Worker pool - piscina - bounded concurrency---
Step 3: Escrever a nota (350-500 linhas)
TL;DR: Em produção, criar um Worker por task é caro (custo de criação amortizado, GC pressure). O pattern canônico é pool: N workers reutilizáveis + queue de tasks pendentes. piscina é a lib de referência. Implementação manual: queue + worker pool + handoff via MessagePort. Sempre incluir graceful shutdown.
O que é: worker pool = abstração que mantém N workers vivos e despacha tasks pra eles via queue. Evita custo de spawn por task.
Por que importa: sem pool, app sob carga cria/destroi workers num loop hot — o custo de ~ms por criação vira gargalo, e o GC tem que limpar workers terminados constantemente.
Como funciona:
Implementação manual mínima (~30 linhas) — pool de 4 workers + queue:
Pool sem maxQueue — backpressure se acumula até OOM
Esquecer pool.destroy() em SIGTERM — graceful shutdown não acontece, tasks em andamento perdidas
Tasks com side effects (escrita em DB) sem idempotência — crash + retry corrompem
maxThreads muito alto em apps com pouca CPU dedicada — context switching mata throughput
Em entrevista:
Frase pronta: “In production, you don’t create a Worker per task — the spawn cost adds up and the garbage collector has to clean up dead workers constantly. The canonical pattern is a worker pool: a fixed number of workers kept alive, with a queue of pending tasks. The reference implementation is piscina, by Matteo Collina — it handles thread management, queueing, idle timeout, and graceful shutdown. The interesting tuning knob is maxThreads, typically set to the number of CPU cores. Always wire pool.destroy() to your SIGTERM handler so in-flight tasks complete before shutdown.”
Vocabulário (5+): pool de workers (worker pool), fila de tarefas (task queue), concorrência limitada (bounded concurrency), encerramento gracioso (graceful shutdown), tempo limite de inatividade (idle timeout).
Veja também:
[[03 - Worker Threads - fundamentos]]
[[04 - Comunicação entre workers - postMessage e MessageChannel]]
[[10 - Cluster vs PM2 vs Kubernetes - quem orquestra]]
[[12 - Armadilhas, regras práticas, cheatsheet]]
[[Node.js]] (tronco)
Step 4: Verificar rubrica (standard)
Step 5: Commit
git add "03-Dominios/Node/Paralelismo/06 - Pool de workers - pattern de produção.md"git commit -m "feat(node-paralelismo): add note 06 — Pool de workers"
Task 8: Nota 07 — Cluster
Files:
Create: 03-Dominios/Node/Paralelismo/07 - Cluster - escalando HTTP por CPU.md
Conteúdo-chave do spec: API: cluster.isPrimary, cluster.fork(), eventos. Restart automático. Port sharing. Sticky sessions. Graceful shutdown.
TL;DR: Cluster é o módulo nativo que fork-a múltiplos processos Node compartilhando a mesma porta HTTP. Primary controla; workers atendem requests. Round-robin no Linux. Útil em deploys single-VM; em prod com orquestrador (K8s, ECS), o orquestrador já faz isso.
O que é, Por que importa, Como funciona com:
Code sample minimal: primary forks N workers, cada worker ouve port 3000:
import cluster from 'node:cluster';import { availableParallelism } from 'node:os';import http from 'node:http';if (cluster.isPrimary) { const numCPUs = availableParallelism(); for (let i = 0; i < numCPUs; i++) cluster.fork(); cluster.on('exit', (worker) => { console.log(`worker ${worker.process.pid} died, restarting`); cluster.fork(); });} else { http.createServer((req, res) => res.end(`pid ${process.pid}`)).listen(3000);}
Port sharing: como funciona (kernel SO_REUSEPORT no Linux + round-robin do Node)
Sticky sessions: por que precisa (WebSocket); como implementar com @socket.io/sticky ou nginx upstream ip_hash
Graceful shutdown: SIGTERM no primary → primary manda disconnect nos workers → workers param de aceitar novas conexões → drain → exit
Na prática: cluster sozinho é raramente usado em prod nova; quando ainda usado é em VMs single-host (small SaaS, internal tooling, scripts/CLIs que precisam paralelizar HTTP)
Armadilhas (3+):
State em memória local de worker (cache, sessões) — comportamento inconsistente entre workers
Esquecer cluster.on('exit', ...) — worker morre e ninguém substitui
Sticky sessions sem reverse proxy ciente — round-robin do kernel mata WebSocket
Usar cluster + orquestrador (1 pod com cluster de 4 + 4 réplicas K8s) = 16 processos sem necessidade
Em entrevista: frase pronta + vocabulário (cluster, primary/worker, port sharing, sticky session, graceful shutdown)
TL;DR:exec (bufferizado, conveniente, vulnerável a shell injection), execFile (sem shell, mais seguro), spawn (streaming, sem buffer limit, ideal pra output longo). Regra: nunca passar input do usuário pro shell; preferir execFile/spawn com array de args.
O que é, Por que importa, Como funciona com code samples:
TL;DR:fork('./worker.js') cria child Node com canal IPC built-in (child.send() / process.on('message')). Diferente de Worker Thread: isolamento total de memória, separate event loop, separate V8 isolate, custo de criação maior (~100ms). Quando preferir fork sobre Worker: isolamento total, native modules incompatíveis com Worker, supervisor tree, processo descartável.
Create: 03-Dominios/Node/Paralelismo/10 - Cluster vs PM2 vs Kubernetes - quem orquestra.md
Conteúdo-chave do spec: Histórico (cluster brilhou ~2014-2018, PM2 fez cluster + watchdog ~2018-2020, hoje K8s/ECS são default). Quando cluster ainda faz sentido em 2026.
Buscar também: discussões recentes sobre cluster nativo em 2026 (pode ser via WebSearch se WebFetch não bastar).
Step 2: Frontmatter
---title: "Cluster vs PM2 vs Kubernetes: quem orquestra"created: 2026-05-07updated: 2026-05-07type: conceptstatus: seedlingpublish: truetags: - node - paralelismo - cluster - pm2 - kubernetes - productionaliases: - PM2 - K8s Node - Cluster vs orquestrador---
Step 3: Escrever a nota (350-500 linhas)
TL;DR: Cluster nativo brilhou em ~2014-2018 quando deploys eram em VMs single-host. PM2 ofereceu cluster + watchdog + logs (default ~2018-2020). Hoje (2026), Kubernetes/ECS/Nomad fazem fork em escala diferente: 1 pod por core, autoscaling horizontal, rolling updates declarativos. Cluster nativo virou raro em prod nova — use orquestrador. Cluster nativo só faz sentido em single-VM deploys ou em scripts/CLIs.
O que é: contraste histórico das 3 abordagens.
Por que importa: muitas equipes ainda usam cluster + K8s sem perceber a redundância (1 pod com cluster de 4 + 4 réplicas K8s = 16 processos). Saber o histórico ajuda a fazer escolhas que envelhecem bem.
Como funciona:
Cluster nativo: API stdlib, primary/worker, port sharing kernel
PM2: wrapper sobre cluster + features (watchdog, logs, zero-downtime reload, monitoring dashboard)
Kubernetes: pod = 1 processo (geralmente Node sem cluster), N pods replica horizontal, kube-proxy/ingress balanceia
Na prática:
Em 2026: K8s/ECS/Nomad é o default em qualquer empresa de médio porte
PM2 ainda usado em VPS pequenos / single-VM (Hetzner, Linode, Digital Ocean droplets)
Cluster nativo: dev local (testar comportamento multi-worker), single-VM deploys de SaaS pequeno, scripts CLI que precisam paralelizar HTTP, ou em pods K8s de tamanho grande quando faz sentido aproveitar a CPU disponível por pod
Armadilhas (3+):
Cluster + K8s sem pensar — overhead inútil
State em worker (sessões, cache local) — funciona em dev, quebra em prod
Confiar em PM2 graceful reload sem testar — alguns apps quebram em SIGUSR2
Migrar pra K8s sem reescrever stateful logic — sessões em memória local viram bug em escala
Em entrevista: frase pronta + vocabulário (orquestrador, autoscaling, rolling update, réplica, balanceamento de carga, processo stateless)
Veja também: 07, 11, 12, Node.js (tronco)
Step 4: Verificar rubrica (standard)
Step 5: Commit
git add "03-Dominios/Node/Paralelismo/10 - Cluster vs PM2 vs Kubernetes - quem orquestra.md"git commit -m "feat(node-paralelismo): add note 10 — Cluster vs PM2 vs K8s"
Task 12: Nota 11 — Decision tree
Files:
Create: 03-Dominios/Node/Paralelismo/11 - Decision tree - qual ferramenta para qual problema.md
Conteúdo-chave do spec: Síntese com fluxograma. Decision tree em ASCII. Tabela problema → ferramenta → razão.
Step 1: Síntese (sem WebFetch)
Reler todas as 10 notas anteriores e o spec do galho. Esta nota é puramente síntese.
Step 2: Frontmatter
---title: "Decision tree: qual ferramenta para qual problema"created: 2026-05-07updated: 2026-05-07type: conceptstatus: seedlingpublish: truetags: - node - paralelismo - decision-tree - referenciaaliases: - Decision tree paralelismo - Qual ferramenta usar---
Step 3: Escrever a nota (300-450 linhas)
Estrutura tópica (não narrativa pura — combina prosa com fluxograma e tabela):
TL;DR: Pergunta-chave: qual o problema? CPU-bound em handler → Worker Thread (com pool em prod). Escalar HTTP além de single-thread → orquestrador (K8s); Cluster apenas se single-VM. Rodar comando externo → spawn / execFile (nunca exec com input do user). Spawn de Node isolado → fork.
O que é: decision tree como artefato — separa problema (CPU? HTTP? OS?) da ferramenta (Worker / Cluster / spawn / fork).
Por que importa: a maioria dos erros não é técnico — é escolher a ferramenta errada pro problema.
Como funciona — fluxograma ASCII completo:
Qual o problema?
├─ CPU-bound em handler/job?
│ └─ → Worker Thread
│ ├─ Tarefa frequente? → pool (piscina)
│ └─ Tarefa rara? → Worker per task OK
│
├─ Preciso escalar HTTP além de 1 thread?
│ ├─ Tem orquestrador (K8s/ECS)? → deixa o orquestrador (1 pod por core)
│ ├─ Single-VM deploy / VPS? → Cluster (ou PM2)
│ └─ Dev local pra testar comportamento multi-worker? → Cluster
│
├─ Preciso rodar comando externo (ffmpeg, git, ls)?
│ ├─ Output curto, sem input do usuário? → execFile (com array de args)
│ ├─ Output streaming? → spawn
│ └─ Comando hardcoded sem input? → exec OK
│ (com input do usuário → NUNCA exec — shell injection)
│
└─ Preciso spawn de processo Node isolado?
├─ Isolamento total (memória, native modules, security)? → fork
├─ CPU-bound só → Worker Thread (mais leve)
└─ Supervisor tree / processo descartável → fork
Tabela problema → ferramenta → razão:
Problema
Ferramenta
Por quê
Hash bcrypt em handler
Worker Thread + pool
CPU-bound, mesmo processo, pool reusável
Image processing 100MB/req
Worker Thread + transferList
Zero-copy de buffers grandes
Matrix ops em ML inference
Worker Thread + SharedArrayBuffer
Memória compartilhada zero-copy
Servir HTTP com 4 cores
K8s 4 réplicas / Cluster (single VM)
Round-robin de conexões
Rodar ffmpeg
spawn
Streaming output
Rodar git log curto
execFile
Buffered + sem shell
Sandbox de código user
fork (ou vm/isolated-vm)
Isolamento total
Worker tree (queue managers)
fork + supervisor pattern
Crash + respawn é OK
Na prática: aplicar a decision tree:
Caso 1: endpoint que recebe upload de imagem e gera thumbnail → Worker Thread + pool (CPU-bound, freq alta)
Caso 2: API que executa aws s3 ls para o user → execFile com array de args (nunca exec)
Caso 3: build server que orquestra child processes → fork + supervisor
Caso 4: WebSocket server escalando em K8s → 4 pods, sem cluster nativo, sticky session via ingress
Armadilhas (3+):
Confundir CPU-bound com problemas de DB lento — DB lento ≠ CPU-bound
Usar Cluster + K8s sem pensar — overhead duplicado
Achar que “vou usar Worker Thread” resolve qualquer problema — só CPU-bound
exec com input do user — sempre vulnerabilidade
Em entrevista: frase pronta integrada + vocabulário consolidado
Veja também: 12, todos os outros do galho, MOC, Node.js, Runtime e Event Loop
Step 4: Verificar rubrica (standard, fluxograma é o code sample principal)
Step 5: Commit
git add "03-Dominios/Node/Paralelismo/11 - Decision tree - qual ferramenta para qual problema.md"git commit -m "feat(node-paralelismo): add note 11 — Decision tree"
Em 03-Dominios/Node/Paralelismo/Paralelismo.md, encontrar:
## Sobre este galho(introdução curta — preencher na Task 14)
Substituir SOMENTE a linha (introdução curta — preencher na Task 14) por:
Este galho cobre **as 3 ferramentas de paralelismo em Node**: Worker Threads (threads JS no mesmo processo), Cluster (múltiplos processos compartilhando porta HTTP), child_process (processo externo via spawn/exec ou Node child via fork). Inclui SharedArrayBuffer/Atomics (concorrência com memória compartilhada), pool de workers (pattern de produção, `piscina`), contexto de produção em 2026 (Cluster vs PM2 vs Kubernetes) e uma decision tree completa de "qual ferramenta para qual problema".Pré-requisito: galho 1 ([[Runtime e Event Loop]]). Em particular as notas [[09 - async-await - o que é, o que não é]] (mito da performance) e [[10 - Bloqueio do event loop - sintomas e causas]] (sintomas que pedem paralelismo).**Audiência primária:** dev senior em prep para entrevista internacional. Cada nota tem seção "Em entrevista" com frase pronta em inglês + vocabulário.**Audiência secundária:** o mesmo dev decidindo arquitetura ou debugando problemas de CPU em produção.
Manter o header ## Sobre este galho.
Step 3: Verificar todos os wikilinks resolvem
Confirmar que cada [[01 - ...]] até [[12 - ...]] corresponde a um arquivo existente:
for i in 01 02 03 04 05 06 07 08 09 10 11 12; do ls "03-Dominios/Node/Paralelismo/" | grep "^$i" || echo "MISSING: nota $i"done
Esperado: 1 match. Anotar o número da linha. Depois encontrar onde termina (próxima ### ou ##).
Step 2: Substituir a seção ### Worker Threads, cluster, child_process — as 3 formas de paralelismo
Substituir TODO o conteúdo entre o ### Worker Threads... e a próxima seção (mantendo o header) por:
### Worker Threads, cluster, child_process — as 3 formas de paralelismo> [!nota] Migrado para galho próprio> > As 3 ferramentas de paralelismo foram expandidas em [[Paralelismo]] (galho 2). Veja em particular [[02 - As 3 ferramentas - Worker Threads, Cluster, child_process]] (visão geral comparativa), [[03 - Worker Threads - fundamentos]] (Worker Threads), [[07 - Cluster - escalando HTTP por CPU]] (Cluster), [[08 - child_process com exec e spawn]] (rodar comandos externos) e [[09 - child_process com fork - Node child com IPC]] (Node child isolado). Decision tree completa em [[11 - Decision tree - qual ferramenta para qual problema]].
IMPORTANTE: Preservar o nível EXATO do header (### três hashes). Cuidado para não deletar a seção seguinte.
Step 3: Adicionar wikilink no ## Veja também do tronco
No tronco, encontrar ## Veja também (perto do final). Adicionar como segundo bullet (depois de [[Runtime e Event Loop]] que foi adicionado no galho 1):
- [[Paralelismo]] — galho 2 da trilha Node Senior; as 3 ferramentas de paralelismo (Worker Threads, Cluster, child_process), SharedArrayBuffer/Atomics, pool de workers, decision tree
Step 4: Atualizar updated no frontmatter do tronco
Mudar updated: 2026-05-07 (já estava nesse valor desde o galho 1) — confirmar que está em 2026-05-07. Se estiver em data anterior, atualizar.
Step 5: Commit
git add "03-Dominios/JavaScript/Backend/Node.js.md"git commit -m "refactor(node): prune trunk Node.js.md, link to Paralelismo branch"
Task 16: MOC central + verificação final
Files:
Modify: 03-Dominios/Node/index.md
Step 1: Atualizar MOC central
Em 03-Dominios/Node/index.md, encontrar a seção:
### Galhos da trilha Node Senior- [[Runtime e Event Loop]] — galho 1: o motor do Node (single-thread, libuv, fases, microtasks, async/await, bloqueio, diagnóstico)
Adicionar logo abaixo:
- [[Paralelismo]] — galho 2: as 3 ferramentas de paralelismo (Worker Threads, Cluster, child_process), SharedArrayBuffer/Atomics, pool de workers, contexto de produção, decision tree
Atualizar updated: 2026-05-07 no frontmatter (se ainda não estiver).
Step 2: Commit MOC central
git add "03-Dominios/Node/index.md"git commit -m "feat(node-paralelismo): wire branch into central Node MOC"
Step 3: Verificação final — critérios de aceitação
# 1. 13 arquivos no diretóriols "03-Dominios/Node/Paralelismo/" | wc -l# Esperado: 13# 2. Todos com publish: truegrep -l "publish: true" "03-Dominios/Node/Paralelismo/"*.md | wc -l# Esperado: 13# 3. Total de linhas do galhowc -l "03-Dominios/Node/Paralelismo/"*.md | tail -1# 4. Tronco tem agora 5 callouts (4 do galho 1 + 1 do galho 2)grep -c "Migrado para galho próprio" "03-Dominios/JavaScript/Backend/Node.js.md"# Esperado: 5# 5. MOC central linka pros 2 galhosgrep -E "Runtime e Event Loop|Paralelismo" "03-Dominios/Node/index.md" | grep -v "^#" | wc -l# Esperado: pelo menos 2 matches (1 por galho)
Reportar o resultado de cada check.
Step 4: Closing commit
git commit --allow-empty -m "chore(node-paralelismo): close branch Galho 2 — Paralelismo12 atomic notes + MOC published in 03-Dominios/Node/Paralelismo/.Trunk Node.js.md pruned (single section). Central Node MOC updated.All acceptance criteria from 2026-05-07-node-paralelismo-design.md met."
Sem Co-Authored-By.
Step 5: Quartz check (passivo)
O Quartz tem deploy via CI (.github/workflows/trigger-site-deploy.yaml); commits em main disparam o build automaticamente. Não é necessário rodar localmente. Mencionar no relatório.
Pós-execução
Atualizar memória se algum aprendizado novo apareceu — galho 2 tem peculiaridades (poda mais simples; novo padrão de wikilinks pro galho anterior; SharedArrayBuffer sem limite de tamanho)
Revisar 2026-05-07-node-roadmap-design.md com aprendizados — afinar a “Política de poda do tronco” se necessário
Decidir destino final do tronco — se já passou do galho 1 + galho 2, o tronco está com 5 callouts; mais um galho e a estrutura começa a se inverter (mais callouts que conteúdo). Ponto de avaliar se vira MOC.
Próximo galho — escolher entre Galho 3 (Streams), Galho 5 (Observability), Galho 4 (Frameworks), ou Galho 6 (Segurança), conforme prioridade do momento
Self-review do plano
Spec coverage:
12 nomes de nota do spec seção 5 cobertos por Tasks 2-13 ✓
MOC criado em Task 1, finalizado em Task 14 ✓
5 rotas alternativas presentes no MOC esqueleto (Task 1) — incluindo “completa” implícita ✓
Tasks de poda (spec seção 10): cobertas em Task 15 ✓
Atualização do MOC central: Task 16 ✓
Critérios de aceitação (spec seção 12): checklist em Task 16 step 3 ✓
Bibliografia (spec seção 8): centralizada no topo + WebFetch específico em cada Task ✓
Restrição de fabricação: bloco no topo + na rubrica de cada nota ✓
Nota 05 (SharedArrayBuffer) sem limite artificial — consistente com spec refinement aprovado pelo usuário ✓
Placeholder scan: O único (introdução curta — preencher na Task 14) é placeholder INTENCIONAL com instrução explícita de substituição — não é placeholder de plano ✓
Type consistency: títulos de notas batem entre Task de criação, MOC esqueleto (Task 1), pass final (Task 14), e poda do tronco (Task 15). Wikilinks usam mesmo título nominal em todas as ocorrências ✓
Coesão com galho 1: wikilinks pra [[Runtime e Event Loop]], [[09 - async-await - o que é, o que não é]], [[10 - Bloqueio do event loop - sintomas e causas]] aparecem nas notas certas (especialmente nota 01) ✓