The shared library is inside the machine.
PostgreSQL loads user-written C functions from shared libraries on demand. The server keeps a loaded object in memory for later calls in the same session. PostgreSQL's C extension guide says these functions follow the same coding conventions as internal functions.[2]
That is the appeal. An extension can use server data types, memory contexts, hooks, shared memory, and the Server Programming Interface. It is also the risk. A native extension is not a remote service with a network boundary.
Language safety and crash isolation answer different questions.
PostgreSQL and C++ unwind by different rules.
ClickHouse engineer Philip Dube describes the mismatch from four PostgreSQL extensions. PostgreSQL ties palloc allocations to memory contexts and uses setjmp and longjmp for error handling. C++ uses destructors and exceptions. A PostgreSQL jump can skip C++ cleanup. An uncaught C++ exception can abort the process.[1]
PostgreSQL's own guide tells extension authors to use palloc and pfree instead of malloc and free. It also requires a module magic block so the server can reject obvious incompatibilities, such as a library built for another PostgreSQL major version.[3]
One team used four boundary shapes.
ClickHouse removed C++ from pg_clickhouse. It kept C++ inside a narrow wrapper for pg_re2, with C++ allocation and exception handling kept away from PostgreSQL C calls. For pg_chdb, it moved the C++ dependency into a helper executable and exchanged data across a smaller protocol.[1]
pg_stat_ch currently keeps C++ in a background worker with handlers for C++ and PostgreSQL failures. The post warns that this is a mitigation, not a general isolation guarantee. A failed cleanup or damaged shared memory can still make the postmaster treat termination as a crash.[1]
Rust reduces one class of mistakes.
The pgrx project gives Rust extensions managed PostgreSQL versions, schema generation, type conversion, memory-context helpers, and cross-version tests. Its README says Rust panics can become PostgreSQL errors instead of process aborts. It also exposes direct unsafe access to PostgreSQL internals through pg_sys.[4]
Rust can make ownership and null handling easier to inspect. It does not turn in-process code into an isolated process. The extension still needs a pinned server version, failure tests, and review of every unsafe or foreign-function boundary.
Write the crash contract before the wrapper.
- List which side owns every allocation and release.
- State which calls may raise a PostgreSQL error or a language exception.
- Keep destructors away from paths that PostgreSQL can jump across.
- Record whether the code runs in a backend, managed worker, or helper process.
- Kill the extension path on purpose and record what restarts, disconnects, or survives.
- Pin the PostgreSQL major version, compiler, extension revision, and test command.