PGConf.dev 2026 Extension Summit
The 2026 Extension Ecosystem Summit takes place at PGConf.dev in Vancouver, BC, Canada on 21 May 2026. This page records the notes taken from each session.
How immutability challenges extension packaging and distribution
Framing: How immutability challenges extension packaging and distribution
The opening question was specifically about immutable Postgres images:
- How do you add an extension to an immutable Postgres image?
- Do you have to restart the server with a new image every time you want to load a new extension?
- CNPG containers are immutable today, so extensions have to be baked in at image build time.
What Postgres 18 gave us, and what's still missing
Postgres 18 introduced extension_control_path, which allows mounting extensions as a read-only volume, a real step forward. But two restart points remain:
- Volumes are only resolved at pod startup → adding a new volume requires a pod restart
- Updating the GUC (
extension_control_path) requires a Postgres restart
What "ideal" would look like
Add extensions by patching the manifest — no pod restarts, no Postgres restarts, no GUC updates.
Key discussion threads
1. Why care about immutability at all?
Timescale was raised as a counter-example: they allow you to upgrade the Timescale extension without restarting Postgres, but to do that they drop immutability. So the tradeoff is real.
The argument for keeping immutability: it gives you a verification chain. You can confirm the extension image hasn't changed, that it has no SBOM mismatch or injected code, and that what's running is what was vetted. Containerd and linkerd already verify image signatures by default — most users just don't enforce it.
Counterpoint that came up repeatedly: immutability and verification are two different things. You can have verified-but-mutable artifacts (signed packages, GPG keys, signed images). Immutability is *one way* to get a strong verification guarantee, not the only way.
Where immutability matters directly regardless of containers: when the base image itself is signed (e.g., postgres.app on macOS signed with Apple's cert), installing an extension into it breaks the signature.
2. Why not just pre-install every extension?
You can build a Docker image with all the extensions you need pre-installed. Extensions aren't huge — nowhere near TB scale — so a single image with everything baked in is feasible, and Docker's layer caching makes it cheap.
The problem this doesn't solve:
- Extension upgrades — getting new versions of extensions into a running deployment
- Two distinct sub-problems: (a) how do you deliver the new extension to the pod without restarting it, and (b) how does Postgres pick it up without restarting?
3. Hot-loading without a restart
The practical pain point underneath everything. Restarts are increasingly unacceptable — uptime expectations have moved from 99.9% to "seconds per year," and large in-memory state makes restarts expensive.
Partial solutions discussed:
- Kubernetes ConfigMaps — mount extensions in, but 1 MB limit (works for small binaries only)
- containerd — can mount images into a running container without restarting it
- The remaining hard problem is Postgres itself picking up new extensions without a backend restart
4. Service provider perspective
An attendee from a cloud-provider described how they sidestep most of the immutability pain:
- Maintain a vetted list of extensions, all pre-baked into the image
- Customers just run
CREATE EXTENSIONagainst what's already there - The expensive step is vetting — confirming the extension won't do something stupid or break tenant isolation on shared infrastructure
- Once vetted, immutability is moot because the image is fixed
- The "1,000 extensions on demand" use case is not their problem
Counterpoint: even if SaaS providers don't care, on-prem deployments — banks, telcos, regulated environments — do. Some of these are purist about immutability. Postgres needs to be adoptable there too.
5. Proposed: directory-of-directories layout (David's proposal)
The concrete proposal that got the most traction, previously floated by David. Today an extension is scattered across the filesystem (share/extension/, lib/, etc.). Proposal:
- A top-level directory containing one subdirectory per extension
- Each subdirectory is self-contained: control file, SQL scripts, shared libraries, and optionally a manifest / signature at the root
- Postgres recurses into the parent to discover extensions
- Additive — coexists with today's mechanism
This avoids the GUC-update problem: you don't keep extending a path list, you drop a directory in and Postgres finds it.
Open questions on this proposal:
- How feasible is it to get into core?
- Recursion depth needs to be capped
- Should Postgres verify what it loads, or just load everything in the directory? If everything, anyone with write access can inject extensions.
- Pushback from the floor: trust today is *already* external to the project — anyone who can add a directory to the current GUC can do the same thing. So is this actually a worse position than what we have?
6. Hash-based verification
Idea floated: when installing an extension, the user supplies a content hash, and Postgres refuses to install unless the on-disk extension matches.
- Solves a related problem too:
install 1.2andinstall 1.0 then upgrade to 1.2can produce different end states because upgrade migration scripts aren't perfect. A hash gives exact-bytes guarantees. - Concern: hash verification at load time could be expensive (seconds for large shared libraries). May need to verify-once-at-install rather than on every load.
Someone also floated hashing the entire canonical catalog state so cross-extension dependency consistency could be verified pre- and post-install.
7. Catalog as source of truth for extension artifacts
Proposal: install the extension artifacts into the database itself — the catalog holds the copy. You stop maintaining files on the filesystem for extension purposes; the database is authoritative.
- Got shot down previously because some extensions (
shared_preload_libraries) must load before the catalog is available - Would change extensions from a filesystem thing into a database thing
- PG TLE already does something like this for the trusted-language subset
The deeper issue underneath: today an extension's identity is split between the catalog (pg_extension, per-database) and the filesystem (shared library, per-instance), with no enforced linkage between SQL-object version and .so version. This bites hard in multi-database clusters.
8. PG TLE (Trusted Language Extensions)
Mentioned as a partial solution for the pure-SQL / trusted-language subset — eliminates the shared-library problem entirely for that class. Doesn't help for extensions that need C code.
Where things stand
- No conclusions. Acknowledged this conversation has happened before.
- Closest thing to a path forward: David's directory-of-directories proposal as an incremental addition (the way
extension_control_pathwas added in 18), not a redesign.
Open questions to take forward
- Can the directory-of-directories approach be prototyped as an additive search mechanism, like
extension_control_pathwas? - What's the right allow-list / verification model so "directory presence" doesn't equal "loadable"?
- Can we get to the ideal state — patch manifest, no pod restart, no Postgres restart, no GUC update — incrementally from where Postgres 18 left us?
Extending Authorisation and Authentication
Extensions and upgrades
Hooks and APIs: What to expose in the core
To extend, to contribute, or to petition to core?
Alastair: Intro
- Functionality can be:
- In core
- In /contrib and installed automatically
- In /contrib
- An extension managed elsewhere
- Moving exiting functionality toward or away from for is impossible
- Oid stability (predictability) during pg_upgrade
Moving further out
- Why
- Limit impact/side effects to those who really use the feature
- Moving away form historical “mistakes”
- Upsides
- Options: Learn how options progress — or don’t
- Delegate rather than deprecate
- Downsides
- Reduction in perceived “completeness” of Postgres
Moving closer in
- Why
- Extensibility isn’t available
- …
- Upsides
- Increased: technical scrutiny and maintenance commitment
- Perceived: Postgres solution completeness and seriousness about a class of problems
- Downsides
- Tying to release cycles
- Licensing changes (when crossing into PGDG repos)
- Upgrading from extension to contrib/core painful
- Adds to cognitive load of core maintainers
Candidates for moving
- btree_gist
- Contrib -> auto installed
- Required to make exclusion constraints work
- Oid management probably a blocker
- pg_stat_statements
- Contrib -> auto installed
- Seems like basic fictionality
- Non-trivial overhead
Candidates for moving outward
- Money type
- Just, oops?
Discussion
Performance, get rolling window of performance issues, but problem is they’re high cost observability metrics. Need core support to expose, where to store, where does it fit? Extensions? Code? That’s a struggle
Alastair: Got easier 1.5y ago, Postgres 17, Michael Pacquier’s pluggable cumulative statistics. Can call same framework like pg_stats, get stuff from memory, reset functions work, all that stuff. Created treatments for internal and external stuff, still not zero overhead or that split wouldn’t have happened. But Good framework for building on. Only get better if we build on them. Quite a bit of pg_stat_statements being rebuilt to run on top of that; previous approach caused some problems.
One dimension to extensions: Availability: different extensions on RDS, Aurora, etc. Make it hard to rely on them to be there. Some providers disable them, some allow superuser task to install them. pg_visibitliy or wal_inspect, core extensions, still availability varies widely
Alastair: Fewer and fewer available in something like Aurora because not Postgres.
Person: If you take Supabase, just Postgres, still stuff that’s not usable.
Alastair: not sure we can solve that here. Cloud envs don’t want you to access file system, Policy prevents. Especially for very raw extensions, not sure there’s an answer. There are ideas to sandbox extensions, e.g., pg_tle, to box execution, can’t get to network for disk. You have env where non superusers can use. Doesn’t address things like page_inspect or wal_inspect, which give full access.
Another example: wal_summarize in core, not extension, some providers don’t allow you to turn it on.
Alastair: May not have wal in the same way, e.g., Aurora.
Laurenz: Pick a different provider.
David: What can we do about that. We create what we thinks is good and AWS makes its choices.
Alastair: If you look at whom to build on,
Felka, AWS: Outside contrib, we need to vet to trust extension. We WANT you to have page_inspect, but we need to trust. Not that we don’t want you to have extensions, we need to trust. IF something moves out of contrib trust becomes more of an issue
Alastair: What can we as extension providers do to make that easier.
Laurenz Albe: page_inspect just gives all access.
It’s my page, why can’t I look at?
What can extension providers do? Hard to build one that’s bulletproof. Sandbox, not auditing, limit execution environment of extension.
Alastair: Can call stuff from OS, or only from Postgres
Felka: We don’t want to allow access to OS stuff, Swiss cheese model, every layer is too far.
Person: PITA to fully understand extensions. Some have source, some only binary. How do you validate unless the community can come together come up with security verification framework.
Alastair: Maybe not safe, but certify what an extension wants to do, “this doesn’t talk to anything but query back end,”, “ this one talks to share memory”, etc.
Person: Is your extension ready. Who takes care of migration. Do you have global variables. These are security concerns. Shared buffer. We need different framework altogether to trust. System level is security concern. I think every vendor has own ways to verify extensions.
Felka: Even if you say creator has to list what extension does, how do we trust it?
Alastair: Need to take out of binary result. Get binaries and look at symbol tables to verify they call only what they need. IS scale, Timescale and Citus at one end, then the rest. Binary analysis will get you a fair way.
Felka: In SQL can generate copy to program, hard to detect.
Alastair; True, special case.
Timescale, redgate, confused how many people developing beyond what’s in contrib. Versioning a PITA. Why does pg_dump not put the version with it? How often with Timescale have people busted stuff? Actually app management with extensions, so many come to Postgres have no idea how to manage it. Different vendors with different versions, a beautiful thing and also extraordinary difficult to manage.
Alastair: Some of this discussed in upgrade session. Do you specify version of extension all the way to proc catalog? Maybe easier time to upgrade if can have multiple installed version. Whole nother—fish. Some things we can see as catalog’s problem, but not “this function an be an extensions”
Other guy: Easy enough to have rule to upgrade extension before upgrade server, so then you’re ready to test on old and new version of server. Easy. What’s hard is community tracking ABI breaks in order to document that they’ve making breaking changes
David; Build farm discussion, aim is to avoid issues
Person: Sometimes they look at all extensions and decide non one will care about a break
David: Yeah, they need to look at more stuff than just PGXN, need to make them aware of stuff as much was possible and they’ll avoid breaks.
Alastair: Surprised not hearing from anyone that their pet function should be in core.
Laurenze: Postgres wouldn’t be where it is today if there wan’t this wonderful extensibility. We have to take some pain for the benefit, otherwise never would have had PostGIS.
Alastair; I agree, usually more people arguing for moving stuff
Laurenze: I think people realize there’s good reason not to.
Daniel Gustafson: extension is frozen in time when we ship a major version. Extension will work from 15 ago with latest version. May have new feature, but won’t break old one. Contrib, if proposed today, wouldn’t happen because not all that useful, so a dumping ground for stuff.
Alastair: CITEXT: get work by David, but not as useful with case insensitive collations. Contrib provides useful test cases, maybe get rid of stuff unless providers useful test harness.
Daniel: I’ve been arguing this for a while. Pgcrypto a good example: has no place in core. But if we removed it would plain die. It’s therefore a useful place for exposing the API we wouldn’t have otherwise. Also good tutorial code. If something provides real value it would be better off outside contrib
Person: Consider project Peter G works on, pg_checker, if it was on GitHub, and he wanted to work on it, would he have to contribute to my GitHub project to keep it in sync with core?
How is that different from anything else?
If someone changes planner nodes, contract not to break contrib, but if you move it out it can break it.
Daniel: Just like anything else. pg_upgrade used to be in contrib, moved it into core, have done it in the past.
So to get rid of contrib, move everything into core or eliminate
Felka: Contrib is the gold standard we can trust;
Daniel: Have you looked at it?
AWS: Anything external means an external developer, I trust the core developers.
Daniel: Good argument, whom do you trust and why? Maintainers bring that to the table, collaborate to set level of trust. Def valid argument.
Is main different between contrib and core whether installed by default?
Daniel: Yes
Could you have contrib modules installed by default? Daniel: We don’t control packages. Christoph Berg packages them separately, we don’t provide packages. Packagers can make choice they want. We have no say in it. If it’s in src/bin, better chance of being installed by default, but still might not be. The fact that we don’t package Postgres probably a good move, because packagers can make their own decisions.
One thing: if something in contrib, proves a thing can be a pure extension, might not be able to rip out stuff in core. btree couldn’t be an extension.
Daniel: In general that should be the case.
Alastair: Get back to trust. Contrib a more trusted home for extensions. If extensions were hosted by something more like CNCF, would that give you more comfort?
Felka: Yeah. PGXN has no barrier, vetting should be part of it, automatic vetting.
Alastair: A model where ways for project, unfortunate how many extensions have issues. Need time to train up maintainers. Have also seen, PL/Rust went away when company working on it went another direction. Need catalog of trusted stuff.
Felka: Some things should be allowed to die.
True!
Laurenz: if proprietary company decides extension won’t ship without something, it’s dead in the water. If OSS not the end of the world if someone stops maintaining it.