Skip to content

This is the multi-page printable view of this section. .

Return to the regular view of this page.

Extensions

PostgreSQL Extensions guide for pgcli

pgcli supports installing and managing PostgreSQL extensions from the Pigsty DEB repository.

How It Works

Extensions are baked into a derived container image:

  1. pg extension install builds a new image (based on the current image + Pigsty repo + extension packages)
  2. Stops and removes the old container
  3. Recreates the container from the new image (host data volumes are preserved)
  4. Updates image_tag in the config file

Benefits of this approach:

  • Extensions survive container rebuilds (baked into the image layer)
  • pg start does not need to run apt-get install on every boot
  • Extension files are persistent and decoupled from the container lifecycle

Commands

Install Extensions

# Install a single extension
pg extension install pg_stat_statements

# Install multiple extensions (single image build, comma-separated)
pg extension install pgmq,uuid-ossp,pg_stat_statements

# Target a specific instance
pg extension install pg_stat_statements -i pg01

Restart confirmation: Extensions requiring shared_preload_libraries (e.g., pg_stat_statements, pg_cron) need a PostgreSQL restart. By default, you will be prompted for confirmation:

# Interactive confirmation (default)
pg extension install pg_stat_statements
# Output:
# Installing extensions that require shared_preload_libraries will cause a PostgreSQL restart.
# Extensions to be installed: [pg_stat_statements]
# This will cause a brief interruption to database connections.
# Restart PostgreSQL now? [y/N]:

# Skip confirmation and restart automatically
pg extension install pg_stat_statements --auto-restart

If you decline the restart, you can apply the changes later:

pg stop -i pg01
pg start -i pg01

List Installed Extensions

pg extension list -i pg01

Example output:

Installed extensions in "pg01":
  pg_stat_statements (managed)
  uuid-ossp (managed)
  plpgsql (unmanaged)
  • managed: tracked by pgcli (recorded in config, included in image)
  • unmanaged: manually installed extensions (not tracked in config)

Remove Extensions

pg extension remove pgmq -i pg01

Workflow:

  1. DROP EXTENSION IF EXISTS pgmq
  2. Update config and shared_preload_libraries
  3. No image rebuild — the -ext image is shared across instances and packages are never uninstalled

Restart confirmation: If removing extensions that require shared_preload_libraries (e.g., pg_stat_statements, pg_cron), you will be prompted for confirmation before restarting:

# Interactive confirmation (default)
pg extension remove pg_stat_statements -i pg01
# Output:
# Removing extensions that require shared_preload_libraries will cause a PostgreSQL restart.
# Extensions to be removed: [pg_stat_statements]
# This will cause a brief interruption to database connections.
# Restart PostgreSQL now? [y/N]:

# Skip confirmation and restart automatically
pg extension remove pg_stat_statements -i pg01 --auto-restart

If you decline the restart, you can apply the changes later:

pg stop -i pg01
pg start -i pg01

View Available Extensions

pg extension available

Lists all 440 known extensions:

  • 45 builtin (contrib, already in the base image — no image build needed)
  • 395 Pigsty catalog (from Pigsty DEB repo, requires image build)

Extension Catalog

See Extension Catalog for the complete list of 45 built-in extensions (no install needed).

See Popular Extensions for usage examples of the most commonly used extensions.

Extensions Outside the Catalog

Only extensions in the catalog (builtin + Pigsty) can be installed via pg extension install. Unknown extension names are rejected before the build starts:

  [X] Unknown extension(s): [nonexistent_ext]

      These extensions are not in the Pigsty catalog or builtin contrib list.
      Check available extensions: pg extension available
      Full Pigsty catalog: https://pigsty.cc/ext/list/

Full catalog: https://pigsty.cc/ext/list/

Configuration

After installing extensions, the config is updated:

instances:
  pg01:
    extensions:
      - pg_stat_statements
      - uuid-ossp
      - pgmq
    podman:
      image_tag: ghcr.io/mars-base/pgcli/pgcli-pg:18-2.58.0-ext

The image_tag points to the derived image containing all installed extensions.

Shared Preload Libraries

Extensions requiring shared_preload_libraries are automatically configured in postgresql.conf:

# === pgcli extensions (managed — do not edit) ===
shared_preload_libraries = 'pg_stat_statements,pg_cron'
# === end pgcli extensions ===

Extensions that must be loaded first (e.g., citus, timescaledb) are automatically placed at position 0 regardless of install order — PostgreSQL fatals if they appear anywhere else.

This is a postmaster-level parameter; PostgreSQL must be restarted after changes.

Troubleshooting

