postgresql-best-practices/references/azure-postgresql-extension-lifecycle.md
Version 9ba96abc800a.bb1 · MIT. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.
← Return to resource and package checksum
title: "Azure PostgreSQL Extension Lifecycle" description: "Manage PostgreSQL extensions on Azure Database for PostgreSQL Flexible Server: allowlisting, shared_preload_libraries, CREATE EXTENSION, and version upgrades"
tags: [azure, postgresql, extensions, allowlist, shared-preload, pgvector]
Extension Lifecycle
Response focus: Prioritize the allowlist-then-create workflow, binary name mapping, and shared_preload restart requirement. Avoid explaining basic
CREATE EXTENSIONsyntax or generic PostgreSQL extension concepts.
Prerequisites
azure_pg_adminrole (default admin role; never superuser)- Shell execution: Steps 1-3 below require az CLI (execute directly via shell). Step 4 (
CREATE EXTENSION) is executable viapostgres_mcp_modify. Server restart requires user confirmation.
Instructions
Step 1: Check if extension is available
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name = 'vector'
ORDER BY name;
Step 2: Allowlist the extension (Azure-specific requirement)
# Add to azure.extensions server parameter
az postgres flexible-server parameter set \
--resource-group myRG --server-name myserver \
--name azure.extensions --value "vector,pg_stat_statements,pg_cron"
WARNING: This overwrites the current list. Always GET current value first and append.
Step 3: For extensions requiring preload (pg_stat_statements, pg_cron, auto_explain)
# Requires server RESTART
az postgres flexible-server parameter set \
--resource-group myRG --server-name myserver \
--name shared_preload_libraries --value "pg_stat_statements,pg_cron"
az postgres flexible-server restart --resource-group myRG --name myserver
Step 4: Create the extension
-- Use binary name, not marketing name
CREATE EXTENSION vector; -- NOT pgvector
CREATE EXTENSION pg_stat_statements;
CREATE EXTENSION azure_ai;
Step 5: Upgrade an extension
ALTER EXTENSION vector UPDATE TO '0.8.0';
Verify
-- Confirm extension installed
SELECT extname, extversion FROM pg_extension WHERE extname = 'vector';
-- List all installed extensions
SELECT extname, extversion FROM pg_extension ORDER BY extname;
-- Verify shared_preload_libraries
SHOW shared_preload_libraries;
Common Mistakes
- [CRITICAL] Allowlist append workflow:
az postgres flexible-server parameter show --name azure.extensionsreturns current list. You must append, not replace:az postgres flexible-server parameter set --name azure.extensions --value "vector,pg_diskann,pg_trgm,NEW_EXT". Setting--value "NEW_EXT"alone REMOVES all existing extensions
Wrong:
bash
# OVERWRITES entire list removes all other extensions!
az postgres flexible-server parameter set --name azure.extensions --value "pg_cron"
Right:
bash
# First GET current list, then APPEND
az postgres flexible-server parameter show --name azure.extensions --query value
# Returns: "vector,pg_stat_statements"
az postgres flexible-server parameter set --name azure.extensions --value "vector,pg_stat_statements,pg_cron"
- [HIGH]
shared_preload_librariesrestart behavior: Adding to this parameter requires server restart. Plan maintenance window. Current value check:SHOW shared_preload_libraries. Common values needing preload:pg_cron,pg_stat_statements,auto_explain - [HIGH] Binary name vs marketing name mapping:
pgvectorCREATE EXTENSION vector.pg_partmanCREATE EXTENSION pg_partman.PostGISCREATE EXTENSION postgis. Always verify withSELECT * FROM pg_available_extensions WHERE name LIKE '%search%'
Wrong:
sql
CREATE EXTENSION pgvector;
-- ERROR: extension "pgvector" is not available
Right:
sql
CREATE EXTENSION vector; -- binary name, not marketing name
- [MEDIUM] Version pinning for reproducibility:
CREATE EXTENSION vector VERSION '0.7.0'ensures same version across environments. Without version, server'sdefault_versionis used which auto-updates with server patches. Pin in migration scripts - [MEDIUM] Extension availability matrix: Available:
vector,pg_diskann,postgis,pg_cron,pg_partman,pg_stat_statements,pg_trgm,hstore,uuid-ossp,azure_ai. NOT available:file_fdw,plpython3u,adminpack,dblink(to external). Check:SELECT * FROM pg_available_extensions ORDER BY name - [HIGH]
azure_pg_adminrole limitations: You haveazure_pg_admin, not superuser. Cannot:CREATE EXTENSIONfor unlisted extensions, load custom C libraries, modifypg_hba.conf. Can: create any extension in the allowlist, manage roles, create databases
Wrong:
sql
-- Attempting superuser-only operations
ALTER SYSTEM SET shared_preload_libraries = 'pg_cron';
-- ERROR: must be superuser to execute this command
Right:
bash
# Use Azure CLI for postmaster-level GUCs
az postgres flexible-server parameter set --name shared_preload_libraries --value "pg_cron"
az postgres flexible-server restart --resource-group myRG --name myserver
- [CRITICAL] Dependency checking before DROP:
SELECT classid::regclass, objid, deptype FROM pg_depend WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'vector')shows what depends on the extension. CASCADE drops all dependent objects (indexes, columns) - [HIGH] Extension update path:
ALTER EXTENSION vector UPDATE TO '0.8.0'only works if update path exists. Check:SELECT * FROM pg_extension_update_paths('vector') WHERE source = '0.7.0'. Some updates require DROP + CREATE (data loss for extension-managed types) - [CRITICAL] "extension not allowlisted" error: Run Step 2 to add the extension to the
azure.extensionsserver parameter. Remember to include all existing extensions in the value - [HIGH] "must be loaded via shared_preload_libraries" error: Run Step 3 and restart the server. The restart is required for the parameter change to take effect
- [HIGH] Exact error recognition:
ERROR: extension "X" is not available= not in allowlist; runSHOW azure.extensions.ERROR: could not open extension control file= allowlisted butshared_preload_librariesmissing; add it and restart.ERROR: permission denied to create extension= session user lacksazure_pg_admin - [HIGH] Version/region extension availability drift: An extension available in East US may still be missing in West Europe. Check
SELECT * FROM pg_available_extensionson the specific target server - [MEDIUM] Extension dependency chains on drop/upgrade:
DROP EXTENSION vector CASCADEalso removespg_diskannindexes. For upgrades, dependent extensions may need updates beforeALTER EXTENSION ... UPDATE - [MEDIUM] CLI vs Portal parameter precedence: CLI and Portal write the same backend setting, but the Portal can lag by 1-2 minutes. Verify the live value with
SHOWafter changes
On Azure HorizonDB (Preview)
-
The
azure.extensionsallowlist is set on a parameter group, not per-server. Parameter groups are first-class resources attached to the cluster (defaultdefault_pg17). To changeazure.extensions, create a new parameter group with the desired allowlist and attach it to the cluster, then runCREATE EXTENSION. Preload-required libraries still go inshared_preload_libraries(static → restart). -
The
azure.extensionsallowlist is set on a parameter group, not per-server. A parameter group is a first-class Azure resource attached to the cluster (defaultdefault_pg17); editazure.extensionsthere instead ofaz postgres flexible-server parameter set, then runCREATE EXTENSION. Preload-required libraries still go inshared_preload_libraries(static → restart). - PostgreSQL 17 only; HorizonDB additionally ships
pg_textsearch(BM25 full-text) andpg_diskann.
# HorizonDB: allowlist lives on the cluster's parameter group
az horizondb parameter-group update \
--resource-group myRG --name default_pg17 \
--parameters '[{"name":"azure.extensions","value":"vector,pg_diskann,pg_textsearch"}]'
See Extensions in HorizonDB, Allow extensions, and Parameter groups.
References
Anti-Hallucination Rules
- Do NOT claim an extension is available on Azure without verification via
SELECT * FROM pg_available_extensions WHERE name = '...'. Extension availability varies by PG major version, region, and service tier. - Do NOT invent extension names. Always verify the binary name (e.g.,
vectornotpgvector,postgisnotPostGIS). - Do NOT claim
ALTER SYSTEMworks on Azure Flexible Server — it requires superuser which is not available. - Do NOT suggest granting superuser or creating superuser roles — Azure only provides
azure_pg_admin. - Do NOT assume
shared_preload_librariescan be changed without a server restart. - Do NOT claim extensions from community PostgreSQL are automatically available on Azure — they must be in the Azure allowlist.
- Do NOT confuse extension availability (visible in
pg_available_extensions) with allowlist status (visible inSHOW azure.extensions). An extension must be allowlisted AND available. - Do NOT claim
dblinkto external servers,file_fdw,plpython3u, oradminpackare available — they are blocked on Azure. - When uncertain about extension support, say "verify availability with
SELECT * FROM pg_available_extensions" rather than asserting it exists.