# extension_destdir

> extension_destdir is a Debian/PGDG downstream staging-prefix GUC observed in the packaged PostgreSQL 9.5–17 images. It was never an upstream PostgreSQL parameter and disappears from the measured packages at PostgreSQL 18.
---

> [!NOTE]
> **Fact — measured pg_settings description:** “Path to prepend for extension loading.”

## Identity {#identity}

| Field | Value | Meaning |
| --- | --- | --- |
| Type | `string` | Measured downstream pg_settings type |
| Context | `superuser` | Settable at runtime by a superuser |
| Unit | — | Raw unit |
| Range | — | Raw limits in the last observed version |
| Enum values | — | — for non-enum types |
| Category | File Locations | Measured downstream classification |
| Latest boot value | `""` | empty string |
{.fields meta="-"}

## Lifecycle {#lifecycle}

| Fact | Value |
| --- | --- |
| First observed | PG9.5 |
| Present in | PG9.5–17 |
| Removed in | PG18 |
| Introduction commit | [Debian/PGDG downstream patch](https://sources.debian.org/patches/postgresql-17/17.10-0%2Bdeb13u1/extension_destdir/) — Debian-specific extension_destdir patch used for extension build-time testing |
| Commit date | — |
| Discussion | [downstream documentation](https://manpages.debian.org/experimental/postgresql-common/pg_virtualenv.1.en.html) |

## Default history {#default-history}

| Versions | Raw `boot_val` | Unit | Human value |
| --- | --- | --- | --- |
| PG9.5–17 | `""` | — | empty string |
{.full-width caption="Measured PG9.0–19 Beta 3 boot defaults"}

## How it works {#mechanism}

The version matrix proves that extension_destdir is exposed by the measured Debian/PGDG binaries from PG9.5 through PG17. An exhaustive upstream GUC-source pickaxe has no introduction commit because the name comes from Debian's extension_destdir package patch, not the PostgreSQL source tree.

The patch prepends a DESTDIR-like staging root when the server locates extension control and SQL files and the modules behind functions. Debian's pg_virtualenv uses it to test a package before its files are installed in their final system paths; it was explicitly a packaging and build-time facility, not a general production extension search path.

From PostgreSQL 18, use the upstream extension_control_path for control and SQL files together with dynamic_library_path for shared libraries, or install the extension in standard locations. Remove extension_destdir from every config file, ALTER SYSTEM layer, role/database setting, and generated template before starting the newer server.

## Tuning advice {#tuning-advice}

> [!TIP]
> **Advice.** These are workload-specific starting points and must be validated with measurements.

| Workload | Guidance |
| --- | --- |
| OLTP | Treat this as downstream migration debt, not a tuning control. Package extensions in supported locations, test extension_control_path and dynamic_library_path under the service account, and remove the obsolete key before the PostgreSQL 18 upgrade. |
| OLAP | Apply the same migration to ETL and analytical extension stacks, including worker processes and standbys. Rehearse CREATE EXTENSION, ALTER EXTENSION UPDATE, restore, and failover with the final filesystem layout. |
| Small nodes | Prefer standard package locations. A one-node system gains little from recreating a Debian build-time staging mechanism, while an unknown GUC can prevent a modern server from starting. |
{.full-width}

## Pigsty {#pigsty}

Values use the fixed 8-vCPU, 32-GiB, 100-GiB SSD fixture and render the current Pigsty templates for PG17; this does not assert current Pigsty support for that historical or beta release.

| Template | Effective value | Versus upstream boot | Source expression |
| --- | --- | --- | --- |
| OLTP | Unmodified | — | — |
| OLAP | Unmodified | — | — |
| CRIT | Unmodified | — | — |
| TINY | Unmodified | — | — |
{.full-width}

> [!CAUTION]
> **Advice — pending human review.** Fact from the current Pigsty template projection: OLTP: PG9.5–17 unmodified; OLAP: PG9.5–17 unmodified; CRIT: PG9.5–17 unmodified; TINY: PG9.5–17 unmodified. No Pigsty-specific rationale is inferred from an absent override.

## Common pitfalls {#common-pitfalls}

- Calling extension_destdir an upstream PostgreSQL parameter or assigning it an upstream introduction commit.
- Continuing to emit the downstream name on PostgreSQL 18 or later, where the measured packages no longer recognize it.
- Migrating extension control files but forgetting the shared-library half of the path design.
- Testing as a build user while the database service account cannot read the final directories, files, or parent paths.

## Related parameters {#related-parameters}

[`extension_control_path`](/parameters/extension-control-path/) · [`dynamic_library_path`](/parameters/dynamic-library-path/) · [`shared_preload_libraries`](/parameters/shared-preload-libraries/) · [`session_preload_libraries`](/parameters/session-preload-libraries/) · [`config_file`](/parameters/config-file/)

## References {#references}

- [Debian source patch: extension_destdir](https://sources.debian.org/patches/postgresql-17/17.10-0%2Bdeb13u1/extension_destdir/)
- [Debian pg_virtualenv documentation](https://manpages.debian.org/experimental/postgresql-common/pg_virtualenv.1.en.html)
- [PostgreSQL 18: extension_control_path](https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-EXTENSION-CONTROL-PATH)
- [Machine-readable GUC export](/data/guc.jsonl)
