Skip to content

[Feature]: Dynamic loading of PostgreSQL extensions via image catalogs #8495

Description

@gbartolini

Is there an existing issue already for this feature request/idea?

  • I have searched for an existing issue, and could not find anything. I believe this is a new feature request to be evaluated.

What problem is this feature going to solve? Why should it be added?

In issue #7991, we completed the first part of the job described in issue #7188 by implementing dynamic loading of extensions through the .spec.postgresql.extensions stanza. The second part of the initial proposal involves adding support for dynamic loading of extensions via image catalogs. This issue is focused on that aspect.

Describe the solution you'd like

Consider the following catalog:

apiVersion: postgresql.cnpg.io/v1
kind: ImageCatalog
metadata:
  name: postgresql
  namespace: default
spec:
  images:
    # ...
    - major: 18
      image: # ... PostgreSQL 18 container image
      extensions: # this should be a list of ExtensionConfiguration objects
        - name: pgvector
          image:
            reference: # registry path for the "pgvector" PostgreSQL 18 extension image

A possible cluster definition could be:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg18
spec:
  instances: 1
  imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ImageCatalog
    name: postgresql
    major: 18
  postgresql:
    extensions:
      - name: pgvector
  storage:
    size: 1Gi

Given that the Cluster already points to a catalog definition for version 18 and requires the pgvector extension, the operator will point to the only pgvector extension image declared in the catalog for PostgreSQL 18. If no such extension exists, the change fails.

The catalog should enable the default configuration of the following options for an extension:

  • extension_control_path
  • dynamic_library_path
  • ld_library_path

We should also consider the possibility of exposing dependencies on other extensions by potentially including the requires field in the control file of PostgreSQL extensions.

Override

The image catalog will basically introduce a middle layer in the "convention over configuration" process of extension definition. Right now, the .spec.postgresql.extensions stanza changes the value from an empty set. When a catalog is present, the .spec.postgresql.extensions stanza will change the values of a given extension from the catalog ones.

For example:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg18-direct-extension
spec:
  instances: 1
  imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ImageCatalog
    name: postgresql
    major: 18
  postgresql:
    extensions:
      - name: pgvector
        image:
          reference: # ... alternative pgvector container image for PostgreSQL 18
  storage:
    size: 1Gi

The override here will request a different image from the one in the catalog. The following options should be overridden based on the name of the extension:

  • extension_control_path
  • dynamic_library_path
  • ld_library_path

Describe alternatives you've considered

See #7188

Additional context

No response

Backport?

No

Are you willing to actively contribute to this feature?

Yes

Code of Conduct

  • I agree to follow this project's Code of Conduct

Activity

  1. added this to the 1.29 milestone on Aug 31, 2025
  2. self-assigned this
    on Aug 31, 2025
  3. ibotty commented on Oct 14, 2025

    @ibotty

    This proposal bundles the declaration of the extension(s) with the base image.

    So if one team manages the postgres-bookworm image catalog (like the catalog from cnpg) and another team manages the my-extension extension they have to collaborate on the image catalog.

    Related: if one team manages extension_1 and another one extension_2, they have to collaborate on the image catalog.

    Maybe a different object type (e.g. ImageExtensionCatalog) that references the existing ImageCatalog) can decouple these.

  4. self-assigned this
    on Dec 11, 2025
  5. changed the title [-][Feature]: dynamic loading of PostgreSQL extensions via image catalogs[/-] [+][Feature]: Dynamic loading of PostgreSQL extensions via image catalogs[/+] on Dec 12, 2025
  6. moved this to Todo in Roadmapon Dec 12, 2025
  7. gbartolini commented on Dec 16, 2025

    @gbartolini
    ContributorAuthor

    Thanks @ibotty.

    This proposal bundles the declaration of the extension(s) with the base image.

    It cannot be otherwise. Libraries shipped by the extension must be related to the actual OS on the base image, otherwise it won't work.

    For example: pgvector:0.8.1-18-trixie must be bundled with postgresql:18-minimal-trixie.

    So if one team manages the postgres-bookworm image catalog (like the catalog from cnpg) and another team manages the my-extension extension they have to collaborate on the image catalog.

    Ultimately, you will need one source, identifying your supply chain. Nobody is preventing you to "merge" the image catalogs. They are just YAML files.

    What we are going to do community wise is to extend the ClusterImageCatalog that we build weekly for PostgreSQL 18 as follows (more or less):

    apiVersion: postgresql.cnpg.io/v1
    kind: ClusterImageCatalog
    metadata:
      name: postgresql-minimal-trixie
      labels:
        images.cnpg.io/family: postgresql
        images.cnpg.io/type: minimal
        images.cnpg.io/os: trixie
        images.cnpg.io/date: '20251208'
        images.cnpg.io/publisher: cnpg.io
    spec:
      images:
      - <...>
      - major: 18
        image: ghcr.io/cloudnative-pg/postgresql:18.1-202512080807-minimal-trixie@sha256:<snip>
        extensions:
          pgvector:
            image: ghcr.io/cloudnative-pg/pgvector:0.8.1-18-YYYYMMDDhhmm-trixie-@sha256:<snip>
          postgis:
            <...>

    Maybe a different object type (e.g. ImageExtensionCatalog) that references the existing ImageCatalog) can decouple these.

    I am worried that this could complicate the user experience, which is precisely why we developed image catalogs. While image catalogs are complex to build (which is acceptable as it's part of the supply chain), they significantly enhance the user experience during run-time. I am concerned that a different object type would have the opposite effect (simplify build process, complicate user experience).

    Thoughts?

  8. AmanKumar1411 commented on Dec 30, 2025

    @AmanKumar1411
    Contributor

    After reading the discussion, it makes sense that extension images need to be closely tied to the base PostgreSQL image and OS. Since extensions ship native libraries, separating them into a different catalog could easily lead to incompatible combinations at runtime.

    Keeping extensions defined inside the ImageCatalog keeps the user experience simple and avoids invalid configurations. The additional complexity is pushed to image and catalog maintainers, which is acceptable as part of the supply chain, while users get a safer and more predictable runtime behaviour.

    This approach also aligns well with the “convention over configuration” goal of image catalogs.
    @gbartolini

  9. added a commit that references this issue on Mar 2, 2026
    cd73556
  10. moved this from Todo to Done in Roadmapon Mar 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions