The one thing to understand first
Historically each PostgreSQL query ran in a single backend process. Parallel query lets the planner split eligible work across multiple worker processes that execute parts of the plan concurrently, then combine results. The machinery lives in src/backend/executor/nodeGather.c, execParallel.c, and the parallel-aware scan nodes.
Parallelism is a cost-based decision, not a guarantee: the planner only goes parallel when the table is big enough to repay worker startup, and it can only launch as many workers as the shared pool has free. “Planned 4, launched 2” is the signature of a pool too small for your concurrency.
The Gather node
A parallel plan has a Gather (or Gather Merge) node. Below it is the parallel portion run by the leader plus its workers; above it is serial. At execution, the leader launches background workers, each runs its copy of the sub-plan, and produces tuples into a shared queue; Gather collects them. Gather Merge preserves <a class="sev1-termlink" href="https://thesev1database.com/glossary/pathkeys/" title="Pathkeys">sort order by merging each worker’s ordered stream.