Summary
On Windows, embedded-postgres currently starts the postgres postmaster as a child of the caller's terminal session and registers an unconditional process-exit shutdown hook. That makes it difficult to run one persistent embedded cluster that is reused by several local processes.
This is a lifecycle/isolation issue rather than a Postgres data issue.
Environment
- Package:
embedded-postgres@17.10.0-beta.17
- OS: Windows 11 x64
- Runtime observed with: Bun 1.3.x / Node-compatible
child_process
- Postgres: package-provided Windows x64 binary
Observed behavior
- Start a persistent embedded cluster from a terminal.
- Reuse that cluster from another process.
- Press Ctrl+C in the terminal that started the cluster, or let a short-lived starter process exit.
Observed effects:
- The postmaster/backends can receive the terminal Ctrl+C event, causing query cancellation and/or fast shutdown of the cluster.
- The package-level
async-exit-hook shutdown handler stops the cluster when the starter process exits, even when the caller wants a persistent shared cluster to outlive that process.
- The current readiness check is tied to parsing stderr output from the child process. A detached/hidden-console launch mode needs connection-based readiness polling instead.
Expected behavior
There should be a supported lifecycle mode for persistent reused clusters where:
- Ctrl+C in the starter terminal does not reach the Postgres postmaster/backends.
- The cluster can intentionally outlive a short-lived process when
persistent: true and the caller asks for detached/shared lifecycle behavior.
stop() still works explicitly.
- Startup readiness is detected by connecting to Postgres instead of relying only on stderr log parsing.
Implementation direction that worked downstream
A downstream patch solved this by:
- On Windows, launching the postmaster with
CreateProcessW and CREATE_NO_WINDOW, tracking the returned postmaster PID for stop().
- On POSIX, spawning detached so terminal SIGINT does not reach the postmaster.
- Polling
pg with SELECT 1 until startup/WAL recovery finishes.
- Making implicit shutdown-on-parent-exit optional for the persistent shared-cluster use case.
I am happy to follow up with a PR if this direction fits the project's API. The key API question is whether this should be a new option such as shutdownOnExit?: boolean / detached?: boolean, or a broader lifecycle mode option.
Summary
On Windows,
embedded-postgrescurrently starts thepostgrespostmaster as a child of the caller's terminal session and registers an unconditional process-exit shutdown hook. That makes it difficult to run one persistent embedded cluster that is reused by several local processes.This is a lifecycle/isolation issue rather than a Postgres data issue.
Environment
embedded-postgres@17.10.0-beta.17child_processObserved behavior
Observed effects:
async-exit-hookshutdown handler stops the cluster when the starter process exits, even when the caller wants a persistent shared cluster to outlive that process.Expected behavior
There should be a supported lifecycle mode for persistent reused clusters where:
persistent: trueand the caller asks for detached/shared lifecycle behavior.stop()still works explicitly.Implementation direction that worked downstream
A downstream patch solved this by:
CreateProcessWandCREATE_NO_WINDOW, tracking the returned postmaster PID forstop().pgwithSELECT 1until startup/WAL recovery finishes.I am happy to follow up with a PR if this direction fits the project's API. The key API question is whether this should be a new option such as
shutdownOnExit?: boolean/detached?: boolean, or a broader lifecycle mode option.