Extension Install Failure

  [X] Unknown extension(s): [nonexistent_ext]

Cause: Extension name is not in the builtin contrib list or Pigsty catalog.

Resolution:

  • Verify the extension name: pg extension available
  • Check the Pigsty catalog: https://pigsty.cc/ext/list/
  • Note the exact SQL extension name (e.g., vector not pgvector)

CREATE EXTENSION Failure

ERROR: extension "pgmq" already exists

The extension is installed but not tracked in config. You can safely ignore this, or manually add it to the config:

extensions:
  - pgmq

Shared Preload Library Conflict

If shared_preload_libraries was manually edited in postgresql.conf, pgcli’s sentinel block will overwrite it.

Resolution: Remove the manual configuration and let pgcli manage it.

Notes

  • Extension count: 45 builtin (contrib) + 395 Pigsty catalog = 440 total known extensions
  • Image size: Each extension adds 10-50MB to the image, but Pigsty packages are optimized
  • Build time: First extension install takes 1-3 minutes (download + build); subsequent installs are faster (cache hits)
  • Replica behavior: Replicas can install extensions, but CREATE EXTENSION will be rejected (read-only). Install on the primary; replicas sync via physical replication
  • Extension upgrades: ALTER EXTENSION ... UPDATE TO ... is not yet supported; run manually via pg exec

1 - Extension Catalog

Built-in PostgreSQL extensions available in the base image

This page lists all built-in extensions available in the base image. For usage examples, see Popular Extensions.

Built-in Extensions (45)

These extensions ship in the PostgreSQL base image — no image build or pg extension install needed. Just run CREATE EXTENSION to enable them.

Requires shared_preload_libraries

These extensions need a PostgreSQL restart after enabling. pgcli handles this automatically when installed via pg extension install.

Extension Description
pg_stat_statements SQL performance analysis — tracks query execution counts, timing, and resource usage
pg_cron Cron-based job scheduler inside the database
pg_hint_plan Query hints to influence the planner
pg_stat_monitor Advanced performance monitoring with query plans
pg_qualstats Query predicate statistics for index recommendations
pg_stat_kcache Kernel-level CPU/IO performance stats
pg_wait_sampling Wait event sampling for performance analysis
pg_track_settings Track configuration changes over time
timescaledb Time-series database extension with hypertables
pg_prewarm Preload table data into shared buffers after restart

No restart needed

These extensions can be enabled instantly with CREATE EXTENSION — no restart required.

Extension Description
uuid-ossp UUID generation functions (v1/v3/v4/v5)
hstore Key-value pair storage in a single column
pgcrypto Hashing (bcrypt/sha256), encryption/decryption, random generation
pg_trgm Trigram similarity matching for fuzzy search
unaccent Strip accents from characters for international text search
fuzzystrmatch Fuzzy string matching (Levenshtein, Soundex, Metaphone)
intarray Integer array operations (unique, sort, intersection)
isn ISBN/ISSN/EAN standard number types with validation
pg_repack Online table reorganization without exclusive locks
pg_squeeze Table space reclamation
pg_partman Automatic partition management
pgvector (Pigsty) Vector similarity search for AI applications
postgis (Pigsty) Geospatial data support
pgmq (Pigsty) Lightweight message queue
tablefunc Crosstab / pivot table functions
btree_gist B-tree index support for GiST indexes
btree_gin B-tree index support for GIN indexes
citext Case-insensitive text type
cube Multi-dimensional cube data type
ltree Hierarchical label tree data type
seg Floating-point interval data type
earthdistance Great-circle distance calculations on Earth’s surface
postgres_fdw Query external PostgreSQL servers as local tables
file_fdw Read server files as foreign tables
dblink Connect to other PostgreSQL databases
amcheck Verify B-tree index integrity
pageinspect Low-level page inspection for debugging
pg_buffercache View shared buffer cache contents
pg_freespacemap View free space map for tables
pg_visibility View visibility map for tables
pg_walinspect Inspect WAL records
pgstattuple Table-level tuple statistics
pgrowlocks Show row-level locking information
pg_surgery Low-level heap tuple manipulation
xml2 XML parsing and XPath functions
dict_int Integer text search dictionary
dict_xsyn Extended synonym text search dictionary
bloom Bloom filter index access method
autoinc Auto-increment trigger function
insert_username Insert username trigger function
moddatetime Auto-update timestamp trigger
refint Referential integrity trigger functions
tcn Triggered change notification
sslinfo SSL connection information functions
lo Large object type support
intagg Integer array aggregate/enumeration
tsm_system_rows Table sampling by row count
tsm_system_time Table sampling by time
pg_logicalinspect Logical replication slot inspection

