Last week we had our September PostgresEDI meetup, the first since postgres.scot went up as the home for Postgres events in Scotland.
Thursday, September 24th took us back to Paterson's Land at the University of Edinburgh, room 1.27 this time, for two talks that could hardly have come at the subject from further apart. Thanks to everyone who came along, to Daniel for joining us from a different corner of the software world, and to pgEdge for the pizza and refreshments. Special thanks to the friend who came all the way down from Aberdeen for the evening, which is a serious commitment for a Thursday.
Jimmy Angelakos (pgEdge)
First up was my own talk on ColdFront, which moves cold rows out of Postgres onto object storage as Apache Iceberg tables in columnar Parquet, and keeps them readable from Postgres as though they had never gone anywhere. The design is deliberately slim: Postgres holds your tables and your SQL, pg_duckdb does the Iceberg reading and writing in-process, Lakekeeper is the catalog, and the object store is whichever one you already have. Your application goes on querying one relation.
The hard part is what happens when the cold tier is writable and several Postgres nodes are writing to it, with a single Iceberg catalog and a single bucket between them. ColdFront takes a ticket before each cold write so that two writers never collide in the first place, and we modelled that protocol in TLA+ rather than trusting our intuition for it.
I closed with vector search over cold data, where a probe comes down to a WHERE clause with no index to build.
📊 View the slides: ColdFront: Transparent PostgreSQL Data Tiering to Apache Iceberg (PDF)
Daniel Roe
After the break, Daniel Roe, who leads the Nuxt core team and works on it full-time at Vercel, showed us what Postgres looks like from the far end of the stack.
He started with wh
[...]Over the past month, several major features got reverted from Postgres 19. At this point, even if everything else goes perfectly, Postgres 19 will be released about a month later than originally planned. A couple recent blog posts seem to suggest the reverts happened due to AI finding complex bugs in those patches, with fixes way too invasive this late in the development cycle. I don’t think that narrative matches reality, and I think it matters to correct that.
Query hints: You asked for it, Postgres 19 gave it to you. Now, they are just waiting to see how you use it.
For years the Postgres community was against adding support for hints. They felt if you had correctly analyzed tables, the Postgres query planner would make the right choice. And they're not wrong, for the most part. Yet many DBAs and developers will tell you of a time when a plan suddenly changed or something was saved by a hint. We can debate the good and bad elements of hints, but the cool thing is that you will soon have a choice in Postgres 19+.
So what are query hints? I came from the SQL Server world like many folks in the Postgres world and they were just there. Oracle, too. They are explicit instructions you give with SQL to change the default execution plan. Note: While industry standard refers to these as "hints," Postgres 19 uses the term "advice," so use both when searching.
This feature, expected later this fall, is coming to Postgres 19 via two new contrib modules (extensions packaged with Postgres that have to be explicitly turned on, like pg_stat_statements, everyone's favorite extension).
Here's a quick look at what it looks like to turn on plan advice and use it:
Out now on GitHub and PGXN, pg_clickhouse v0.11.0 and the chdb extension v0.1.2 continue our dogged focus on cross-database compatibility. A slew of these enhancements derive from our header-only C libraries, clickhouse-c and pg-clickhouse-c. Let's take a look at just three of the changes in these releases.
What a character {#what_a_character}
First up, character encoding. In the process of developing the benchmark for the chdb extension post, I discovered that pg-clickhouse-c wasn't validating character encodings on text columns. My colleague Philip quickly patched the library to raise an exception when any text- or json-based type contains bytes that violate the database encoding.
This fix shipped in chdb v0.1.1, but we delayed pg_clickhouse a bit to avoid errors for anyone with existing foreign tables that read invalidly-encoded data. pg_clickhouse v0.11.0 adds a new foreign server option, check_encoding, that provides encoding error handlers. The options are:
After trying not to add any Rust packages to the PostgreSQL RPM repository, I finally bit the bullet and pushed pgrx and postgresql_anonymizer to the RPM repos, along with packaging guidelines:
https://github.com/pgdg-packaging/pgdg-rpms/wiki/Packaging-Rust-extensions-(pgrx
Some limitations exist for now:
https://github.com/pgdg-packaging/pgdg-rpms/wiki/Packaging-Rust-extensions-(pgrx)#supported-distributions
Hoping to add RHEL 10.3 and 9.9 support in November.
Enjoy!
In many real production databases, we often see some tables receiving high-frequency updates (millions per day) and autovacuum running repeatedly (hundreds of times per day). Additionally, those tables can sometimes become heavily bloated. The end effect is poor performance, poor concurrency, and an unmanageable database.
In case we are using methods pg_gather for diagnosis, such anomalies are easy to spot by clicking on the table header to sort.
Very often, a closer look at these tables reveals that status-update workloads are driving these heavy updates. Many times, even the table names reveal their purpose through words like “task”, “queue”, or “bucket”. A discussion with application architects often reveals that these tables are used for specific workflows, with status fields tracking what is completed and what remains pending for further processing. There can also be multiple workflow stages. Sounds like use case for Kafka, right? Yes, Kafka is widely used to manage such workflows.
While this is happening on the database side, the buzz around “Just use PostgreSQL” is becoming increasingly popular. System designers and architects want to reduce the complexity of maintaining multiple components and dealing with operational issues. More complexity implies more potential failures. Recently, Chandan Shukla wrote a blog post titled PostgreSQL as a Workflow Engine: Building Reliable Long-Running AI Jobs Without Kafka, detailing trade-offs and considerations for building a simple yet reliable workflow engine using simple methods.
Yet, critical questions remain:
Yes, we can. Furthermore, when building modern enterprise applications where data arrives as even
[...]On 22 September, the Toulouse PUG met, organized by
Speakers:
On 23 September 2026, the Postgres Meetup Group Valencia met, organized by
Speakers:
On 23 September 2026, the Hamburg PostgreSQL User Group met, organized by Joshua Steinmann and Tobias Alvermann.
Speakers:
On 23 September 2026, the PostgreSQL User Group Vienna met, organized by Cornelia Biacsics and Ranjeet Kumar.
Speakers:
On 24 September 2026, the PostgreSQL Edinburgh Meetup-Group met, organized by Jimmy Angelakos. Daniel Roe delivered a talk.
On 14 September 2026, the Bay Area Postgres Meetup Group met. Organized by Elizabeth Christensen. Elizabeth Christensen and Lukas Fittl delivered a talk.
Since I started building packages separately on each supported RHEL minor version, there has been a repository RPM for each minor version (9.6, 9.7, 9.8, 10.0, ...) in addition to the one for the major versio (9, 10). All of them share the same package name, and the minor version specific ones are also published in the repository of the latest minor version. As a result, dnf update replaced the major version repository RPM with the one of the latest minor version at that time, which then stayed on that minor version forever, even after the OS moved to a newer one.
I just fixed that issue. Please update the repo RPMs at your earliest convenience. Read the details here:
https://yum.postgresql.org/news/repo-rpms-follow-os-minor-version/
Issue detail: https://github.com/pgdg-packaging/pgdg-rpms/issues/215
I'd like to thank Daryl Herzmann for the report, analysis and testing.
Two years ago I compared pg_repack and pg_squeeze, the two extensions most of us reach for when a table has bloated beyond what autovacuum will ever give back and VACUUM FULL isn't an option.
PostgreSQL 19 changes the starting point. REPACK brings VACUUM FULL and CLUSTER together under one command, and REPACK (CONCURRENTLY) does the rewrite online. It needs no extension and no shared_preload_libraries, so it works on managed services too. That will bring online repacking to a much wider audience, so I spent the last few weeks measuring what it actually does to a running database, and how it compares with the two extensions.
Rewriting a table is easy when nobody is using it. VACUUM FULL takes an ACCESS EXCLUSIVE lock, copies the live rows into a new file, rebuilds the indexes and swaps the files. Nobody can read or write the table in the meantime, and on a big table that's minutes or hours.
The online version REPACK (CONCURRENTLY) does the same. Except you can use the table while it's being copied and hence it keeps changing while the process runs. A row copied in the first few seconds can get updated two minutes later. Or deleted. An online repack tool needs to do three things.
REPACK gets the first two steps for free from logical decoding. The mechanism logical replication is using. It starts by creating a temporary replication slot, which gives it a snapshot. Point in time for the initial copy. Because every change that happens during that phase is written to WAL anyway, a background work
The phrase now appears on almost every technology vendor’s website. That’s exactly why it has stopped meaning much.
A database is called AI-ready because it supports vectors. A cloud platform is AI-ready because it offers foundation models. A data platform is AI-ready because it can build a RAG pipeline. An application platform is AI-ready because somebody added a copilot.
These capabilities matter, but none of them answers the harder enterprise question: can the organisation safely turn its existing data, systems, processes and business rules into trusted AI-assisted or autonomous outcomes?
That’s a much higher bar. Think of an organisation with fragmented data, decades of applications, several clouds, conflicting sources of truth, regulatory obligations and a board asking when agents will reach production. For that organisation, “AI-ready” can’t mean starting again with a pristine architecture. It has to mean something more practical:
An organisation is AI-ready when it can introduce increasingly capable AI without losing control of data, authority, outcomes or evidence.
That changes the conversation. The question is no longer simply “Can we run AI?” It becomes a set of harder questions. Where should AI run? What should it know, and what should it be allowed to do? How will we know what happened when something goes wrong? And can the architecture evolve as models, regulations, workloads and business requirements change?
Those are architecture questions.
One of the easiest mistakes in enterprise AI is to start with the model. Which LLM? Do we need an agent? Which vector database? Should we build a knowledge graph? Which orchestration framework becomes the standard?
These are useful questions, but they are rarely the first ones. A better sequence starts with the outcome. What business result are we trying to improve, and what data and context does it require? Which parts of the process should stay deterministic, and where does judg
[...]
TypeSafe opened early access to its Jev model on 15 September 2026, pricing input at $0.042 per million tokens and listing output tokens as free, so at our own estimate of 150 input tokens a support ticket, labelling ten million tickets comes to about $63. Storing those labels in new category and confidence columns is a Postgres backfill on a large table, and when we ran one on a million rows in ten batches, the WHERE clause that picked each batch decided most of what the table paid for it.
Range batches at the default fillfactor, with nothing run between them, took the heap from 269.3 MB to 548.3 MB and nearly doubled the three indexes to 70.1 MB. Only 11.5% of the updates were HOT when we repeated them at fillfactor 90 with a VACUUM after every batch, so the indexes still grew to 64.4 MB. Swapping id between lo and hi for id % 10 = r, and changing nothing else, lifted the HOT share to 96.1% and held the indexes at 36.4 MB against the 35.6 MB they started at. Where range batches wrote 850 MB of WAL, interleaving wrote 455 MB, a lead it kept only until a checkpoint followed every batch and the interleaved run wrote 3 022 MB against 1 025 MB for range batches.
id % 10 batch asks for one row in ten.
id % 10 passes inside one id range before moving to the next kept interleaving's HOT share and wrote 544 MB of WAL with a checkpoint after every range.
ALTER TABLE ... SET (fillfactor = 90) with no rewrite still gave 86.2% HOT on a table loaded at fillfactor 100, and a rewrite by V
You can't read a pg_dump file the way you read a table. To see what is inside, you normally restore it into a PostgreSQL server first.
pg_restore and grep can list the tables without a restore, and even print a table's rows as raw text. They can't filter, sort or join them.
The free PostgreSQL Dump Viewer opens a pg_dump without a server. It replays the dump into a real PostgreSQL inside your browser tab and shows the tables, rows and foreign keys. You can run read-only SQL on it, and the file is never uploaded.
Before restoring a dump, you often need one small answer: is this the right backup, which schemas does it contain, are the rows you need actually there? Starting a server, restoring, waiting and then running one query is sensible for a real recovery. It is too much ceremony for a received backup or a pre-restore check.
Restoring a database puts it back into service; inspecting a dump answers a question about a file.
For inspection, the first things I want are usually the database tree, a table preview, the declared foreign keys, and read-only SQL. If I find what I need, I might export that result as CSV or JSON. If I do not, I have learned that before setting up a server and committing to a restore.
That is why we built the PostgreSQL Dump Viewer. It replays the dump into a real PostgreSQL running inside the browser tab. The file never leaves your computer, and the temporary database is gone when you close the tab.
The result is deliberately narrow: browse schemas and tables, inspect relationships, run read-only PostgreSQL SQL, and export a result. It is not a production restore service.
| PostgreSQL Dump Viewer | Restore into a PostgreSQL se |
|---|
I’m happy to share that I was a guest on the Rails Business podcast and the episode is now live. Here’s a recap of the topics we discussed.
We spent most of the time discussing engineering work last year related to scaling the database workload for peak traffic at Aura where we use Ruby on Rails and PostgreSQL.
I’m presenting this information in two places this fall, Rails at Scale Summit in Austin, TX, and the Postgres Summit in NYC.
Besides the podcast, you can get more details in these posts:
If you’re not able to make those events or prefer to listen to a discussion of the content, then the podcast will have a lot of the same information.
Besides the work at Aura, we also checked in on my book High Performance PostgreSQL for Rails, which has now been available in print for two years. Ryan asked about what’s next for the book, and it’s a difficult question to answer.
With the availability and quality of AI tooling for software engineers, I don’t see developers buying books as much. With fewer prospective readers, the ROI is less attractive for authors and publishers to commit to the resource-intensive process of creating a book.
I’m grateful to have had the opportunity to write a book before the rise of the AI tools. I’m still getting positive feedback from my book which is very fulfilling.
Recently I met Madison Sites who’s a reader, and they shared feedback that they’re reading the book as part of the WNB.rb book club. Madison said the book has been helpful for building vocabulary and familiarity with database concepts and implementation details, and that’s helped with database work and better comprehension for conference talks about similar topics. I appreciated hearing about that!
We segued into how we
[...]
With PGConf.dev 2027 now on the horizon, I found myself thinking back to PGConf.dev 2026 and all the moments that stayed with me.
What started with two accepted talk submissions for the Community Day at PGConf.dev 2026 turned into four days filled with community discussions, anniversary celebrations, hallway conversations, poster sessions, unconference discussions, and countless opportunities to meet the people behind PostgreSQL.
Some moments made me think. Some made me laugh. Others reminded me why I enjoy contributing to this community so much.
Between my first PGConf.dev, my recent transition to Microsoft, two accepted talks, a community coin I didn’t expect, and a brief moment of wondering whether I belonged, this conference turned out to be far more memorable than I anticipated.
Some moments stayed with me...
PGConf.dev 2026 took place in Vancouver, Canada. I decided to arrive a few days early, for several reasons:
I have attended many PostgreSQL conferences in Europe over the years, and one thing I always enjoy is seeing how every event develops its own personality.
PGConf.dev immediately felt different.
PGConf.dev (2024–2026), formerly known as PGCon (2007–2023), it is a conference for people who actively build PostgreSQL. And when I say build PostgreSQL, I do not only mean writing code.
PGConf.dev brings together: PostgreSQL committers and code contributors, Documentation writers, Infrastructure maintainers, Meetup organizers, Community o
[...]Number of posts in the past two months
Number of posts in the past two months
Get in touch with the Planet PostgreSQL administrators at planet at postgresql.org.