This guide covers the complete process for updating Rust-based PostgreSQL extensions that use pgrx (formerly pgx). These extensions include wrappers, pg_graphql, and pg_jsonschema.
Updating a pgrx extension can involve one or more of these changes:
- Extension version only - New release of the extension with same Rust/pgrx versions
- Extension + pgrx version - Extension requires a newer pgrx version
- Extension + pgrx + Rust version - Full stack update including the Rust toolchain
Each scenario requires different file changes. This guide covers all three.
| Purpose | File |
|---|---|
| Extension versions | nix/ext/versions.json |
| Extension-specific config | nix/ext/<name>/default.nix |
| pgrx versions + Rust mappings | nix/cargo-pgrx/versions.json |
| cargo-pgrx package definitions | nix/cargo-pgrx/default.nix |
| pgrx extension builder | nix/cargo-pgrx/mkPgrxExtension.nix |
| Overlays (buildPgrxExtension_*) | nix/overlays/default.nix |
| Rust toolchain source | flake.nix (rust-overlay input) |
| Pinned rust-overlay version | flake.lock |
| Situation | Scenario |
|---|---|
| Same pgrx and Rust as previous version | 1 - Extension only |
| Extension's Cargo.toml has newer pgrx | 2 - Extension + pgrx |
| Extension requires Rust version not in rust-overlay | 3 - Full stack update |
| "attribute missing" error for Rust version | 3 - Need nix flake update rust-overlay |
Use this when the extension has a new release but uses the same pgrx and Rust versions as a previous version.
| File | Change |
|---|---|
nix/ext/versions.json |
Add new version entry |
nix/ext/<extension>/default.nix |
Add old version to allPreviouslyPackagedVersions |
-
Edit
nix/ext/versions.json- Add the new version entry:"wrappers": { "0.5.6": { "postgresql": ["15", "17", "orioledb-17"], "hash": "sha256-...", "pgrx": "0.16.0", "rust": "1.87.0" }, "0.5.7": { "postgresql": ["15", "17", "orioledb-17"], "hash": "", "pgrx": "0.16.0", "rust": "1.87.0" } }
- Copy the
pgrxandrustvalues from the previous version - Set
hashto""initially
- Copy the
-
Update
allPreviouslyPackagedVersionsinnix/ext/<extension>/default.nix:allPreviouslyPackagedVersions = [ "0.5.6" # Add the previous version here "0.5.5" # ... older versions ];
This ensures migration SQL files are created for users upgrading from older versions.
-
Stage your changes:
git add . -
Build to get the hash:
nix build .#psql_17.exts.wrappers -LThe build will fail and print the correct hash. Copy it to
versions.json. -
Rebuild to verify:
nix build .#psql_17.exts.wrappers -L
Use this when the extension requires a newer pgrx version.
| File | Change |
|---|---|
nix/ext/versions.json |
Add new version with new pgrx version |
nix/ext/<extension>/default.nix |
Add old version to allPreviouslyPackagedVersions |
nix/cargo-pgrx/versions.json |
Add new pgrx version (if not already present) |
nix/cargo-pgrx/default.nix |
Add new cargo-pgrx_x_y_z entry (if not already present) |
nix/overlays/default.nix |
Add new buildPgrxExtension_x_y_z (if not already present) |
-
Check if the pgrx version exists in
nix/cargo-pgrx/versions.json:cat nix/cargo-pgrx/versions.json | grep "0.16.1"
-
If pgrx version doesn't exist, add it to
nix/cargo-pgrx/versions.json:"0.16.1": { "hash": "", "rust": { "1.88.0": { "cargoHash": "" } } }
The
rustobject maps Rust versions to their correspondingcargoHash. You'll need to calculate both thehash(for the pgrx crate) andcargoHash(for cargo dependencies). -
Add cargo-pgrx entry in
nix/cargo-pgrx/default.nix:cargo-pgrx_0_16_1 = mkCargoPgrx { version = "0.16.1"; hash = ""; cargoHash = ""; };
-
Add overlay entry in
nix/overlays/default.nix:buildPgrxExtension_0_16_1 = prev.buildPgrxExtension.override { cargo-pgrx = final.cargo-pgrx.cargo-pgrx_0_16_1; };
-
Update
nix/ext/versions.jsonwith the new extension version:"0.5.7": { "postgresql": ["15", "17", "orioledb-17"], "hash": "", "pgrx": "0.16.1", "rust": "1.88.0" }
-
Stage and build to calculate hashes:
git add . nix build .#psql_17.exts.wrappers -L
You'll need to run this multiple times, updating hashes as they're calculated:
- First failure: pgrx crate hash
- Second failure: cargoHash for pgrx
- Third failure: extension hash
Use this when you need a newer Rust toolchain version.
All files from scenario 2, plus:
| File | Change |
|---|---|
flake.lock |
Update rust-overlay input |
The Rust toolchain comes from the rust-overlay flake input. This overlay provides pre-built Rust versions with hashes already calculated. The overlay is updated daily on GitHub, but your local flake.lock pins a specific version.
-
Check if your Rust version is available:
nix eval --raw --impure --expr ' let flake = builtins.getFlake (toString ./.); pkgs = import flake.inputs.nixpkgs { system = builtins.currentSystem; overlays = [ (import flake.inputs.rust-overlay) ]; }; in builtins.concatStringsSep "\n" (builtins.attrNames pkgs.rust-bin.stable) '
This lists all available stable Rust versions.
-
If your Rust version is missing, update rust-overlay:
nix flake update rust-overlay
IMPORTANT: Use
nix flake update rust-overlay(with the input name) to update ONLY the rust-overlay input. Runningnix flake updatewithout arguments updates ALL inputs, which WILL cause unintended changes. -
Verify the version is now available:
nix eval --raw --impure --expr ' let flake = builtins.getFlake (toString ./.); pkgs = import flake.inputs.nixpkgs { system = builtins.currentSystem; overlays = [ (import flake.inputs.rust-overlay) ]; }; in builtins.concatStringsSep "\n" (builtins.attrNames pkgs.rust-bin.stable) ' | grep "1.88.0"
-
Add the new Rust version to pgrx mappings in
nix/cargo-pgrx/versions.json:"0.16.1": { "hash": "sha256-...", "rust": { "1.87.0": { "cargoHash": "sha256-..." }, "1.88.0": { "cargoHash": "" } } }
Each pgrx version can support multiple Rust versions. The
cargoHashmay differ between Rust versions. -
Continue with extension update as in scenario 2.
After making changes, verify everything works:
nix flake check -LThe -L flag shows full build logs, which is essential for debugging.
- All extension builds for all PostgreSQL versions
- Extension test suites
- Migration path validity (upgrade scripts between versions)
- Package structure integrity
For faster iteration, test just your extension before running full checks:
# Build for one PostgreSQL version
nix build .#psql_17.exts.wrappers -L
# Build for all PostgreSQL versions
nix build .#psql_15.exts.wrappers -L
nix build .#psql_17.exts.wrappers -LExample:
error: attribute '"1.88.0"' missing
at /nix/store/.../nix/ext/wrappers/default.nix:19:15:
cargo = rust-bin.stable.${rustVersion}.default;
Did you mean one of 1.38.0, 1.48.0, 1.58.0, 1.68.0 or 1.78.0?
Cause: The Rust version specified in versions.json isn't available in your pinned rust-overlay.
Solution:
nix flake update rust-overlayThen verify the version is available (see section 3).
Cause: The pgrx version in versions.json isn't defined in nix/cargo-pgrx/versions.json.
Solution: Add the pgrx version entry to nix/cargo-pgrx/versions.json with appropriate Rust version mappings.
Cause: The Rust version isn't mapped for this pgrx version in nix/cargo-pgrx/versions.json.
Solution: Add the Rust version to the pgrx entry:
"0.16.1": {
"hash": "sha256-...",
"rust": {
"1.87.0": { "cargoHash": "sha256-..." },
"1.88.0": { "cargoHash": "" } // Add this
}
}When calculating hashes, you'll see errors like:
hash mismatch in fixed-output derivation:
wanted: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
got: sha256-xYz123ActualHashValue...=
Copy the got value to replace the empty or incorrect hash.
If the build still fails after updating hashes:
- Stage all changes:
git add . - Clean Nix cache (if necessary):
nix store gc - Rebuild:
nix build .#psql_17.exts.<extension> -L
Some extensions (like wrappers) have git dependencies that require outputHashes in their cargoLock configuration. If you see errors about missing hashes for git dependencies:
- Check the extension's
default.nixfor thecargoLock.outputHashessection - Add any new git dependencies with their calculated hashes