2 - Popular Extensions

Usage examples for the most commonly used PostgreSQL extensions

Usage examples for the most commonly used PostgreSQL extensions, tested on PG 18 with pgcli.

Performance & Monitoring

Extension Install Description
pg_stat_statements pg extension install pg_stat_statements SQL performance analysis. Must-have for production.
pg_repack pg extension install pg_repack Online table reorganization. Reclaims bloat.
pg_prewarm pg extension install pg_prewarm Preload table data after restart.
# Install all at once
pg extension install pg_stat_statements,pg_repack,pg_prewarm --auto-restart

# Find top 5 slow queries
pg exec "SELECT query, calls, total_exec_time::numeric(10,2) AS ms
         FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 5;"

# Repack a bloated table
pg exec -- pg_repack -U admin -d default_db -t my_table --no-superuser-check

# Prewarm a table
pg exec "SELECT pg_prewarm('my_table');"

Data Types & Identifiers

Extension Install Description
uuid-ossp builtin UUID generation (v1/v3/v5). PG 18 has built-in gen_random_uuid() (v4) and uuidv7() (v7) — no extension needed.
hstore builtin Key-value pair storage.
citext builtin Case-insensitive text. Foo = foo.
# UUID generation (PG 18 built-in — no extension needed)
pg exec "SELECT gen_random_uuid();"  # v4 random UUID (built-in since PG 13)
pg exec "SELECT uuidv7();"           # v7 time-ordered UUID (new in PG 18)

# uuid-ossp extension — only needed for v1/v3/v5 UUIDs
pg exec "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
pg exec "SELECT uuid_generate_v1();"  # v1 timestamp + MAC address
pg exec "SELECT uuid_generate_v3(uuid_ns_url(), 'https://example.com');"  # v3 MD5-based
pg exec "SELECT uuid_generate_v5(uuid_ns_url(), 'https://example.com');"  # v5 SHA-1 based

# Key-value storage
pg exec "SELECT 'theme => dark, lang => en'::hstore -> 'theme';"
# Returns: dark

# Case-insensitive matching
pg exec "CREATE TABLE users (email citext);
         INSERT INTO users VALUES ('Alice@Example.COM');
         SELECT * FROM users WHERE email = 'alice@example.com';"

Search & Text

Extension Install Description
pg_trgm builtin Trigram similarity for fuzzy search and autocomplete.
unaccent builtin Strip accents for flexible international text search.
# Fuzzy search
pg exec "SELECT name, similarity(name, 'John') FROM users
         ORDER BY similarity(name, 'John') DESC LIMIT 5;"

# Create a trigram index for fast fuzzy search
pg exec "CREATE INDEX users_name_trgm_idx ON users USING gin (name gin_trgm_ops);"

# Remove accents
pg exec "SELECT unaccent('Crème Brûlée');"  -- returns 'Creme Brulee'

# Combine for accent-insensitive fuzzy search
pg exec "SELECT name FROM users WHERE name % unaccent('Creme Brulee');"

Security & Encryption

Extension Install Description
pgcrypto builtin Hashing, encryption/decryption, random generation.
pgaudit pg extension install pgaudit Audit logging. Required for compliance (GDPR, HIPAA, SOX).
# Hash a password with bcrypt
pg exec "SELECT crypt('my_password', gen_salt('bf'));"

# Verify a password
pg exec "SELECT (crypt('my_password', stored_hash) = stored_hash);"

# Symmetric encryption/decryption
pg exec "SELECT pgp_sym_decrypt(pgp_sym_encrypt('secret', 'key'), 'key');"

# Enable audit logging for specific operations
pg exec "SET pgaudit.log = 'read, ddl';"

Geospatial

Extension Install Description
postgis pg extension install postgis Full spatial database: geometry, spatial indexes, distance/area.
pg extension install postgis --auto-restart

# Create a table with spatial data
pg exec "CREATE TABLE places (id serial, name text, geom geometry(Point, 4326));"
pg exec "INSERT INTO places (name, geom) VALUES
         ('San Francisco', ST_MakePoint(-122.4, 37.8)),
         ('London', ST_MakePoint(-0.1276, 51.5074));"

# Find places within 5km of a point
pg exec "SELECT name FROM places
         WHERE ST_DWithin(geom, ST_MakePoint(-122.4, 37.8)::geography, 5000);"

# Calculate distance between two cities (in meters)
pg exec "SELECT ST_Distance(
           ST_MakePoint(-74.006, 40.7128)::geography,
           ST_MakePoint(-0.1276, 51.5074)::geography);"
