In Part 6 of this special Postgres in Production deep dive series, Ryan Booz asks a question that determines how useful pg_stat_statements can be for you at all: do you have a high cardinality workload? This episode covers what that actually means, why ORMs, dynamic SQL, and AI-assisted development tools generate more unique queries than you might expect, a side by side demo of the same workload on Postgres 17 and Postgres 18, and the concrete checks that tell you whether pg_stat_statements is losing the data you need for query tuning.
Share this episode: Click here to share this episode on LinkedIn. Feel free to sign up for our newsletter and subscribe to our YouTube channel.
Transcript
Over the first five episodes we covered what pg_stat_statements is and the metrics it stores (Part 1), what makes a statement “unique” through normalization (Part 2), where the query texts live on disk (Part 3), how new metrics get stored and old ones get deallocated (Part 4), and the configuration settings that control all of it (Part 5).
Through all of that, I have probably mentioned the pg_stat_statements.max setting at least 100 times, because it’s so crucial to understanding how effective the data is that you have. This episode is about the workloads that consistently outrun that setting, and being able to identify whether you’re in that situation is really helpful to determining if pg_stat_statements can help you do the query tuning and optimization that you need it to.
My previous article talked about the checkpoint happiness hint: You probably should not change the checkpoint_timeout setting from its default of 5 minutes.
A good follow-up question was raised: can an HA replica can save you from downtime if you want to set a large checkpoint_timeout?
It’s true that Postgres allows promoting a replica without restarting, if there’s an unplanned primary restart and your primary is going to take an hour to come back online (after you increased checkpoint_timeout to 45 minutes). But this glosses over the fact that if the replica experiences a restart, then it will take an hour to start up too. Checkpoints on the primary directly translate into restartpoints on the replica (it’s the same WAL stream).
First case: everything is manually managed by a DBA and there’s little automation. Bugs in the tooling are a risk, but the biggest risk here is human error. As we often say in COE’s: people make mistakes. Hoping they won’t make a mistake is not a realistic plan for a reliable platform.
Second case: postgres is increasingly automated and we need to be careful that our automation doesn’t accidentally restart a replica while we’re promoting it.
Even with automation, common Postgres orchestration kits heavily rely on “the DBA knows how to configure it” (ie. you still can’t trust all of the defaults). One example: PG configuration changes require rolling restarts. Is the default behavior of common orchestration frameworks to continue a rolling restart even if the first node never comes back up? Are we back to the first case of relying on the DBAs to know the specific incantation of special commands they need to run, to ensure they never accidentally end up restarting both nodes? If the rolling restart can’t complete, will the DBA know how to address it without accidentally triggering a restart in any way?
And what if a query is triggering a postgres bug which causes a restart – like consuming enough memory to trigger OOM? This is r
[...]There is no shortage of PostgreSQL operators for Kubernetes. Projects such as CloudNativePG, the Zalando postgres-operator, Crunchy PGO, and StackGres have all helped shape the ecosystem.
Our answer is simple: multi-site PostgreSQL along with other capabilities.
The CYBERTEC PG Operator delivers the PostgreSQL lifecycle management expected from a Kubernetes operator, while placing a strong focus on operating PostgreSQL across multiple Kubernetes locations through Multi-site Clusters.
From cross-site replication and automated failover to validated deployment models, architecture guidance, and operational documentation, Multi-site Clusters were developed to address challenges that arise when PostgreSQL extends beyond a single Kubernetes environment.
The CYBERTEC PG Operator is open source, built on proven PostgreSQL technologies, and backed by CYBERTEC's PostgreSQL expertise.
We are excited to share the project with the community and look forward to your feedback and contributions.
Explore the source here: https://github.com/cybertec-postgresql/CYBERTEC-pg-operator
The post Introducing the CYBERTEC PG Operator appeared first on CYBERTEC PostgreSQL | Services & Support.
Formatting SQL tends to bring some of the same questions again and again: should we uppercase clause keywords? should we put the separating comma at the start of a line to ease refactoring? how to align the SQL clauses with one-another?
Over the years I have grown my own SQL style and didn’t find tooling that would implement it. Also, I’ve been asked here and there if there is a tool that would replicate The Art of PostgreSQL SQL indentation style… and now there is finally a good answer to that question!
sqlfmt is a gofmt-style formatter that implements my own favorite SQL indentation style. One opinionated style, no configuration knobs. Run it, commit the result, move on.
You have probably read a dozen tutorials on setting up PostgreSQL High Availability (HA). On paper, it looks simple: spin up a primary instance, spin up a standby, and let them replicate.
But what happens when you move to a multi-region architecture? What happens when your disaster recovery (DR) backup utility (like pgBackRest) strictly demands secure TLS (HTTPS) endpoints, but configuring native SSL on local storage/MinIO is an administrative nightmare? More importantly, when disaster strikes and you fail over to your DR region, how do you successfully fail back to your original primary region without running into timeline conflicts, operator deadlocks, or S3 archive poisoning?
This comprehensive guide takes you through the entire lifecycle—from the initial secure bootstrap to simulated regional failure, active failover, and the highly complex process of reversing roles (failback) using the Crunchy PostgreSQL Operator (PGO) on Kubernetes and MinIO as the secure WAL repository.
pgBackRest is extremely strict: it expects secure S3 endpoints over HTTPS. However, setting up native TLS directly on a local MinIO deployment is often over-engineered and tedious.
We solve this by deploying a lightweight NGINX Reverse Proxy in our minio namespace. This proxy terminates SSL/TLS on port 443 using a self-signed certificate and cleanly forwards plain HTTP traffic to MinIO on port 9000.
Generate a certificate valid for the proxy's in-cluster DNS name ( minio-secure.minio.svc.cluster.local):
# Generate the private key and self-signed certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=minio-secure.minio.svc.cluster.local" \
-addext "subjectAltName = DNS:minio-secure.minio.svc.cluster.local"
# Save the TLS certificate inside the minio namespace
kubectl create secret tls minio-secure-tls \
--key tls.key \
--cert tls.crt \
-n minThe PostGIS Team is pleased to release PostGIS 3.7.0beta2! Best Served with PostgreSQL 19 Beta2 and GEOS 3.15.0beta2.
This version requires PostgreSQL 14 - 19beta2, GEOS 3.10 or higher, and Proj 6.1+. To take advantage of all features, GEOS 3.15+ is needed. To take advantage of all SFCGAL features SFCGAL 2.3.0+ is needed.
This release contains fixes and enhancements since 3.7.0beta1 release.
Cheat Sheets:
This release is a beta of a major release, it includes bug fixes since PostGIS 3.6.4 and new features.
Enterprise AI doesn’t fail because strategy was wrong. Or because the platform wasn’t ready. Or because the execution layer broke.
It fails because organizations treat those as three different conversations — run by three different teams, on three different timelines — instead of what they actually are: three altitudes of the same question.
That question is simple to state and hard to answer: what does it take to build AI systems that organizations can actually trust in production?
Over the past several months, I’ve written about three frameworks that each answer part of it — OWNS, CALM, and ORBIT. Read individually, they can look like three different discussions: one about platform strategy, one about architectural readiness, one about engineering execution. They are not three discussions. They are three layers of one answer, and none of them is complete without the other two.
Every successful enterprise AI initiative I’ve seen eventually reaches the same realization. The first question isn’t technical. The second isn’t about models. The third isn’t even about AI. It starts with choosing the right strategic direction. Then preparing the platform to support it. Only then does reliable execution become possible. That’s why these three frameworks emerged in this order — not as three independent topics, but as a sequence, each one a precondition for the next.
It’s tempting to want a single checklist for “is our AI trustworthy” — one framework, one score, one green light. That temptation is understandable and it’s also the wrong instinct, because the question changes shape depending on who’s asking it and when — and in most organizations, the three questions are often owned by three different teams.
A board member evaluating a platform decision isn’t asking the same question as an architect assessing whether that platform is ready for production AI, and neither of them is asking the same question as an engineer trying to make sure
[...]Before diving into this final post covering new Postgres 19 features, I just want to say it's been a wild ride. Postgres 19 has been a veritable treasure trove of enhancements, perhaps more than any previous release; or maybe that's just my perception. Usually I just skim through the release notes and nod along, sometimes jotting down things that look interesting for later study. Maybe calling out each element that caught my eye was the right thing to do, to really show how far Postgres has come since the last release, rather than simply accepting the status quo. It's easy to miss an otherwise innocuous one-liner in a changelog.In any case, every major Postgres release ships with a marquee feature or two, and I've covered several of them in this series on Postgres 19. Some will garner dedicated conference talks or a flurry of frantic blogs from equally zealous authors. The big-ticket items always get their time in the spotlight. But I'm not here to talk about that this week. Like the last article on a handful of unassuming new function calls, this week will focus on some syntax tweaks that may never really trend anywhere—the lost and unsung.Why dedicate a whole article to syntactic sugar? Why fuss over features that, taken one at a time, save maybe four lines of SQL apiece? Because four lines of SQL, multiplied across every project we'll ever touch, becomes a veritable mountain of saved aggravation. Postgres 19 happens to bring a whole potpourri of these, and a few of them scratch itches I didn't even know I had.Let's wander through my notes and see what turned up.
The Talk Selection Committee of PGConf.EU 2026 met to finalize the conference schedule:
On 22 July 2026, the PostgreSQL Down Under Meetup met, organized by David Micallef. Gabriele Bartolini delivered a talk.
On 22 July 2026, the Adelaide PostgreSQL User Group met, organized by Robins Tharakan.
Speakers:
On 22 July , 2026 the Sydney PostgreSQL User Group met, organized by:
Speakers:
Multi-media contributions
(2026-08-06 17:44:32) postgres=# \luacode Enter code to be copied followed by a newline. End with a backslash and a period on a line by itself, or an EOF signal. >> function x(n) >> return n + 10 >> end >> \. (2026-08-06 17:45:32) postgres=# \luacode Enter code to be copied followed by a newline. End with a backslash and a period on a line by itself, or an EOF signal. >> print (x(10)) >> \. 20
The most dangerous AI decision isn’t the wrong one. It’s the one nobody can explain afterward.
Most conversations about AI reliability start in the wrong place. They start with the model — its accuracy, its reasoning quality, its benchmark scores — as if reliability were something a better model eventually solves. It isn’t. A model can retrieve the right documents, reason correctly, and select the right action, and the system built around it can still fail in ways that have nothing to do with intelligence at all. A network times out. A worker restarts mid-task. A message arrives twice. A process crashes after changing state but before recording that it did.
None of these are model problems. They are execution problems — the same problems distributed systems have wrestled with for decades, now arriving at the doorstep of AI because agentic systems finally do enough real-world work for the failure modes to matter.
That’s why I believe the next decade of AI engineering will look increasingly like the last two decades of distributed systems engineering. The novelty won’t be in handling model responses. It will be in making those responses durable, coordinated, recoverable, and accountable inside production systems.
This is the premise behind ORBIT: an execution discipline for AI systems that retrieve, reason, and act. Five principles — Outbox First, Rate & Shared State, Background Is the Unit of Execution, Idempotency from Day One, and Trace Everything — that don’t ask whether a model reasoned well. They ask whether the system around it can be trusted to execute what the model decided, survive the failures that will inevitably occur, and be understood afterward by the humans accountable for what happened.
A demo proves that an AI system can reason. Production has to prove something harder: that the entire workflow can recover when networks fail, services restart, mes
[...]PostgreSQL is already the default database for agentic AI. That question is settled. But the more agentic your workloads get, the more your database needs to do. Models and workflows flood it with signals, state, memory, and checkpoints, and most teams just absorb the flood, treating PostgreSQL like a parking lot rather than a compute layer. The people building these systems are AI engineers, not database people. They haven't explored what PostgreSQL can actually do when you treat it as a first-class compute citizen. Production agentic AI creates workload patterns that look nothing like anything most teams have operated before. Agents write intermediate results, update shared state, run concurrent multi-step workflows against the same tables, and do all of this without coordinating with each other. Your chatbot is pulling RAG context from a table that a data-cleaning agent is actively updating, while a forecasting agent parks half-finished calculations in a scratch table that three other processes read from.The demos look great, but the architecture decisions at the database layer determine whether your agents run reliably at scale or whether you spend Monday mornings untangling a mess that autonomous processes made over the weekend.
Chat-with-your-data is where most teams start. A user asks a question in natural language, the database runs a similarity search against stored vectors, retrieves relevant context, and feeds it back to the model for a g[...]
CloudNativePG lets the ClusterImageCatalog carry extension images alongside the operand, a capability every currently supported release already has, so a Cluster manifest only needs to name an extension and nothing else. This recipe deploys the community’s extension catalog and shows the operator resolving pgvector’s image, paths and dependencies from a single, versioned source of truth per PostgreSQL major version. More importantly, it is the piece of infrastructure that turns extension distribution into a real ecosystem: once an extension lands in the catalog, every Cluster that references it inherits it for free, with no manifest ever needing to change again.
What I learned after moving from conference volunteer duty to the other side of the Call for Papers.
Disclosure: This is my personal account of the experience, based on the publicly documented PostgreSQL Europe selection process and aggregate statistical analysis. I am intentionally not discussing individual proposals, speakers, scores, committee comments, private conversations, or confidential data.
I cannot say with certainty why I was invited. My best guess is pleasantly unromantic: an invitation to apply was sent to previous conference volunteers, and I had volunteered at several recent PGConfEU events. I applied, and apparently nobody found a sufficiently alarming reason to reject me.
Topic groups were created for this post-selection analysis (for this blog only) from the primary subject of each proposal; they are not official PGConf.EU categories.
The review scope
The PGConf.EU 2026 CFP contained 407 submissions from 228 distinct speakers. I read and voted on every one of them, although my votes were needed only in the two tracks assigned to me:
Application Developer
Community
That arrangement made sense. Reading the full submission pool gave me context across the CFP, while having two assigned tracks allowed me to examine those proposals in much greater depth.
My review process usually began with the abstract. I then checked the CFP notes for supporting material such as code, slides, recordings, or a related blog post. When none was provided, I searched previous PostgreSQL conferences, PGdays, and meetups to see whether the talk or an earlier version of it had already been presented. There are enough PostgreSQL events during the year that this occasionally felt less like reviewing and more like conference archaeology.
Here is a query that shows up in every analytics workload:
SELECT count(DISTINCT user_id) FROM events;
It looks like the cheapest possible thing: count the distinct users. On a machine with cores to spare you would expect Postgres to throw a few parallel workers at it, the way it does for almost any large scan. It does not. That one keyword, DISTINCT, switches off parallel query for the entire statement, and the larger your table the more it costs you. No setting or index changes that; the reason is in how the aggregate has to execute.
Ten million events, about fifty thousand distinct users, a handful of countries. Nothing unusual.
CREATE TABLE events (
id bigint GENERATED ALWAYS AS IDENTITY,
user_id int NOT NULL,
country text NOT NULL,
amount numeric(10,2) NOT NULL
);
INSERT INTO events (user_id, country, amount)
SELECT (random()*50000)::int + 1,
(ARRAY['US','DE','GB','FR','JP','BR','IN','CA'])[(random()*7)::int + 1],
(random()*500)::numeric(10,2)
FROM generate_series(1, 10000000);
ANALYZE events;
max_parallel_workers_per_gather is at its default of 2 on fresh cluster. For these examples I raised it to 4 and work_mem to 64MB, so there's no resource starvation to blame for the plans below.
Start with a plain count(*), which has nothing to deduplicate:
EXPLAIN (ANALYZE, COSTS OFF) SELECT count(*) FROM events;
Finalize Aggregate (actual rows=1.00 loops=1)
-> Gather (actual rows=5.00 loops=1)
Workers Planned: 4
Workers Launched: 4
-> Partial Aggregate (actual rows=1.00 loops=5)
-> Parallel Seq Scan on events (actual rows=2000000.00 loops=5)
Four workers plus the leader (loops=5) each scan their slice and keep a running count, and the leader adds the five partial counts together at the end.
Now add one word:
EXPLAIN (ANALYZE, COSTS OFF, BUFFERS) SELECT count(DISTINCT user_id) FROM events;
Aggregate (actual rows=1.00 loops=1)
Buffers: shared hit=[...]
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.