Skip to content

pgs3

S3-compatible object storage endpoint implemented inside PostgreSQL

pgs3 : S3-compatible object storage endpoint implemented inside PostgreSQL

Overview

ID Extension Package Version Category License Language
9430 pgs3 pgs3 0.1.1 SIM Apache-2.0 Rust
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
--sLd-- No Yes Yes Yes no no
Relationships
Schemas pgs3
See Also aws_s3 pg_lake pg_parquet pg_ducklake omni_aws
Early alpha; PG17-18; endpoint startup requires preload or pgs3.start(); TLS terminates externally; small-object and 100,000-object Fork performance gates remain unmet.

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT PIGSTY 0.1.1 18 17 16 15 14 pgs3 -
RPM PIGSTY 0.1.1 18 17 16 15 14 pgs3_$v -
DEB PIGSTY 0.1.1 18 17 16 15 14 postgresql-$v-pgs3 -
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
el8.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
el9.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
el9.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
el10.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
el10.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
d12.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
d12.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
d13.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
d13.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
u22.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
u22.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
u24.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
u24.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
u26.x86_64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
u26.aarch64 PIGSTY 0.1.1 PIGSTY 0.1.1 N/A N/A N/A
Package Version OS ORG SIZE File URL
pgs3_18 0.1.1 el8.x86_64 pigsty 919.2 KiB pgs3_18-0.1.1-1PGSTY.el8.x86_64.rpm
pgs3_18 0.1.1 el8.aarch64 pigsty 740.1 KiB pgs3_18-0.1.1-1PGSTY.el8.aarch64.rpm
pgs3_18 0.1.1 el9.x86_64 pigsty 892.7 KiB pgs3_18-0.1.1-1PGSTY.el9.x86_64.rpm
pgs3_18 0.1.1 el9.aarch64 pigsty 795.8 KiB pgs3_18-0.1.1-1PGSTY.el9.aarch64.rpm
pgs3_18 0.1.1 el10.x86_64 pigsty 892.7 KiB pgs3_18-0.1.1-1PGSTY.el10.x86_64.rpm
pgs3_18 0.1.1 el10.aarch64 pigsty 796.7 KiB pgs3_18-0.1.1-1PGSTY.el10.aarch64.rpm
postgresql-18-pgs3 0.1.1 d12.x86_64 pigsty 796.1 KiB postgresql-18-pgs3_0.1.1-1PGSTY~bookworm_amd64.deb
postgresql-18-pgs3 0.1.1 d12.aarch64 pigsty 655.4 KiB postgresql-18-pgs3_0.1.1-1PGSTY~bookworm_arm64.deb
postgresql-18-pgs3 0.1.1 d13.x86_64 pigsty 796.4 KiB postgresql-18-pgs3_0.1.1-1PGSTY~trixie_amd64.deb
postgresql-18-pgs3 0.1.1 d13.aarch64 pigsty 657.6 KiB postgresql-18-pgs3_0.1.1-1PGSTY~trixie_arm64.deb
postgresql-18-pgs3 0.1.1 u22.x86_64 pigsty 863.0 KiB postgresql-18-pgs3_0.1.1-1PGSTY~jammy_amd64.deb
postgresql-18-pgs3 0.1.1 u22.aarch64 pigsty 767.4 KiB postgresql-18-pgs3_0.1.1-1PGSTY~jammy_arm64.deb
postgresql-18-pgs3 0.1.1 u24.x86_64 pigsty 858.2 KiB postgresql-18-pgs3_0.1.1-1PGSTY~noble_amd64.deb
postgresql-18-pgs3 0.1.1 u24.aarch64 pigsty 762.8 KiB postgresql-18-pgs3_0.1.1-1PGSTY~noble_arm64.deb
postgresql-18-pgs3 0.1.1 u26.x86_64 pigsty 856.0 KiB postgresql-18-pgs3_0.1.1-1PGSTY~resolute_amd64.deb
postgresql-18-pgs3 0.1.1 u26.aarch64 pigsty 760.0 KiB postgresql-18-pgs3_0.1.1-1PGSTY~resolute_arm64.deb
Package Version OS ORG SIZE File URL
pgs3_17 0.1.1 el8.x86_64 pigsty 919.1 KiB pgs3_17-0.1.1-1PGSTY.el8.x86_64.rpm
pgs3_17 0.1.1 el8.aarch64 pigsty 740.0 KiB pgs3_17-0.1.1-1PGSTY.el8.aarch64.rpm
pgs3_17 0.1.1 el9.x86_64 pigsty 892.9 KiB pgs3_17-0.1.1-1PGSTY.el9.x86_64.rpm
pgs3_17 0.1.1 el9.aarch64 pigsty 796.2 KiB pgs3_17-0.1.1-1PGSTY.el9.aarch64.rpm
pgs3_17 0.1.1 el10.x86_64 pigsty 892.9 KiB pgs3_17-0.1.1-1PGSTY.el10.x86_64.rpm
pgs3_17 0.1.1 el10.aarch64 pigsty 794.9 KiB pgs3_17-0.1.1-1PGSTY.el10.aarch64.rpm
postgresql-17-pgs3 0.1.1 d12.x86_64 pigsty 796.4 KiB postgresql-17-pgs3_0.1.1-1PGSTY~bookworm_amd64.deb
postgresql-17-pgs3 0.1.1 d12.aarch64 pigsty 654.9 KiB postgresql-17-pgs3_0.1.1-1PGSTY~bookworm_arm64.deb
postgresql-17-pgs3 0.1.1 d13.x86_64 pigsty 796.4 KiB postgresql-17-pgs3_0.1.1-1PGSTY~trixie_amd64.deb
postgresql-17-pgs3 0.1.1 d13.aarch64 pigsty 654.8 KiB postgresql-17-pgs3_0.1.1-1PGSTY~trixie_arm64.deb
postgresql-17-pgs3 0.1.1 u22.x86_64 pigsty 862.9 KiB postgresql-17-pgs3_0.1.1-1PGSTY~jammy_amd64.deb
postgresql-17-pgs3 0.1.1 u22.aarch64 pigsty 767.5 KiB postgresql-17-pgs3_0.1.1-1PGSTY~jammy_arm64.deb
postgresql-17-pgs3 0.1.1 u24.x86_64 pigsty 858.2 KiB postgresql-17-pgs3_0.1.1-1PGSTY~noble_amd64.deb
postgresql-17-pgs3 0.1.1 u24.aarch64 pigsty 762.1 KiB postgresql-17-pgs3_0.1.1-1PGSTY~noble_arm64.deb
postgresql-17-pgs3 0.1.1 u26.x86_64 pigsty 856.0 KiB postgresql-17-pgs3_0.1.1-1PGSTY~resolute_amd64.deb
postgresql-17-pgs3 0.1.1 u26.aarch64 pigsty 759.9 KiB postgresql-17-pgs3_0.1.1-1PGSTY~resolute_arm64.deb

