Skip to content

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

Return to the regular view of this page.

Extension

Harness the synergistic power of PostgreSQL extensions

Pigsty allows you to harness the synergistic superpower of the Postgres extensions ecosystem with 3 things: Catalog, Repo, and pig.

Extension Catalog
    The complete list of <span class="text-lg font-black text-emerald-500">437</span> available PostgreSQL extensions
Software Repository
    The APT/YUM repo that deliver PostgreSQL extensions
Package Manger
    The missing package manager for PostgreSQL & Extensions
Quick Start
    How to get, install, config, manage these extensions?

There are 437 PostgreSQL extensions in the v3.7.0 catalog. PostgreSQL 18 is the default in v3.7.0.

The per-major figures below are the archive’s PG13–17 compatibility snapshot; the final PG18 breakdown was not recorded in this table. Use the v3.7.0 package aliases and release note for PG18.

Distro All PGDG PIGSTY CONTRIB OTHER MISS PG17 PG16 PG15 PG14 PG13
EL 417 119 227 71 0 6 399 407 410 394 368
Debian 410 103 236 71 0 13 397 400 403 391 363

ecosystem

TIME GIS RAG FTS OLAP FEAT LANG TYPE UTIL FUNC ADMIN STAT SEC FDW SIM ETL

MIT ISC PostgreSQL BSD-0 BSD-2 BSD-3 Artistic Apache-2.0 MPL-2.0 GPL-2.0 GPL-3.0 LGPL-2.1 LGPL-3.0 AGPL-3.0 Timescale


Usage

Package
    Download and install extensions with package alias
Download
    Download Extensions from PGDG / Pigsty Repo
Install
    Install Postgres Extension Packages
Config
    Configure extensions and setup pre-loading
Download
    Download Extensions from PGDG / Pigsty Repo
Install
    Install Postgres Extension Packages
Config
    Configure extensions and setup pre-loading
Create
    CREATE Postgres Extension in Database
Update
    Upgrade Postgres Extension
Remove
    Uninstall Postgres Extension

Index

Category Extensions
TIME emaj periods pg_background pg_cron pg_later pg_task table_version temporal_tables timescaledb timescaledb_toolkit timeseries
GIS address_standardizer address_standardizer_data_us earthdistance geoip h3 h3_postgis mobilitydb ogr_fdw pg_geohash pg_polyline pgrouting pointcloud pointcloud_postgis postgis postgis_raster postgis_sfcgal postgis_tiger_geocoder postgis_topology q3c tzf
RAG pg4ml pg_similarity pg_summarize pg_tiktoken pgml smlar vchord vector vectorize vectorscale
FTS fuzzystrmatch hunspell_cs_cz hunspell_de_de hunspell_en_us hunspell_fr hunspell_ne_np hunspell_nl_nl hunspell_nn_no hunspell_pt_pt hunspell_ru_ru hunspell_ru_ru_aot pg_bestmatch pg_bigm pg_search pg_tokenizer pg_trgm pgroonga pgroonga_database vchord_bm25 zhparser
OLAP citus citus_columnar columnar duckdb_fdw pg_analytics pg_duckdb pg_fkpart pg_mooncake pg_parquet pg_partman pg_strom plproxy tablefunc
FEAT age bloom hll hypopg imgsmlr index_advisor jsquery omni omni_auth omni_aws omni_cloudevents omni_containers omni_credentials omni_email omni_http omni_httpc omni_httpd omni_id omni_json omni_kube omni_ledger omni_manifest omni_mimetypes omni_os omni_polyfill omni_python omni_regex omni_rest omni_schema omni_seq omni_service omni_session omni_sql omni_sqlite omni_test omni_txn omni_types omni_var omni_vfs omni_vfs_types_v1 omni_web omni_worker omni_xml omni_yaml orioledb pg_cardano pg_graphql pg_hint_plan pg_incremental pg_ivm pg_jsonschema pgmq pgq plan_filter rdkit rum
LANG bool_plperl bool_plperlu dbt2 faker hstore_pllua hstore_plluau hstore_plperl hstore_plperlu hstore_plpython3u jsonb_plperl jsonb_plperlu jsonb_plpython3u ltree_plpython3u pg_tle pgtap pldbgapi pljava pllua plluau plperl plperlu plpgsql plpgsql_check plprofiler plprql plpython3u plr plsh pltcl pltclu plv8
TYPE acl asn1oid chkpass citext collection country cube currency debversion emailaddr hashtypes hstore ip4r isn l10n_table_dependent_extension ltree md5hash numeral pg_duration pg_rational pg_rrule pg_sphere pg_xenophile pgfaceting pglite_fusion pgmp pgpdf prefix roaringbitmap seg semver timestamp9 uint uint128 unit uri xml2
UTIL bzip cryptint data_historization ddl_historization envvar floatfile gzip hashlib http icu_ext pg_curl pg_extra_time pg_html5_email_address pg_net pg_protobuf pg_readme pg_readme_test_extension pg_render pg_smtp_client pgjq pgjwt pgpcre pgqr pgsql_tweaks pguecc schedoc shacrypt sparql url_encode xxhash zstd
FUNC aggs_for_arrays aggs_for_vecs arraymath autoinc base36 base62 btree_gin btree_gist convert count_distinct ddsketch dict_int dict_xsyn extra_window_functions financial first_last_agg floatvec insert_username intagg intarray lower_quantile moddatetime omnisketch permuteseq pg_base58 pg_hashids pg_idkit pg_math pg_uuidv7 pgx_ulid quantile random refint sequential_uuids tcn tdigest topn tsm_system_rows tsm_system_time unaccent uuid-ossp vasco xicor
ADMIN adminpack amcheck basebackup_to_shell basic_archive ddlx fio lo old_snapshot pg_catcheck pg_cheat_funcs pg_checksums pg_cooldown pg_crash pg_dirtyread pg_drop_events pg_orphaned pg_permissions pg_prewarm pg_readonly pg_repack pg_savior pg_squeeze pg_surgery pg_upless pgagent pgautofailover pgcozy pgdd pgfincore pgpool_adm pgpool_recovery pgpool_regclass pre_prepare prioritize safeupdate table_log
STAT auto_explain bgw_replstatus explain_ui meta pageinspect pagevis pg_buffercache pg_freespacemap pg_logicalinspect pg_overexplain pg_proctab pg_profile pg_qualstats pg_relusage pg_show_plans pg_sqlog pg_stat_kcache pg_stat_monitor pg_stat_statements pg_store_plans pg_tracing pg_track_settings pg_visibility pg_wait_sampling pg_walinspect pgmeminfo pgnodemx pgrowlocks pgsentinel pgstattuple powa sslinfo system_stats toastinfo
SEC anon auth_delay credcheck logerrors login_hook noset passwordcheck passwordcheck_cracklib pg_auditor pg_auth_mon pg_jobmon pg_session_jwt pg_snakeoil pg_tde pgaudit pgauditlogtofile pgcrypto pgcryptokey pgextwlist pgsmcrypto pgsodium sepgsql set_user sslutils supabase_vault supautils
FDW aws_s3 db2_fdw dblink file_fdw firebird_fdw hdfs_fdw jdbc_fdw kafka_fdw log_fdw mongo_fdw multicorn mysql_fdw odbc_fdw oracle_fdw pgbouncer_fdw pgspider_ext postgres_fdw redis redis_fdw sqlite_fdw tds_fdw wrappers
SIM babelfishpg_common babelfishpg_money babelfishpg_tds babelfishpg_tsql documentdb documentdb_core documentdb_distributed orafce pg_dbms_job pg_dbms_lock pg_dbms_metadata pg_statement_rollback pgmemcache pgtt session_variable spat
ETL db_migrator decoder_raw decoderbufs mimeo pg_bulkload pg_fact_loader pg_failover_slots pgactive pgl_ddl_deploy pglogical pglogical_origin pglogical_ticker pgoutput repmgr test_decoding wal2json wal2mongo