Extension Install Description
pgvector pg extension install vector Store and search embedding vectors. Standard for AI apps.
pg extension install vector --auto-restart

# Create a table with vector column
pg exec "CREATE TABLE items (id serial PRIMARY KEY, embedding vector(3));"
pg exec "INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]'), ('[7,8,9]');"

# Find nearest neighbors (Euclidean distance)
pg exec "SELECT id FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;"

# Create an IVFFlat index for fast approximate search
pg exec "CREATE INDEX items_embedding_idx ON items USING ivfflat (embedding vector_l2_ops);"

Time Series

Extension Install Description
timescaledb pg extension install timescaledb Optimized time-series storage with hypertables.
pg extension install timescaledb --auto-restart

# Create a hypertable
pg exec "CREATE TABLE sensor (time timestamptz NOT NULL, value float);
         SELECT create_hypertable('sensor', 'time');"

# Time-bucket aggregation
pg exec "SELECT time_bucket('1 hour', time) AS bucket, avg(value)
         FROM sensor GROUP BY bucket ORDER BY bucket;"

Scheduling & Distributed

Extension Install Description
pg_cron pg extension install pg_cron Cron-based job scheduler. Auto-configured by pgcli.
citus pg extension install citus Distributed PostgreSQL with sharding.
pg extension install pg_cron --auto-restart

# Schedule a daily cleanup job (runs at midnight)
pg exec "SELECT cron.schedule('cleanup', '0 0 * * *',
         'DELETE FROM logs WHERE created_at < now() - interval ''30 days''');"

# List scheduled jobs
pg exec "SELECT jobid, schedule, command FROM cron.job;"

# Unschedule a job
pg exec "SELECT cron.unschedule('cleanup');"

Foreign Data

Extension Install Description
postgres_fdw builtin Query external PostgreSQL servers as local tables.
pg_duckdb pg extension install pg_duckdb Embedded DuckDB analytics engine. Read Parquet/CSV, offload OLAP queries.
# Create a foreign server
pg exec "CREATE SERVER remote FOREIGN DATA WRAPPER postgres_fdw
         OPTIONS (host '10.0.0.2', port '5432', dbname 'analytics');"

# Create user mapping
pg exec "CREATE USER MAPPING FOR current_user SERVER remote
         OPTIONS (user 'reader', password 'secret');"

# Import remote schema as foreign tables
pg exec "IMPORT FOREIGN SCHEMA public FROM SERVER remote INTO remote_schema;"

# Query remote data as if it were local
pg exec "SELECT * FROM remote_schema.events LIMIT 10;"
pg extension install pg_duckdb --auto-restart

# Run SQL in DuckDB — duckdb.query is a table function (FROM clause required)
pg exec "SELECT * FROM duckdb.query(\$\$ SELECT 42 AS answer, 'hello' AS msg \$\$);"

# Export a table to Parquet
pg exec "COPY my_table TO '/tmp/my_table.parquet' (FORMAT 'parquet');"

# Read Parquet/CSV files directly
pg exec "SELECT * FROM duckdb.query(\$\$
         SELECT * FROM read_parquet('/tmp/my_table.parquet') WHERE id > 2 \$\$);"

# Offload an entire query to DuckDB (OLAP acceleration)
pg exec "SET duckdb.force_execution = true;
         SELECT category, sum(amount) FROM sales GROUP BY category;"

# Pure DuckDB SQL (no PostgreSQL planner involved)
pg exec "SELECT * FROM duckdb.raw_query(\$\$ SELECT range AS n FROM range(1, 6) \$\$);"

# --- Read files from S3 / MinIO (no file copy needed) ---

# Create an S3 secret once (use_ssl is text: 'true'/'false')
pg exec "SELECT duckdb.create_simple_secret('S3', '<access_key>', '<secret_key>',
         '', 'us-east-1', 'path', '', 'minio.example.com:9000',
         's3://bucket', '', 'false');"

# Query a CSV in the bucket directly
pg exec "SELECT * FROM duckdb.query(\$\$
         SELECT category, count(*) AS cnt, sum(sales) AS total_sales
         FROM read_csv('s3://bucket/products.csv', auto_detect=true)
         GROUP BY category ORDER BY total_sales DESC \$\$);"

Compatibility Notes

Extension PG 18 Status Notes
pgml Not available Only supports PG 14-17 (no PG 18 package)
uuid-ossp Partially needed PG 18 built-in: gen_random_uuid() (v4), uuidv7() (v7). Extension only needed for v1/v3/v5