Source

pig build pkg pgs3;		# build rpm/deb

Install

Make sure PGDG and PIGSTY repo available:

pig repo add pgsql -u   # add both repo and update cache

Install this extension with pig:

pig install pgs3;		# install via package name, for the active PG version

pig install pgs3 -v 18;   # install for PG 18
pig install pgs3 -v 17;   # install for PG 17

Config this extension to shared_preload_libraries:

shared_preload_libraries = 'pgs3';

Create this extension with:

CREATE EXTENSION pgs3;

Usage

Sources:

pgs3 0.1.1 turns one PostgreSQL database into a path-style S3-compatible endpoint. PostgreSQL background workers authenticate SigV4 requests and execute versioned object operations against ordinary SQL tables, so object metadata, payloads, authorization, WAL, physical backup, and recovery remain inside PostgreSQL. It targets PostgreSQL 17 and 18 and remains early-alpha software.

Core Workflow

Install the extension in the database that will own the object store, create a restricted tenant role and credential, then start the worker pool:

CREATE EXTENSION pgs3;

CREATE ROLE tenant_app
  NOLOGIN NOINHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE
  NOREPLICATION NOBYPASSRLS;

SELECT pgs3.create_credential(
  'tenant-access-key', 'replace-with-a-secret', 'tenant_app'::name, true
);

SELECT pgs3.start();
TABLE pgs3.worker_state;
TABLE pgs3.stats;

For automatic startup, preload the library and configure the target database before restarting PostgreSQL:

shared_preload_libraries = 'pgs3'
pgs3.enabled = on
pgs3.target_database = 'artifacts'
pgs3.listen_addr = '127.0.0.1'
pgs3.port = 9000
pgs3.workers = 4

Adding or removing shared_preload_libraries, or changing pgs3.target_database, requires a PostgreSQL restart. Other documented settings use SIGHUP semantics, but operational readiness must be checked through pgs3.worker_state and logs rather than only an open TCP port. A manually started pool can be stopped with pgs3.stop().

Client and Storage Behavior

Clients must use path-style addressing and an explicit endpoint:

export PGS3_ENDPOINT='https://s3.example.com'
export AWS_ACCESS_KEY_ID='<access-key>'
export AWS_SECRET_ACCESS_KEY='<secret-key>'
export AWS_DEFAULT_REGION='us-east-1'

aws --endpoint-url "$PGS3_ENDPOINT" s3api list-buckets

Always pass --endpoint-url; otherwise an AWS client can silently send a request to AWS. The supported client paths include AWS CLI, boto3, rclone, s3fs, and DuckDB httpfs. Bucket and object operations include range and conditional reads/writes, ListObjectsV2, permanent version history, delete markers, CopyObject, and multipart upload.

The canonical payload lives in pgs3.blob. Object versions, CopyObject, SQL Restore, and metadata-only Fork operations can share the same blob rather than duplicating bytes. One endpoint serves one configured database.

Operations and Security

Credential access keys map to PostgreSQL tenant roles. Keep those roles NOLOGIN, NOINHERIT, and NOBYPASSRLS; do not use pgs3.server_role as an application identity. Row-level security is the tenant-isolation boundary, while credential-management and worker-control functions remain operator-only.

SigV4 requires reversibly stored secrets, so database backups and replicas contain credential material and must be encrypted and access-controlled. pgs3 serves cleartext HTTP; production deployments need an external TLS proxy that preserves the signed path, host, and headers. Use physical backups: logical dump/restore is not supported for the extension-owned object state.

Compatibility and Limitations

The packaged and upstream-supported paths are PostgreSQL 17 and 18 with pgrx 0.19.2. Version 0.1.1 includes the tested 0.1.0 -> 0.1.1 extension upgrade edge.

pgs3 is not a general-purpose production S3 replacement. Virtual-host addressing, built-in TLS, IAM or bucket-policy languages, ACLs, lifecycle rules, and cross-database routing are not implemented. Small-object GET/PUT targets and the 100,000-object Fork target are not met, and full-object GET currently materializes the response in memory. Set a deployment-specific object-size limit and review the upstream limitations before exposing an endpoint.