Inspect PostgreSQL 18.6 extension packages before installation, distinguish trusted from superuser-only code, verify schema/version/dependencies, and practice a secure hstore install/update review.

Extension Packaging, CREATE EXTENSION, Versioning, Dependencies, and Trust Boundaries

Inspect PostgreSQL 18.6 extension packages before installation, distinguish trusted from superuser-only code, verify schema/version/dependencies, and practice a secure hstore install/update review.

Intermediate → Advanced180–240 minutesPostgreSQL extensibility and federationPostgreSQL 18.6 baselineCore + PostgreSQL supplied extensions only in mandatory labsServiceHub disposable objects: ch19_*Admin/superuser required where postgres_fdw or untrusted-code boundaries are demonstratedFree local tooling; no managed service requiredLast reviewed: August 2026

Learning outcomes

ServiceHub wants fuzzy matching, key/value utilities, cross-database access, and possibly third-party observability features. PostgreSQL deliberately supports such extensibility, but CREATE EXTENSION is not an app-store install button. An extension is a database-level package whose control and SQL files—and sometimes a native shared library—must already be installed on the server. Installing one can execute privileged database code, so package provenance and trust boundaries are part of database security.

01

Distinguish an extension control file, install/update SQL scripts, and optional shared libraries.

02

Compare extension files available on the server with extensions installed in the current database.

03

Interpret trusted, superuser, relocatable, schema, requires, and version metadata.

04

Install a supplied trusted extension into a secure schema and verify its ownership/version.

05

Review update paths and avoid assuming IF NOT EXISTS or ALTER EXTENSION UPDATE proves compatibility.

Mental model

The operating system/package manager puts extension files on the PostgreSQL server. CREATE EXTENSION registers and executes those files inside one database and records the resulting member objects in pg_extension. Those are two separate installation layers.

1. Available on the server is not installed in this database

sql · extension inventory preflight
SELECT current_setting('server_version') AS server_version;SELECT name, default_version, installed_version, commentFROM pg_available_extensionsWHERE name IN ('hstore','postgres_fdw','pg_trgm','plpgsql')ORDER BY name;SELECT e.extname, e.extversion,       n.nspname AS schema_name,       pg_get_userbyid(e.extowner) AS extension_owner,       e.extrelocatableFROM pg_extension AS eJOIN pg_namespace AS n ON n.oid = e.extnamespaceORDER BY e.extname;

pg_available_extensions reflects control files the running server can discover. pg_extension shows what this specific database has registered. If a module such as hstore is absent from the available view, install the PostgreSQL 18 matching supplied/contrib package first; do not download an arbitrary binary built for another major version.

2. Connect catalog availability to the server installation

The available-extension views are database-facing evidence that the running server discovered control files. When package provenance matters, also record the PostgreSQL installation paths and package-manager identity for the same server build. PostgreSQL 18 can search its configured extension_control_path; pg_config reports paths associated with a PostgreSQL installation when that utility is installed.

sql · extension control-path evidence
SELECT current_setting('extension_control_path') AS extension_control_path,       current_setting('server_version') AS server_version;
shell · host-side PostgreSQL path evidence
pg_config --versionpg_config --sharedirpg_config --pkglibdir

Do not assume the pg_config found first in a shell PATH describes the same server process. Compare its major/version and installation provenance with the running server and the operating-system package inventory.

3. Inspect the control-file contract before installation

sql · available versions, trust, schema and dependencies
SELECT name, version, installed,       superuser, trusted, relocatable, schema, requires, commentFROM pg_available_extension_versionsWHERE name IN ('hstore','postgres_fdw')ORDER BY name, version;

These columns expose selected control-file properties. superuser=true normally means only a superuser can install/update the extension. When trusted=true is also declared, PostgreSQL permits a non-superuser with CREATE on the current database to install it; the install/update script itself executes as the bootstrap superuser. This is why marking an extension trusted is a strong security promise, not a convenience flag.

The requires array declares prerequisite extensions. CREATE EXTENSION ... CASCADE can install missing dependencies recursively, but it selects their default versions. Production change review should normally resolve dependency versions deliberately instead of using CASCADE as discovery.

4. Secure the destination schema

sql · create a locked extension schema and disposable installer role
CREATE SCHEMA IF NOT EXISTS ch19_ext AUTHORIZATION servicehub_owner;REVOKE CREATE ON SCHEMA ch19_ext FROM PUBLIC;DROP ROLE IF EXISTS ch19_extension_installer;CREATE ROLE ch19_extension_installer NOLOGIN;GRANT CREATE ON DATABASE servicehub_lab TO ch19_extension_installer;GRANT USAGE, CREATE ON SCHEMA ch19_ext TO ch19_extension_installer;