1 - Quick Start

Install, Load, create, update PostgreSQL extensions

There are unparalleled 437 extensions available in Pigsty for 14 mainstream Linux distros.


Overview

It takes 4 steps to deliver an extension: downloads, installs, config, and create:

Step 1

    [**Download**](#download-extension) : Which extension packages to download

    ```yaml tab="config" title="define which extensions to be downloaded"
    repo_extra_packages: [ postgis, timescaledb, vector ]
    ```
    ```bash tab="apply" title="download package"
    make repo
    ```

Step 2

    [Install](#install-extension) : Which extensions to be installed

    ```yaml tab="config"
    pg_extensions: [ postgis, pgvector, timescaledb ]
    ```
    ```bash tab="apply"
    ./pgsql.yml -t pg_ext     # install extensions
    ```

Step 3

    [**Load**](#load-extension) : Which extensions to be pre-loaded

    ```yaml tab="config"
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'  # add extension to preload libraries (not all extensions need this)
    ```
    ```bash tab="apply" title="edit existing cluster config and reload"
    pg edit-config --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'
    ```

Step 4

    [**Create**](#create-extension) : Create extension in the [database](/docs/pgsql/db)

    ```yaml tab="config"
    pg_databases:
    - { name: meta ,extensions: [ postgis, timescaledb, vector ] }
    ```
    ```sql tab="apply" title="create extension in existing database"
    CREATE EXTENSION postgis CASCADE;
    ```

Quick Start

You can describe extensions in the config inventory, and pigsty will download, install, configure, and enable extensions for you. This example makes postgis, pgvector, timescaledb out-of-the-box:

all:
  children:
    pg-meta:
      hosts: {10.10.10.10: { pg_seq: 1, pg_role: primary }}
      vars:
        pg_cluster: pg-meta
        pg_databases: {name: meta, extensions: [ postgis, vector ]} # create (in database)
        pg_extensions: [ postgis, pgvector ]                        # install (in cluster)
  vars:
    repo_extra_packages: [ postgis, timescaledb, vector ]           # download  (globally)

When you init this PG cluster, these extensions will be made available for you in the pg-meta cluster.

Here’s a more complicated example: launch Postgres with required extensions for self-hosting supabase:

all:
  children:
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_databases:
          - name: postgres
            baseline: supabase.sql
            schemas: [ extensions ,auth ,realtime ,storage ,graphql_public ,supabase_functions ,_analytics ,_realtime ]
            extensions:                                 # Extensions to enable in the postgres database
              - { name: pgcrypto  ,schema: extensions } # Encryption functions
              - { name: pg_net    ,schema: extensions } # Asynchronous HTTP
              - { name: pgjwt     ,schema: extensions } # JSON Web Token API for PostgreSQL
              - { name: uuid-ossp ,schema: extensions } # Generate universally unique identifiers (UUIDs)
              - { name: pgsodium        }               # Modern cryptography for PostgreSQL
              - { name: supabase_vault  }               # Supabase Vault extension
              - { name: pg_graphql      }               # GraphQL support
              - { name: pg_jsonschema   }               # JSON schema validation
              - { name: wrappers        }               # Collection of foreign data wrappers
              - { name: http            }               # Web page retrieval within the database
              - { name: pg_cron         }               # Job scheduler for PostgreSQL
              - { name: timescaledb     }               # Time-series data support
              - { name: pg_tle          }               # Trusted Language Extensions for PostgreSQL
              - { name: vector          }               # Vector similarity search
              - { name: pgmq            }               # Lightweight message queue
        # supabase required extensions for loading
        pg_libs: 'timescaledb, plpgsql, plpgsql_check, pg_cron, pg_net, pg_stat_statements, auto_explain, pg_tle, plan_filter'
        pg_parameters:
          cron.database_name: postgres
          pgsodium.enable_event_trigger: off
  vars:
    pg_version: 17
    repo_extra_packages: [pg17-core ,pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-olap ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl ]
    pg_extensions:                  [pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl ] #,pg17-olap]

All available extensions for PG 17 are downloaded and installed, and required ones are loaded & enabled.

2 - Package

Extension Packages and Alias

Mange extensions and packages are not that simple, here are two common extension examples:

Entity Example pgvector Example postgis
Extension vector postgis, postgis_topology, postgis_raster,…
Package pgvector postgis
OS PKG pgvector_18 postgresql-16-postgis-3
RPM/DEB pgvector_18_0.8.1-1PGDG.rhel8.x86_64.rpm postgresql-17-postgis-3_3.5.2+dfsg-1.pgdg22.04+1_amd64.deb

To install the right RPM / DEB with minimal effort, we need to use the abstract layer: package alias. So you can install these extensions by specifying the “Normalized” names, like pgvector or postgis. Without knowing any details about PG & OS version, Arch, Extension versions, and any other details.

Package alias pkg are used for extension download & install, but you’ll have to use the extension name ext when CREATE EXTENSION in the database (like the vector in meta database). And beware some extensions require explicit preloading, like the timescaledb in the above example.

Besides, all the extensions are categorized into 16 major categories, we also have alias for the entire extension category so that you can download and install them in batch, such as:

replace 17 with 16,15,14,13,...
repo_extra_packages: [ pg17-main ,pg17-core ,pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-olap ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl]
pg_extensions: [pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl ] #,pg17-olap]

All extensions CAN be installed simultaneously, except the olap category, where citus conflict with hydra, and pg_duckdb conflict with pg_mooncake. So you can download them all, but install one at a time.

3 - Download

Download PostgreSQL Extension

In Pigsty, downloading and installing extensions are separate steps. During INFRA module installation, Pigsty downloads all required software to the local machine and creates a local YUM/APT repo for the entire deployment.

This approach accelerates installation, eliminates redundant downloads, removes the need for database nodes to access the internet, reduces network traffic, improves delivery reliability, and ensures consistent versions across your environment - all best practices for production deployments.

For development environments, installing extensions directly from internet repo is also acceptable


Quick Start

Packages defined in repo_packages and repo_extra_packages are automatically downloaded to your local repo during Pigsty installation.

For PostgreSQL-related packages (core and extensions), typically put them in repo_extra_packages while leaving repo_packages with its os-specific global defaults.

The default value for repo_extra_packages is [pgsql-main], an alias representing core PostgreSQL and critical extensions for the current active major version.

repo_extra_packages: [ pgsql-main ]  # main packages (kernel + 3 extension) for current pg major 18

To add specific extensions, simply add Pigsty extension package name (pkg) to this parameter. Pigsty automatically downloads the appropriate packages for your active PG version and current OS distro.

repo_extra_packages: [ pgsql-main, documentdb, citus, postgis, pgvector, pg_cron, rum ]

To download all available extensions for the current PG version, add all 16 extension category aliases (as in the rich config template):

repo_extra_packages: [ pgsql-main ,pgsql-time ,pgsql-gis ,pgsql-rag ,pgsql-fts ,pgsql-olap ,pgsql-feat ,pgsql-lang ,pgsql-type ,pgsql-util ,pgsql-func ,pgsql-admin ,pgsql-stat ,pgsql-sec ,pgsql-fdw ,pgsql-sim ,pgsql-etl]

Alternatively, use version-specific aliases to download extensions for multiple PostgreSQL versions:

repo_extra_packages: [
    pg18-core,pg18-time,pg18-gis,pg18-rag,pg18-fts,pg18-olap,pg18-feat,pg18-lang,pg18-type,pg18-util,pg18-func,pg18-admin,pg18-stat,pg18-sec,pg18-fdw,pg18-sim,pg18-etl,
    pg17-core,pg17-time,pg17-gis,pg17-rag,pg17-fts,pg17-olap,pg17-feat,pg17-lang,pg17-type,pg17-util,pg17-func,pg17-admin,pg17-stat,pg17-sec,pg17-fdw,pg17-sim,pg17-etl,
    pg16-core,pg16-time,pg16-gis,pg16-rag,pg16-fts,pg16-olap,pg16-feat,pg16-lang,pg16-type,pg16-util,pg16-func,pg16-admin,pg16-stat,pg16-sec,pg16-fdw,pg16-sim,pg16-etl,
    pg15-core,pg15-time,pg15-gis,pg15-rag,pg15-fts,pg15-olap,pg15-feat,pg15-lang,pg15-type,pg15-util,pg15-func,pg15-admin,pg15-stat,pg15-sec,pg15-fdw,pg15-sim,pg15-etl,
    pg14-core,pg14-time,pg14-gis,pg14-rag,pg14-fts,pg14-olap,pg14-feat,pg14-lang,pg14-type,pg14-util,pg14-func,pg14-admin,pg14-stat,pg14-sec,pg14-fdw,pg14-sim,pg14-etl,
    pg13-core,pg13-time,pg13-gis,pg13-rag,pg13-fts,pg13-olap,pg13-feat,pg13-lang,pg13-type,pg13-util,pg13-func,pg13-admin,pg13-stat,pg13-sec,pg13-fdw,pg13-sim,pg13-etl,
]

To add new extensions to your local repo, modify the parameters above and run:

./infra.yml -t repo_build   # Re-download and rebuild local repo

To refresh the repo metadata on all other nodes in your environment, run:

./node.yml  -t node_repo    # [Optional] apt update / yum makecache

Alias Mapping

PostgreSQL has a rich open-source ecosystem with numerous packages across different systems and architectures.

Pigsty provides an abstraction layer that categorizes PostgreSQL packages into “aliases,” hiding differences between systems, architectures, and PG versions.

In the Quick Start section, we used aliases like pgsql-main and pgsql-core. These aliases are translated into specific package names based on your system and architecture. For EL systems, pgsql-main expands to postgresql$v* kernel packages with pgvector_$v*, pg_repack_$v*, and wal2json_$v* extension packages.

pgsql-main:   "postgresql$v* pg_repack_$v* wal2json_$v* pgvector_$v*"

The $v placeholder is replaced by the pg_version value (default: 18) to target the correct version. The * wildcard expands to include all package variants (e.g., server, libs, contrib, devel). Pigsty handles these details automatically.

The complete list of available packages and aliases is in roles/node_id/vars/<os_package>.yml. Here are commonly used aliases available across all supported systems:

postgresql:   "postgresql$v*"
pgsql-main:   "postgresql$v* pg_repack_$v* wal2json_$v* pgvector_$v*"
pgsql-core:   "postgresql$v postgresql$v-server postgresql$v-libs postgresql$v-contrib postgresql$v-plperl postgresql$v-plpython3 postgresql$v-pltcl postgresql$v-test postgresql$v-devel postgresql$v-llvmjit"
pgsql-simple: "postgresql$v postgresql$v-server postgresql$v-libs postgresql$v-contrib postgresql$v-plperl postgresql$v-plpython3 postgresql$v-pltcl"
pgsql-client: "postgresql$v"
pgsql-server: "postgresql$v-server postgresql$v-libs postgresql$v-contrib"
pgsql-devel:  "postgresql$v-devel"
pgsql-basic:  "pg_repack_$v* wal2json_$v* pgvector_$v*"

pgsql-time:   "timescaledb-tsl_$v* timescaledb-toolkit_$v pg_timeseries_$v periods_$v* temporal_tables_$v* e-maj_$v table_version_$v pg_cron_$v* pg_task_$v* pg_later_$v pg_background_$v*"
pgsql-gis:    "postgis35_$v* pgrouting_$v* pointcloud_$v* h3-pg_$v* q3c_$v* ogr_fdw_$v* geoip_$v pg_polyline_$v pg_geohash_$v*"
pgsql-rag:    "pgvector_$v* vchord_$v pgvectorscale_$v pg_vectorize_$v pg_similarity_$v* smlar_$v* pg_summarize_$v pg_tiktoken_$v pg4ml_$v"
pgsql-fts:    "pg_search_$v pgroonga_$v* pg_bigm_$v* zhparser_$v* pg_bestmatch_$v vchord_bm25_$v hunspell_cs_cz_$v hunspell_de_de_$v hunspell_en_us_$v hunspell_fr_$v hunspell_ne_np_$v hunspell_nl_nl_$v hunspell_nn_no_$v hunspell_ru_ru_$v hunspell_ru_ru_aot_$v"
pgsql-olap:   "citus_$v* pg_analytics_$v pg_duckdb_$v* pg_mooncake_$v* duckdb_fdw_$v* pg_parquet_$v pg_fkpart_$v pg_partman_$v* plproxy_$v*" #hydra_$v* #pg_strom_$v*
pgsql-feat:   "hll_$v* rum_$v pg_graphql_$v pg_jsonschema_$v jsquery_$v* pg_hint_plan_$v* hypopg_$v* index_advisor_$v pg_plan_filter_$v* imgsmlr_$v* pg_ivm_$v* pg_incremental_$v* pgmq_$v pgq_$v* pg_cardano_$v omnigres_$v" #apache-age_$v*
pgsql-lang:   "pg_tle_$v* plv8_$v* pllua_$v* pldebugger_$v* plpgsql_check_$v* plprofiler_$v* plsh_$v* pljava_$v*" #plprql_$v #plr_$v* #pgtap_$v* #postgresql_faker_$v* #dbt2-pgsql-extensions*
pgsql-type:   "prefix_$v* semver_$v* postgresql-unit_$v* pgpdf_$v* pglite_fusion_$v md5hash_$v* asn1oid_$v* pg_roaringbitmap_$v* pgfaceting_$v pgsphere_$v* pg_country_$v* pg_xenophile_$v pg_currency_$v* pgcollection_$v* pgmp_$v* numeral_$v* pg_rational_$v* pguint_$v* pg_uint128_$v* hashtypes_$v* ip4r_$v* pg_duration_$v* pg_uri_$v* pg_emailaddr_$v* acl_$v* timestamp9_$v* chkpass_$v*"
pgsql-util:   "pgsql_gzip_$v* pg_bzip_$v* pg_zstd_$v* pgsql_http_$v* pg_net_$v* pg_curl_$v* pgjq_$v* pgjwt_$v pg_smtp_client_$v pg_html5_email_address_$v url_encode_$v* pgsql_tweaks_$v pg_extra_time_$v pgpcre_$v icu_ext_$v* pgqr_$v* pg_protobuf_$v pg_envvar_$v* floatfile_$v* pg_readme_$v ddl_historization_$v data_historization_$v pg_schedoc_$v pg_hashlib_$v pg_xxhash_$v* postgres_shacrypt_$v* cryptint_$v* pg_ecdsa_$v* pgsparql_$v"
pgsql-func:   "pg_idkit_$v pg_uuidv7_$v* permuteseq_$v* pg_hashids_$v* sequential_uuids_$v topn_$v* quantile_$v* lower_quantile_$v* count_distinct_$v* omnisketch_$v* ddsketch_$v* vasco_$v* pgxicor_$v* tdigest_$v* first_last_agg_$v extra_window_functions_$v* floatvec_$v* aggs_for_vecs_$v* aggs_for_arrays_$v* pg_arraymath_$v* pg_math_$v* pg_random_$v* pg_base36_$v* pg_base62_$v* pg_base58_$v pg_financial_$v*"
pgsql-admin:  "pg_repack_$v* pg_squeeze_$v* pg_dirtyread_$v* pgfincore_$v* pg_cooldown_$v* ddlx_$v pg_prioritize_$v* pg_readonly_$v* pg_upless_$v pg_permissions_$v pg_catcheck_$v* preprepare_$v* pgcozy_$v pg_orphaned_$v* pg_crash_$v* pg_cheat_funcs_$v* pg_fio_$v pg_savior_$v* safeupdate_$v* pg_drop_events_$v table_log_$v" #pg_checksums_$v* #pg_auto_failover_$v* #pgagent_$v* #pgpool-II-pgsql-extensions
pgsql-stat:   "pg_profile_$v* pg_tracing_$v* pg_show_plans_$v* pg_stat_kcache_$v* pg_stat_monitor_$v* pg_qualstats_$v* pg_store_plans_$v* pg_track_settings_$v pg_wait_sampling_$v* system_stats_$v* pg_meta_$v pgnodemx_$v pg_sqlog_$v bgw_replstatus_$v* pgmeminfo_$v* toastinfo_$v* pg_explain_ui_$v pg_relusage_$v pagevis_$v powa_$v*"
pgsql-sec:    "passwordcheck_cracklib_$v* supautils_$v* pgsodium_$v* vault_$v* pg_session_jwt_$v pg_anon_$v pgsmcrypto_$v pgaudit_$v* pgauditlogtofile_$v* pg_auth_mon_$v* credcheck_$v* pgcryptokey_$v pg_jobmon_$v logerrors_$v* login_hook_$v* set_user_$v* pg_snakeoil_$v* pgextwlist_$v* pg_auditor_$v sslutils_$v* noset_$v*" #pg_tde_$v*
pgsql-fdw:    "wrappers_$v multicorn2_$v* odbc_fdw_$v* mysql_fdw_$v* tds_fdw_$v* sqlite_fdw_$v* pgbouncer_fdw_$v redis_fdw_$v* pg_redis_pubsub_$v* hdfs_fdw_$v* firebird_fdw_$v aws_s3_$v log_fdw_$v*" #jdbc_fdw_$v* #oracle_fdw_$v* #db2_fdw_$v* #mongo_fdw_$v* #kafka_fdw_$v
pgsql-sim:    "documentdb_$v* orafce_$v pgtt_$v* session_variable_$v* pg_statement_rollback_$v* pg_dbms_metadata_$v pg_dbms_lock_$v pgmemcache_$v*" #pg_dbms_job_$v #wiltondb
pgsql-etl:    "pglogical_$v* pglogical_ticker_$v* pgl_ddl_deploy_$v* pg_failover_slots_$v* db_migrator_$v wal2json_$v* postgres-decoderbufs_$v* decoder_raw_$v* mimeo_$v pg_fact_loader_$v* pg_bulkload_$v*" #wal2mongo_$v* #repmgr_$v*

When using these aliases, the $v placeholder is replaced with the PostgreSQL major version number from pg_version (default: 18).

To download packages for different PostgreSQL versions, either:

  • Change the pg_version parameter, or
  • Use version-specific aliases by replacing the pgsql- prefix with pg18-, pg17-, pg16-, etc.

Not all extensions are available on all systems. Some extensions are commented out in the aliases because they:

  • Are unavailable on specific systems
  • Have extensive dependencies (like pl/R)
  • Depend on commercial software (like oracle_fdw)
  • Are unavailable in the latest PG 18 but available in earlier versions

You can still manually add these extensions if needed.

4 - Install

Install PostgreSQL Extension

Pigsty piggyback on standard OS package managers (yum/apt) to install PostgreSQL extensions.


Quick Start

When installing extensions, Pigsty uses the same alias mapping in the download section.

Install all extensions explicitly specified in the pg_extensions parameter, for the cluster pg-meta:

all:
  children:
    pg-meta:
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars:
        pg_cluster: pg-meta
        pg_extensions: # extensions to be installed on this cluster
          - timescaledb timescaledb_toolkit pg_timeseries periods temporal_tables emaj table_version pg_cron pg_task pg_later pg_background
          - postgis pgrouting pointcloud pg_h3 q3c ogr_fdw geoip pg_polyline pg_geohash #mobilitydb
          - pgvector vchord pgvectorscale pg_vectorize pg_similarity smlar pg_summarize pg_tiktoken pg4ml #pgml
          - pg_search pgroonga pg_bigm zhparser pg_bestmatch vchord_bm25 hunspell
          - citus hydra pg_analytics pg_duckdb pg_mooncake duckdb_fdw pg_parquet pg_fkpart pg_partman plproxy #pg_strom
          - age hll rum pg_graphql pg_jsonschema jsquery pg_hint_plan hypopg index_advisor pg_plan_filter imgsmlr pg_ivm pg_incremental pgmq pgq pg_cardano omnigres #rdkit
          - pg_tle plv8 pllua plprql pldebugger plpgsql_check plprofiler plsh pljava #plr #pgtap #faker #dbt2
          - pg_prefix pg_semver pgunit pgpdf pglite_fusion md5hash asn1oid roaringbitmap pgfaceting pgsphere pg_country pg_xenophile pg_currency pg_collection pgmp numeral pg_rational pguint pg_uint128 hashtypes ip4r pg_uri pgemailaddr pg_acl timestamp9 chkpass #pg_duration #debversion #pg_rrule
          - pg_gzip pg_bzip pg_zstd pg_http pg_net pg_curl pgjq pgjwt pg_smtp_client pg_html5_email_address url_encode pgsql_tweaks pg_extra_time pgpcre icu_ext pgqr pg_protobuf envvar floatfile pg_readme ddl_historization data_historization pg_schedoc pg_hashlib pg_xxhash shacrypt cryptint pg_ecdsa pgsparql
          - pg_idkit pg_uuidv7 permuteseq pg_hashids sequential_uuids topn quantile lower_quantile count_distinct omnisketch ddsketch vasco pgxicor tdigest first_last_agg extra_window_functions floatvec aggs_for_vecs aggs_for_arrays pg_arraymath pg_math pg_random pg_base36 pg_base62 pg_base58 pg_financial
          - pg_repack pg_squeeze pg_dirtyread pgfincore pg_cooldown pg_ddlx pg_prioritize pg_checksums pg_readonly pg_upless pg_permissions pgautofailover pg_catcheck preprepare pgcozy pg_orphaned pg_crash pg_cheat_funcs pg_fio pg_savior safeupdate pg_drop_events table_log #pgagent #pgpool
          - pg_profile pg_tracing pg_show_plans pg_stat_kcache pg_stat_monitor pg_qualstats pg_store_plans pg_track_settings pg_wait_sampling system_stats pg_meta pgnodemx pg_sqlog bgw_replstatus pgmeminfo toastinfo pg_explain_ui pg_relusage pagevis powa
          - passwordcheck supautils pgsodium pg_vault pg_session_jwt pg_anon pg_tde pgsmcrypto pgaudit pgauditlogtofile pg_auth_mon credcheck pgcryptokey pg_jobmon logerrors login_hook set_user pg_snakeoil pgextwlist pg_auditor sslutils pg_noset
          - wrappers multicorn odbc_fdw jdbc_fdw mysql_fdw tds_fdw sqlite_fdw pgbouncer_fdw mongo_fdw redis_fdw pg_redis_pubsub kafka_fdw hdfs_fdw firebird_fdw aws_s3 log_fdw #oracle_fdw #db2_fdw
          - documentdb orafce pgtt session_variable pg_statement_rollback pg_dbms_metadata pg_dbms_lock pgmemcache #pg_dbms_job #wiltondb
          - pglogical pglogical_ticker pgl_ddl_deploy pg_failover_slots db_migrator wal2json wal2mongo decoderbufs decoder_raw mimeo pg_fact_loader pg_bulkload #repmgr

Or install all extensions by category aliases globally:

all:
  vars:
    pg_version: 18   # default in v3.7, so pgsql-main is equivalent to pg18-main
    pg_extensions: [ pgsql-main ,pgsql-time ,pgsql-gis ,pgsql-rag ,pgsql-fts ,pgsql-olap ,pgsql-feat ,pgsql-lang ,pgsql-type ,pgsql-util ,pgsql-func ,pgsql-admin ,pgsql-stat ,pgsql-sec ,pgsql-fdw ,pgsql-sim ,pgsql-etl]

You can also specify the PG major version explicitly in these alias:

all:
  vars:

    pg_extensions: [pg17-time ,pg17-gis ,pg17-rag ,pg17-fts ,pg17-feat ,pg17-lang ,pg17-type ,pg17-util ,pg17-func ,pg17-admin ,pg17-stat ,pg17-sec ,pg17-fdw ,pg17-sim ,pg17-etl ] #,pg17-olap]

Install all extensions simultaneously is applicable (except two conflicts in the olap category) but not recommended. Just install the extensions you need by explicitly specifying them in the pg_extensions parameter.


Configure

During PGSQL cluster init, Pigsty will automatically install packages (& alias) specified in pg_packages and pg_extensions.

Both parameters can be used to install PostgreSQL-related packages. Typically, pg_packages is used to globally specify packages that should be installed across all PostgreSQL clusters in your environment: such as the PostgreSQL kernel, high-availability agent like Patroni, connection pooling with pgBouncer, monitoring with pgExporter, etc.

By default, Pigsty also specifies 3 important extensions here: pgvector, pg_repack, and wal2json for vector search, bloat management, and CDC change extraction.

Meanwhile, pg_extensions is usually used to specify extension for a specific cluster. The default is an empty list, indicating no other extensions will be installed by default.

pg_packages:                      # pg packages to be installed, alias can be used, state=present
  - postgresql
  - wal2json pg_repack pgvector
  - patroni pgbouncer pgbackrest pg_exporter pgbadger vip-manager
pg_extensions: []                 # pg extensions to be installed, alias can be used, state=latest

An important distinction: packages installed via pg_packages are merely ensured to be present, whereas those installed via pg_extensions are automatically upgraded to the latest available version.

When using a local software repo, this distinction isn’t an issue. However, when using upstream internet repo, consider this carefully and move extensions you don’t want automatically upgraded to pg_packages.


Install

Extensions pre-defined in the pg_extensions (and pg_packages) will be installed during cluster provisioning.

To install new extensions on a provisioned PostgreSQL cluster:

First, add extensions to pg_extensions, then execute the playbook subtask:

./pgsql.yml -t pg_extension  # install extensions specified in pg_extensions

Note that extension plugins specified in the pg_extension task will be upgraded to the latest available version in your current environment by default.


Repo

To install extension, you need to ensure one of the following conditions is met:

  • Local Repo: You have configured using Pigsty’s local repo, and the extensions have already been downloaded to the local repo.
  • Online Repo: You have directly configured upstream internet repo on the target node, and internet access is available on these nodes.

For production environments, we recommend using Pigsty’s local software repo to manage and install extensions uniformly: First download extensions to the local repo, then install them from there. This ensures consistent extension versions across your environment and prevents database nodes from directly accessing the internet. You have to do nothing when installed from local repo, just make sure they are downloaded to the local repo.

For development environments, you may choose to directly use upstream internet repo for convenience. Use the following commands to add Internet repo and install extensions on the target cluster directly:

./node.yml  -l <cls> -t node_repo -e node_repo_modules=local,node,pgsql    # Enable internet repo on target node
./pgsql.yml -l <cls> -t pg_extension                                        # Install extensions using local+internet upstream repos

Package Alias

When installing extensions, users can use extension aliases to specify extension.

The aliases will be translated to the current active PG major version and OS environment.

and translated to the corresponding RPM/DEB package names by alias translation mechanism.


Caveats

  • There are two known conflicts:
  • pgaudit got a different naming pattern on el for pg 15-: pg16+ = pgaudit, pg15=pgaudit17, pg14=pgaudit16 pg13=pgaudit15 pg12=pgaudit14
  • postgis got its own version in el package name: postgis35 by default, and postgis33 for legacy el7

5 - Config

Preload extensions and configure extension parameters

While most PostgreSQL extensions written in SQL can be directly enabled with CREATE EXTENSION, some extensions that use special postgres hook will require an extra step to preload them before using.


Preloading

Most extensions have one or more corresponding dynamic library (.so, .dylib, .dll), some of them require preloading before using. Attempting to CREATE these extensions without proper preloading will result in an error. And a wrongly configured preload library may lead to a failure on database restart/start.

Some extensions can partially work without preloading, which means part of the extension features are available directly, and the rest of the features are available after preloading.

To preload an extension, add it to the shared_preload_libraries and restart the database server. The Extension Catalog gives the complete list of extensions that require dynamic preloading.


Configure

To configure a preload on new postgres cluster, the pg_libs parameter can be used. It will be populated to the shared_preload_libraries parameter during postgres cluster bootstrap.

Example: Setup Supabase Extension Preloading

This example show how to specify pre-loaded extensions with pg_libs parameter.

all:
  children:
pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, plpgsql, plpgsql_check, pg_cron, pg_net, pg_stat_statements, auto_explain, pg_tle, plan_filter'

shared_preload_libraries is a comma-separated list of extensions.

Beware that only works before cluster creation. After that, you’ll have to config cluster to change the shared_preload_libraries parameter on existing cluster. (with patronictl, ALTER SYSTEM, etc…)

add timescaledb to shared_preload_libraries
pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'
pg restart pg-meta    # restart to apply changes

If you want to configure preloading manually, you can just change the postgresql.conf by yourself


Default

The default value of pg_libs is pg_stat_statements, auto_explain, which preload these two Contrib extensions by default, these two extensions provide essential observability:

  • auto_explain: Automatic logging of slow query execution plans
  • pg_stat_statements: Tracks planning and execution statistics for grouped SQL statements

Caveats

Preload libraries are loaded one by one, so the order of extensions in shared_preload_libraries matters, Here are some known rules to follow:

  • For STAT extension, add them AFTER pg_stat_statements to ensure using the same query_id.
  • timescaledb and citus should be placed at the BEGINNING of shared_preload_libraries
  • If you use citus and timescaledb together, place citus before timescaledb.
  • Use pg_documentdb and pg_documentdb_core as library name for documentdb.
  • pg_search does not require preloading in PostgreSQL 17 and later, but earlier versions do.

Parameter

Some extensions have configurable parameters, you can manage them in different places.

Consult the official docs of each extension for details.

6 - Create

Create & Enable PostgreSQL Extension

Quick Start

You can enable (create) extension using the CREATE EXTENSION statement:

CREATE EXTENSION vector; -- no explicit loading required
CREATE EXTENSION timescaledb; -- explicit loading required

Extensions need to be installed first, some extension also requires preloading before using.

Some extensions have dependencies on other extensions. In such cases, you can either install the dependencies first or use the CASCADE clause to install all dependencies at once.

CREATE EXTENSION documentdb CASCADE; -- create documentdb extension and all its dependencies

You can also provision extension with Pigsty, which will automatically create the extensions for you.


Configure

Extensions (database logical objects) are logically part of PostgreSQL databases. In Pigsty, you can specify which extensions to be created in a database with pg_databases parameter.

pg_databases:
  - { name: meta ,extensions: [ vector, postgis, timescaledb ] }

But you can explicitly specify extension details with the object format, like create them in a specific schema. Or install a specific version. Here’s a complete example (self-hosting supabase):

pg_databases:
  - name: postgres
    baseline: supabase.sql
    schemas: [ extensions ,auth ,realtime ,storage ,graphql_public ,supabase_functions ,_analytics ,_realtime ]
    extensions:                                 # Extensions to be enabled in the postgres database
      - { name: pgcrypto  ,schema: extensions } # cryptographic functions
      - { name: pg_net    ,schema: extensions } # async HTTP
      - { name: pgjwt     ,schema: extensions } # json web token API for postgres
      - { name: uuid-ossp ,schema: extensions } # generate universally unique identifiers (UUIDs)
      - { name: pgsodium        }               # pgsodium is a modern cryptography library for Postgres.
      - { name: supabase_vault  }               # Supabase Vault Extension
      - { name: pg_graphql      }               # pg_graphql: GraphQL support
      - { name: pg_jsonschema   }               # pg_jsonschema: Validate json schema
      - { name: wrappers        }               # wrappers: FDW collections
      - { name: http            }               # http: allows web page retrieval inside the database.
      - { name: pg_cron         }               # pg_cron: Job scheduler for PostgreSQL
      - { name: timescaledb     }               # timescaledb: Enables scalable inserts and complex queries for time-series data
      - { name: pg_tle          }               # pg_tle: Trusted Language Extensions for PostgreSQL
      - { name: vector          }               # pgvector: the vector similarity search
      - { name: pgmq            }               # pgmq: A lightweight message queue like AWS SQS and RSMQ

Define Extension

The extensions field is a list of extension (name or object) to be created in the database. It will be created under the first schema in dbsu’s search_path, (usually the public schema).

Here, the extensions in the database object is a list where each element can be:

  • A simple string representing the extension name, such as vector
  • Alternatively, A dictionary that may contain the following fields can be used:
    • name: Extension name, REQUIRED, beware it may differ from the extension package name.
    • schema: Schema for installing the extension, OPTIONAL, defaults to the first schema in the current dbsu search path, usually the default public.
    • version: Specifies the extension version, OPTIONAL, defaults to the latest version, rarely used.

If the database doesn’t exist yet, the extensions defined here will be automatically created when creating a cluster or creating a database through Pigsty.

Re-creating database with non-trivial baseline schema may be dangerous (if you put some DROP there) So for existing clusters / databases, it’s advised to use your own schema migration tool to manage extensions. (pgadmin, psql, bytebase, flyway, sqlitch,…) But it’s helpful to enlist them in the config inventory for bookkeeping purposes. (So if you want to fork this cluster, it includes these extensions)


Default Extension

Some built-in extensions and one special pg_repack are created by default in Pigsty.

These extensions are defined by pg_default_extensions, created in the template1 database and the postgres database by default. Newly created databases will inherit these extensions from template1, so you don’t need to create them again.

pg_default_extensions:
  - { name: pg_stat_statements ,schema: monitor }
  - { name: pgstattuple        ,schema: monitor }
  - { name: pg_buffercache     ,schema: monitor }
  - { name: pageinspect        ,schema: monitor }
  - { name: pg_prewarm         ,schema: monitor }
  - { name: pg_visibility      ,schema: monitor }
  - { name: pg_freespacemap    ,schema: monitor }
  - { name: postgres_fdw       ,schema: public  }
  - { name: file_fdw           ,schema: public  }
  - { name: btree_gist         ,schema: public  }
  - { name: btree_gin          ,schema: public  }
  - { name: pg_trgm            ,schema: public  }
  - { name: intagg             ,schema: public  }
  - { name: intarray           ,schema: public  }
  - { name: pg_repack } # <-- The only 3rd-party extension created by default

One extra default schema monitor is defined by pg_default_schemas is also created by default. Which is used to contain monitoring related extensions, tables, functions and views.

There are three 3rd-party extensions that are available by default in Pigsty:

Extension What Where
pg_repack Online Bloat Control Tools in the pg_default_extensions
wal2json Changing data capture in JSON extension without DDL, install means available
vector vector data type & indexes in pg_databases as an example

The pg_repack extension is an important utility for maintaining bloat tables online.

vector is a very popular extension for RAG, It is installed by default (in the pgsql-main alias) and created in the placeholder meta database in most config template.

The wal2json is another important extension for Changing Data Capture (CDC). It is installed by default, but it is an extension without DDL, So you don’t need to CREATE it explicitly.


Extension without DDL

Extension without DDL does not require the CREATE EXTENSION command to work

PostgreSQL extensions typically consist of three parts: a required control file, optional SQL files, and optional libraries. If an extension does not have SQL file, CREATE EXTENSION command is not needed.

Component Description Required
Control file Key metadata, name, dependencies, schema, version,… REQUIRED
SQL file SQL DDL statements, Types, Functions, etc… OPTIONAL
Library file binary shared libraries (.so, .dylib, .dll) OPTIONAL

Since SQL / LIB files are optional, there are four possible combinations of extension types:

LOAD / DDL Requires CREATE EXTENSION Doesn’t require CREATE EXTENSION
Requires LOAD Extensions using hooks Headless extensions
Doesn’t Require LOAD Extensions not using hooks Logical decoding output plugins

7 - Update

How to update PostgreSQL extensions to newer versions

To update an existing extension, you need to first update the RPM/DEB package with your OS’s package manager, then alter the extension to the new version in PostgreSQL with ALTER EXTENSION ... UPDATE.

You can upgrade extension packages with the following commands

pig ext update extname...
yum upgrade extname...
apt upgrade extname...
./pgsql.yml -t pg_ext   # -l cls

All extensions listed in pg_extensions will be upgraded using during the pgsql.yml playbook execution.


Upgrade Packages

Extensions (Package Alias) listed in pg_extensions will be upgraded with pgsql.yml’s pg_ext subtask:

~/pigsty
./pgsql.yml -t pg_ext

This playbook will automatically install the latest available version of extension RPM/DEB packages in your current environment. (from built local repo or via Internet directly). You can also upgrade extensions with linux system’s yum/apt upgrade command directly, but you need to specify the full package names:

yum upgrade extname...
apt upgrade extname...

Pigsty’s pig cli can also help you with that, without the burden of specifying full package names:

pig ext update extname|pkgalias

Alter Extension

Execute the ALTER EXTENSION ... UPDATE SQL command to update the extension to the new version:

ALTER EXTENSION name UPDATE [ TO new_version ]

If the TO new_version clause is omitted, the extension will be updated to the latest version available.

8 - Remove

How to remove PostgreSQL extensions

Remove Extension

To uninstall an extension, you typically need to run the DROP EXTENSION SQL statement:

DROP EXTENSION "<extname>";

If other extensions or database objects depend on this extension, you’ll need to remove those dependencies first before uninstalling the extension. Or remove all of them with CASCADE option:

DROP EXTENSION "<extname>" CASCADE;
Warning

The CASCADE option will delete all objects that depend on this extension,
including database objects, functions, views, etc. Use with caution!

Some extensions don’t have DDL, these extensions do not require the DROP EXTENSION statement to uninstall. Instead, you can simply remove the extension from the shared_preload_libraries (if configured) and uninstall the package. Refer to the Extensions Without DDL section for more details.


Remove Loading

If you’re using an extension that requires dynamic loading (which modifies the shared_preload_libraries parameter), you need to first re-confnigure the shared_preload_libraries parameter.

Remove the extension name from shared_preload_libraries and restart the database cluster for the changes to take effect.

For extensions that need dynamic loading, refer to the Extensions that Need Loading list.


Uninstall Package

After removing the extension (logical object) from all databases in the cluster, you can safely uninstall the extension’s software package. Ansible commands can help you do this conveniently:

ansible <cls> -m package -a "name=<extname> state=absent"

You can also use pig, or apt/yum commands directly to uninstall.

If you don’t know the extension package name, you can refer to the Extension List or check the extension package name mapping defined in roles/node_id/vars.