pgrx

A Rust framework for building safe, native PostgreSQL extensions without writing C.

Framework
Cargo
v0.19.2
4,769stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
87/100Excellent
Development Activity84
Maintenance100
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
90/100Excellent
Architecture88
Code Quality88
Innovation92
Learning Curve90

pgrx lets you write PostgreSQL extensions entirely in Rust, targeting the same C-level extension API that PostgreSQL itself exposes, but wrapped in safe, idiomatic abstractions. Functions marked #[pg_extern] are automatically exposed as SQL-callable user-defined functions, custom Rust structs and enums can be registered as native Postgres types, and the extension’s SQL schema is generated for you rather than hand-written and maintained separately.

Under the hood, pgrx translates Rust panics into Postgres ERRORs that abort only the current transaction instead of crashing the server process, and ties Rust’s ownership and drop semantics into Postgres’s own memory-context allocator so extension code behaves predictably even when Postgres itself errors out mid-call. A companion CLI, cargo-pgrx, manages the entire development loop: downloading and compiling supported PostgreSQL versions, scaffolding new extension crates, running an extension live inside psql for interactive testing, executing the test suite against multiple PostgreSQL versions, and packaging the extension for distribution.

The project is maintained by the PgCentral Foundation and backs a number of production PostgreSQL extensions, supporting PostgreSQL 13 through 19 from a single codebase via Cargo feature gating.

What You Get

  • #[pg_extern] macro to expose ordinary Rust functions as Postgres SQL-callable functions, with return types like SetOfIterator and TableIterator mapped to RETURNS SETOF / RETURNS TABLE
  • Automatic SQL schema generation via a build-time entity graph (pgrx_sql_entity_graph), so the extension’s .control/SQL files stay in sync with the Rust source instead of being hand-maintained
  • #[derive(PostgresType)] and #[derive(PostgresEnum)] to expose custom Rust structs and enums as native Postgres types, including binary send/recv protocol support
  • Safe Server Programming Interface (SPI) access for running queries against the current database from inside the extension
  • Panic-to-error translation (#[pg_guard]) so a Rust panic aborts the current transaction with a Postgres ERROR rather than crashing the backend process
  • The cargo-pgrx CLI: cargo pgrx init (download/compile supported PG versions), cargo pgrx new (scaffold an extension), cargo pgrx run (build, install, and drop into psql), cargo pgrx test, and cargo pgrx package
  • Cross-version compatibility from PostgreSQL 13 through 19 (plus 19beta1) from a single codebase, selected via Cargo feature flags

Common Use Cases

  • Writing custom aggregate functions, operators, or scalar/table-returning functions that need to run inside the database process for performance
  • Building a native Postgres data type (e.g. a custom geometric, encoded, or domain-specific value type) with its own I/O and binary protocol functions
  • Implementing background workers that run inside the Postgres process and coordinate with the database via SPI or shared memory
  • Wrapping an existing Rust library (parsing, cryptography, ML inference, etc.) as callable SQL functions without leaving the safety of Rust
  • Building trigger functions that need typed, panic-safe access to the modified row

Under The Hood

Architecture pgrx is organized as a Cargo workspace of cooperating crates rather than one monolith: pgrx-pg-sys provides raw, bindgen-generated FFI bindings to Postgres internals per supported server version; pgrx builds safe wrappers on top (SPI, PgBox, memory contexts, datum conversions, triggers, background workers); pgrx-macros and pgrx-sql-entity-graph implement the procedural macros and the build-time SQL entity graph that turns #[pg_extern]-annotated Rust functions into registered SQL objects; and cargo-pgrx is a separate CLI crate that owns the developer-facing scaffold/build/test/package lifecycle, including downloading and compiling the PostgreSQL versions an extension targets. An extension author’s code sits at the top of this stack, calling into the pgrx prelude and relying on the macro layer to generate the extern "C" glue Postgres actually calls.

Tech Stack The workspace targets a recent Rust edition with resolver = "3" and depends on bindgen (via the dedicated pgrx-bindgen crate) to generate raw C bindings to the Postgres source tree, thiserror for typed error types, uuid, enum-map, and bitflags in the public API surface, and cargo_metadata/cargo_toml/clap-cargo inside the cargo-pgrx CLI for driving Cargo and inspecting extension manifests. Building extensions additionally requires a C compiler and libclang, since pgrx compiles against and links a C shim into the target Postgres version.

Code Quality The workspace carries dedicated pgrx-tests and pgrx-unit-tests crates that run the test suite against real, live PostgreSQL instances, exercised across the full supported version matrix in CI (tests.yml, package-test.yaml, will-it-blend-develop.yml). Error handling is typed throughout via thiserror-based error enums (e.g. SpiError) rather than string errors or silent panics, rustfmt.toml and rust-analyzer.toml keep formatting consistent, and a deny.toml enforces license and dependency-security policy via cargo-deny. Over three dozen example extensions under pgrx-examples/ double as both documentation and integration-test fixtures.

What Makes It Unique Most Postgres extension development happens in C, where a wild pointer or an unchecked NULL can crash the whole server process. pgrx’s distinguishing bet is translating Rust’s safety guarantees across that boundary: panics become recoverable transaction-aborting errors instead of process crashes, and Rust’s Drop semantics are wired into Postgres’s own per-transaction memory-context allocator so cleanup happens correctly even on the error path. Combined with automatic SQL schema generation from annotated Rust code, it removes both of the traditionally hardest parts of extension development — memory safety and keeping hand-written SQL definitions in sync with the implementation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search