A secure install schema is not cosmetic. Extension installation/update scripts resolve object names through a controlled search_path; an untrusted user's trojan-horse objects in writable installation/dependency schemas can turn a careless privileged extension script into privilege escalation.

5. Install a trusted supplied extension as a non-superuser role

hstore is a PostgreSQL-supplied trusted extension in a default installation. First verify its row in pg_available_extension_versions. If unavailable, install the matching PostgreSQL 18 contrib package and repeat the preflight.

sql · trusted-extension installation
SET ROLE ch19_extension_installer;CREATE EXTENSION hstore  SCHEMA ch19_ext;RESET ROLE;REVOKE CREATE ON DATABASE servicehub_lab FROM ch19_extension_installer;SELECT e.extname, e.extversion,       n.nspname AS schema_name,       pg_get_userbyid(e.extowner) AS extension_ownerFROM pg_extension AS eJOIN pg_namespace AS n ON n.oid = e.extnamespaceWHERE e.extname = 'hstore';

The extension object is owned by the caller role. For a trusted extension whose script is allowed to run with bootstrap-superuser privileges, contained objects can have different ownership according to the extension packaging rules. Do not infer contained-object privileges merely from pg_extension.extowner.

6. What files does CREATE EXTENSION conceptually consume?

Artifact Purpose Operational concern
name.control Default version, trust/superuser, schema, dependencies, relocatability, module pathname Must match the running server's installed package
name--version.sql Creates database objects for a version Executes inside an implicit transaction and can be privileged
name--old--new.sql Updates member objects between versions Must be reviewed/tested like a schema migration
shared library, if any Native C code loaded into PostgreSQL backend processes ABI/version/security/crash blast radius

An SQL-only extension can still be security-sensitive. A native extension adds another boundary: server process code can corrupt memory, crash a backend, or interact with the OS according to its implementation and privileges.

7. IF NOT EXISTS is not verification

sql · deliberately incomplete install check
CREATE EXTENSION IF NOT EXISTS hstore;-- NOTICE: extension "hstore" already exists, skipping-- The NOTICE does not prove the existing object is in the desired-- schema/version or matches today's package files. Verify:SELECT e.extname, e.extversion, n.nspnameFROM pg_extension AS eJOIN pg_namespace AS n ON n.oid = e.extnamespaceWHERE e.extname = 'hstore';

PostgreSQL explicitly warns that IF NOT EXISTS only avoids an error; it does not prove the existing extension matches what the current statement would install. Treat installed version/schema/dependencies as acceptance evidence.

8. Review update paths before running an update

sql · extension update-path evidence
SELECT name, default_version, installed_versionFROM pg_available_extensionsWHERE name = 'hstore';SELECT *FROM pg_extension_update_paths('hstore')WHERE source = (  SELECT extversion FROM pg_extension WHERE extname = 'hstore')ORDER BY target;

ALTER EXTENSION hstore UPDATE can only apply update scripts that exist in the installed package. PostgreSQL chooses an available path; it does not understand semantic version ordering. Review the path and extension release notes, back up/restore-test, and then apply the update in a change window appropriate to the extension's objects.

9. Dependencies and member objects

sql · inspect extension members through pg_depend
SELECT pg_describe_object(d.classid, d.objid, d.objsubid) AS memberFROM pg_depend AS dJOIN pg_extension AS e  ON e.oid = d.refobjidWHERE d.deptype = 'e'  AND e.extname = 'hstore'ORDER BY memberLIMIT 30;

Extension member objects are managed as one package. Changing a member manually can create drift: pg_dump normally dumps CREATE EXTENSION, not the member's modified definition. Extension changes belong in versioned update scripts or a separately owned object outside the extension.

Production judgment

Adopt an extension only after you can identify its source/package, license, target PostgreSQL majors, available/install version, trust/superuser model, schemas/dependencies, native code, preload/restart requirements, backup/restore behavior, update path, monitoring, and removal plan.

10. Checkpoint

Check your understanding

  1. What is the difference between pg_available_extensions and pg_extension?
  2. What does trusted=true permit—and why is it security-sensitive?
  3. Why should an extension install schema reject CREATE from untrusted roles?
  4. Why is CREATE EXTENSION IF NOT EXISTS insufficient as a deployment check?
  5. Why can manually editing an extension-member function break restore expectations?
Review the answers

Available views describe files/versions the server can load; pg_extension describes what this database installed. Trusted permits eligible non-superusers with database CREATE to install despite a superuser requirement, with privileged script execution. Writable install schemas permit trojan-object attacks on careless scripts. IF NOT EXISTS proves only name existence. pg_dump normally recreates extension packages rather than dumping altered member definitions.

Authoritative references

Extension, FDW, language, and server-code behavior is privilege-, package-, version-, and platform-sensitive. These PostgreSQL 18 primary sources define the mechanisms used here.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.