Latest Blog Posts

pg_statviz 1.2 released with PostgreSQL 19 support and new features
Posted by Jimmy Angelakos on 2026-08-20 at 18:00

pg_statviz new logo, with a blocking locks chart from the new module

Just in time for the PostgreSQL 19 betas, I'm excited to announce release 1.2 of pg_statviz, the minimalist extension and utility pair for time series analysis and visualization of PostgreSQL internal statistics.

This release adds support for the upcoming PostgreSQL 19:

  • pg_statviz now captures the new wal_fpi_bytes counter from pg_stat_wal.
  • The PG18/19 I/O worker, effective WAL level, and autovacuum scoring settings are captured in snapshot_conf.
  • The release has been tested against 19 beta3, and across the whole PostgreSQL 13 to 19 range.

It also introduces a new blocking locks analysis module:

  • Each snapshot now records the number of blocked and blocking sessions, along with a breakdown by lock type (relation, transactionid, tuple, and so on).
  • Detection is built on pg_blocking_pids(), so even soft blocks (sessions that are just ahead in the lock wait queue) are counted, not just hard conflicts.
  • Storage stays lightweight: table size is independent of how many sessions were involved in the blocking.
  • The module produces charts and AI verdicts like every other module, and the deterministic severity floor applies here too: sustained blocking can never be reported as healthy.

Blocking locks by type

Blocking locks by type, as captured by the new blocking module (click to enlarge).

Also new is the openai AI provider:

  • --ai openai uses the OpenAI API, so the same flag works with OpenAI itself and with any other service or local server that implements that API.
  • You can select the endpoint and model with the OPENAI_BASE_URL and OPENAI_MODEL environment variables.
  • The openai package has been added to the [ai] extras, and zero-dependency installs remain unchange

Finally, this release also updates the default AI models to claude-sonnet-5 for Claude and gemini-3.7-flash for Gemini.

pg_statviz takes the view that everything should be light and minimal. Unlike commercial monitoring platforms, it doesn't require invasive agents or open connections to th

[...]

Do Global Hash Tables Strike Back in PostgreSQL?
Posted by Andrei Lepikhov in pgEdge on 2026-08-20 at 17:50

In this article written for experienced PostgreSQL engineers and core developers, I want to describe how we tested one hypothesis — whether a shared hash table can be used to speed up parallel aggregation by hashing. A recent paper claims that the shared hash table is an unfairly dismissed way of doing parallel aggregation, and that the key to success is moving the group lookup out from under the lock. We considered the idea of shared parallel aggregate, brought it to a working patch set for PostgreSQL, and ran measurements on a many-core instance in Google Cloud.

  1. Does the hypothesis hold in PostgreSQL — and if it does, how exactly.
  2. What we pay for it.
  3. Is contention on LWLock really the only bottleneck?
  4. Can this approach be reused to speed up other operations in a query plan?
The short answer to the third question: no, it is not the only one. The lookup under the lock is the biggest of the problems, and it can be removed. Underneath it we found at least three more issues (two of which are invisible in the paper), because it is written about an engine with threads rather than processes.

The starting point

From time to time I get reports from PostgreSQL users complaining that a query which looks quite simple takes a very long time. in such a case looks roughly like this:Here we see an ordinary table scan and an aggregate over the result. The scan takes a negligible amount of time (250 ms), the partial aggregate fits into four seconds, delivers rows by the sixth — and after that, about 18 of the 25 seconds are eaten by , which runs in a single process. Everything happens in memory, so spilling has nothing to do with it. The aggregation is done by hashing, so no hidden sorts are expected either.Part of the reason is visible right here: 3 million rows on the input, almost 600 thousand groups on the output. Five rows per group means that the partial aggregation barely compresses the data stream, the hash table grows fat both in the workers and in the leader, and about 2.44 million partial st[...]

Hackorum Update: What's New Since February
Posted by Kai Wagner in Percona on 2026-08-20 at 10:00

Back in February, I wrote about Hackorum, a forum style web view of the pg-hackers mailing list. If you missed that post, you can read it here first. It turns the mailing list into something that reads and navigates a bit more like a modern forum, while the mailing list itself stays the source of truth.

Hackorum topic index showing pg-hackers threads with commitfest, patch and CI status icons

Contributions for week 31 & 32
Posted by Cornelia Biacsics in postgres-contrib.org on 2026-08-20 at 07:51

On 6 August, the Postgres Summit US 2026 Program Committee met to finalize the schedule:

  • Chelsea Dole
  • Jonathan Hinds
  • Jonathan Katz

On 11 August, the San Francisco Bay Area PostgreSQL Meetup Group, organized by Katharine Saar, Stacey Haysler and Christophe Pettus. Kalyani Madipadiga and Stacey Haysler delivered a talk.

On 12 August, the Program Committee of PGConf.PL finished the talk selection:

  • Andreas Scherbaum (non-voting chair)
  • Adam Wołk
  • Hubert "depesz" Lubaczewski
  • Svitlana Lytvynenko

On 13 August, the PostgreSQL Edinburgh Meetup Group met, organized by Jimmy Angelakos. Torsten Förtsch and Paolo Guagliardo delivered a talk.

Claire Giordano and Aaron Wislang hosted and published a new podcast episode on 14 August, 2026 “How AI is changing software development with Simon Willison” from the Talking Postgres series.

Community Blog Posts:

Welcome to pg_shmemviz: PostgreSQL shared memory visualizer
Posted by Bertrand Drouvot on 2026-08-20 at 01:00

Introduction

The purpose of this blog post is to introduce pg_shmemviz, a new tool to visualize PostgreSQL shared memory.

It follows the same approach as pg_walviz, bringing physical layout and byte level navigation to PostgreSQL shared memory instead of WAL segments.

Views such as pg_shmem_allocations, pg_buffercache and pg_shmem_allocations_numa are useful to inspect selected aspects of shared memory. However, sometimes we also want to see where allocations are physically located, which C structures they contain, their exact fields and padding, the regions reached through pointers and the corresponding raw bytes.

Welcome to pg_shmemviz

pg_shmemviz is a development and debugging tool that captures PostgreSQL’s main and dynamic shared memory segments into an offline snapshot and displays them in a local browser.

The interface combines a shared memory map, an allocation table, a structure inspector and a Physical Bytes view. They are synchronized: selecting an allocation, structure field or byte updates the other views. Pointer and history navigation can also cross captured segments.

As a picture is worth a thousand words, let’s have a look at it:

pg_shmemviz overview

Shared memory overview

pg_shmemviz shared memory overview

The map displays named allocations, allocator padding and unused ranges. Main shared memory, DSM control, DSM and DSA segments can be selected independently. One can filter the allocation table, select an allocation or zoom into a physical range.

Structure Fields and padding

pg_shmemviz Structure Fields and padding

The Structure Fields panel uses DWARF from the exact postgres executable to display nested C structures, field offsets, values, compiler padding and array stride padding.

Pointer targets with known bounds appear as referenced regions. Selecting one highlights its source pointer and opens the target bytes. Specialized discovery covers PostgreSQL statistics, WAL, process, SLRU, dynahash and DSM registry structures.

Physical Bytes

pg_shmemviz Physical Bytes

The Physical Bytes panel displays bounded byte windows classified by stru

[...]

All Your GUCs in a Row: krb_caseins_users and krb_server_keyfile
Posted by Christophe Pettus in pgExperts on 2026-08-20 at 01:00
PostgreSQL's GSSAPI authentication relies on two server-wide settings: `krb_server_keyfile` points to a dedicated keytab file (never share the system one), and…

Reliable HubSpot Sync with a Transactional Outbox and QStash
Posted by uzair aslam on 2026-08-19 at 22:07

A database vault sends durable events through a queue, idempotent worker, rate-control gate, retry loop, and observability dashboard

Build a retry-safe HubSpot synchronization pipeline with atomic outbox events, signed QStash workers, call-level rate control, reconciliation, and Sentry.

A reliable HubSpot integration has to survive the worst possible success: HubSpot commits the change, but the worker loses the response before recording it. Retrying may repeat the call; refusing to retry may leave the local event unresolved. That ambiguity is why queues alone are not enough. The database, publisher, worker, and remote mutation all need explicit identities and recoverable state.

This is the delivery layer for the 40-site architecture and its versioned brand-routing plan. The application first accepts a desired state locally; this pipeline makes HubSpot converge on it without blocking the visitor.

Eliminate the database-and-queue dual write

Writing the subscription to PostgreSQL and then publishing to QStash creates two independent writes. If the process crashes between them, the subscription exists but no worker is scheduled. Publishing first has the opposite failure: the worker can observe an event whose business transaction later rolls back.

The transactional outbox pattern puts the desired subscription change and an immutable event in the same database transaction. A separate dispatcher publishes committed outbox rows. The dispatcher is allowed to publish more than once because the worker is idempotent.

Subscription and outbox schema
CREATE TABLE subscription_requests (
  id uuid PRIMARY KEY,
  brand_id text NOT NULL REFERENCES brands(id),
  contact_key text NOT NULL,
  product_id text NOT NULL,
  desired_state text NOT NULL CHECK (desired_state IN ('subscribed', 'unsubscribed')),
  mapping_version integer NOT NULL,
  idempotency_key text NOT NULL,
  request_hash text NO
[...]

Modeling Multi-Brand Subscription Routing in HubSpot
Posted by uzair aslam on 2026-08-19 at 22:07

Multiple brand sources enter a central routing matrix and fan out into communication, segment, property, and analytics destinations

A data-driven model for mapping websites and brands to HubSpot subscription types, Brands IDs, segments, contact properties, and analytics destinations.

When brand A means six HubSpot segments, one communication subscription type, one HubSpot Brand ID, and several attribution properties, the mapping is part of the product. Hiding those IDs in conditionals turns every new website, campaign, and reorganization into a deployment—and makes it difficult to explain why a contact landed where they did.

This article expands the configuration layer introduced in the 40-site HubSpot architecture. The goal is to let every website express business intent while one versioned model resolves that intent into HubSpot targets.

Use one internal brand identity

Start with a stable internal brand key such as brand_a. Map every accepted hostname and form to that key. Do not use the hostname itself as the business identity: domains change, several domains can represent one brand, preview hosts must be rejected, and a single site can expose more than one subscription product.

Core routing tables
CREATE TABLE brands (
  id text PRIMARY KEY,
  name text NOT NULL,
  hubspot_business_unit_id bigint,
  active boolean NOT NULL DEFAULT true,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE brand_hosts (
  hostname text PRIMARY KEY,
  brand_id text NOT NULL REFERENCES brands(id),
  environment text NOT NULL CHECK (environment IN ('production', 'preview')),
  accepts_subscriptions boolean NOT NULL DEFAULT false
);

CREATE TABLE subscription_products (
  id text PRIMARY KEY,
  name text NOT NULL,
  channel text NOT NULL DEFAULT 'EMAIL',
  active boolean NOT NULL DEFAULT true
);

CREATE TABLE brand_subscription_routes (
  brand_id text NOT NU
[...]

Every AI Agent May Need PostgreSQL. Not Every Agent Should Own the Truth.
Posted by Vibhor Kumar on 2026-08-19 at 05:06

Databricks’ acquisition of Electric is noteworthy for several reasons. Electric developed PGlite, a WebAssembly build of PostgreSQL that can run inside a browser, application, serverless environment, or AI agent sandbox. It also developed synchronization technology intended to connect these distributed environments with a central PostgreSQL system.

The speed of adoption is striking. PGlite grew from one million to 13 million weekly downloads in approximately 12 months. The project began with foundational PostgreSQL-to-WASM work by Neon co-founder Stas Kelvich, which Electric subsequently turned into an embeddable database used across development tools, testing frameworks, browser sandboxes, and AI applications. (Neon announcement)

That is impressive execution. But the more important story is not the acquisition.

It is the new architectural role emerging for PostgreSQL.

For most of its history, PostgreSQL has been deployed as a server. Applications connect to it across a network, execute transactions, and depend on it as a durable system of record. PGlite introduces another possibility: PostgreSQL can run inside the application—or even inside the agent itself.

That brings the database closer to the agent’s execution loop and removes a network round trip from operations involving local context. But it also raises a much harder question:

If every agent has a database, which database owns the truth?

Why agents create a different state problem

Traditional applications generally have known execution paths. Their queries are designed in advance, their data-access patterns can be tested, and their infrastructure is relatively stable.

Agents behave differently.

An agent may decide at runtime which information it needs, which tools to invoke, and which intermediate results to retain. It may retrieve documents, generate embeddings, create a plan, call external systems, revise its assumptions, and coordinate with other agents.

All of that activity produces state.

Some s

[...]

All Your GUCs in a Row: join_collapse_limit
Posted by Christophe Pettus in pgExperts on 2026-08-19 at 01:00
PostgreSQL famously does not implement query hints. This is about 95% true, and join_collapse_limit is the other 5%: set it to 1, and the planner joins your tables in exactly the order you wrote them. This is not an exploit or an accident of implementation; it is documented, and according to Tom …

Why Postgres Breaks Kubernetes container_memory_working_set_bytes Metric
Posted by Jeremy Schneider on 2026-08-18 at 23:28

Kubernetes metric container_memory_working_set_bytes is used for evicting/killing pods with too much memory use, especially if request < limit (don’t do this with Postgres). The metric is calculated from cgroups v2 memory.stat metrics as current-inactive_file [source].

You’d assume it’s a good metric for memory usage in kubernetes. But with Postgres, this metric is very inaccurate for memory utilization and doesn’t tell you at all if you’re going to OOM crash your database.

After having the same conversation so many times about Postgres on Kubernetes, I need to write it down so I can just send people here to read it.

I will show better metrics to watch.

We start with fundamentals.

Note: scripts to reproduce all tests and graphs are at https://github.com/ardentperf/cgroup-postgres-memtest

Kubernetes Node E2E Tests

This is ground-zero for what Kubernetes promises to be true. AI research is telling me make test-e2e-node has several memory-pressure eviction tests:

  • MemoryAllocatableEviction [source]
  • MemoryAllocatableEvictionPodLevelResources [source]
  • PriorityMemoryEvictionOrdering [source]
  • PriorityMemoryEvictionOrderingPodLevelResources [source]

I believe these tests all use a test kit called agnhost [source]. Lets fire it up in docker and grab a few cgroup v2 metrics

docker run --name graph-repro-run_1-1821100 \
    --memory 512m --memory-swap 512m --detach \
    registry.k8s.io/e2e-test-images/agnhost:2.47 \
    stress --mem-alloc-size 25Mi --mem-alloc-sleep 5s --mem-total 1Gi

container_memory_working_set_bytes is the yellow line: current-inactive_file. It tells current memory usage, excluding linux page cache contents on the “active” file LRUs. The blue line is my own metric, where I’ve excluded all LRUs (both active and inactive) – basically I’m saying “memory usage not including the page cache”.

Looking at the graph:

Anonymous memory ramp-up. As expected, OOM when memory usage hits the cgroup max (aka Pod Memory Limit). If you’re taki

[...]

Postgres 19: How Our Advice Has Changed Since We Wrote It
Posted by Christopher Winslett in Crunchy Data on 2026-08-18 at 19:00

Over the years we have written a lot about how data gets into Postgres, how it sits on disk, and how indexes help you find it again. Some of that advice was written against Postgres 10 or 11. A surprising amount of it is still exactly what we would tell you for the upcoming Postgres 19 release. Functionality described here is based on current betas; minor details may still change before GA.

This post revisits Crunchy posts in the “load, storage, indexes, and partitioning” bucket: what we wrote, which version moved the needle, and what we would tell you to do now. Along the way: async I/O, more resilient COPY, LZ4 by default, richer BRIN shapes, skip scan, and smoother partition operations.

Async I/O: faster scans and vacuum on modern storage

In 2019 we benchmarked a BRIN index against a B-tree and a parallel sequential scan on the same time-series table. Sometimes BRIN won. Sometimes the parallel seq scan won: four workers chewing through the heap beat a clever index. That was the right lesson for Postgres 11: indexes are a tradeoff against what the executor can already do in parallel.

Postgres 18 made those heap reads substantially faster.

Async I/O lets backends queue multiple disk reads instead of waiting on each one. Sequential scans, bitmap heap scans (the path BRIN and many bitmap index plans finish with), and vacuum all benefit. Community benchmarks have shown up to ~3× on cold, latency-bound storage, a big deal for cloud disks. Defaults matter here: io_method = worker is on out of the box; on Linux 5.1+ you can try io_method = io_uring. See Get Excited About Postgres 18 for the operator view.

Postgres 19 builds on that: I/O workers can autoscale (io_min_workers / io_max_workers), read-ahead scheduling improved, and EXPLAIN (ANALYZE, IO) can show what the async subsystem is doing. Parallel query is still there; each worker can queue several reads and keep making progress while some of them are still in flight, so you get more useful work between waits. Parallel autovacuum workers

[...]

PgColumnar 1.0Alpha2 released
Posted by Joshua Drake in CommandPrompt on 2026-08-18 at 16:08
Release date: 2026-08-18Previous release: 1.0-alpha (2026-08-04)GithubChangelogpgColumnar is a columnar table access method for PostgreSQL. This is the second alpha. It adds read-only Apache Iceberg support, reads and writes over S3-compatible object storage, a maintenance daemon, and a broad round of statistics, planner, performance, and security work. The on-disk native format (PGCN v1) is unchanged; existing tables are read and written as before.

Introducing YeSQL: Practical PostgreSQL, One Concept at a Time
Posted by Dimitri Fontaine on 2026-08-18 at 08:00

I’m happy to share something new: YeSQL is live, a free set of 24 short PostgreSQL lessons — one concept, one runnable query, real data, no signup. It’s free to use today, and it’s also a prototype for something I’ve wanted to build for a while: making every query in The Art of PostgreSQL runnable, right on the page.

Highly Available PostgreSQL on Kubernetes in 10 Minutes
Posted by Hans-Juergen Schoenig in Cybertec on 2026-08-18 at 05:07

"Highly available PostgreSQL" usually means leader election, streaming replicas, automatic failover, health checks, and a lot of careful wiring. With the CYBERTEC PG Operator (CPO) it means a 14-line YAML file. Here's the whole thing, start to finish, on a laptop with minikube.

Every command and output below comes from a tutorial we ran end-to-end on a fresh minikube(Kubernetes 1.30, CPO 0.9.2, PostgreSQL 18.4).

A cluster and an operator

minikube start -p cpo-deploy --driver=docker --cpus=2 --memory=4096

helm repo add cpo https://cybertec-postgresql.github.io/CYBERTEC-operator-tutorials
helm repo update cpo
kubectl create namespace cpo
helm install cpo cpo/postgres-operator -n cpo --version 0.9.2 \
  --set configKubernetes.enable_pod_antiaffinity=false
kubectl -n cpo rollout status deploy/postgres-operator

One information worth knowing: enable_pod_antiaffinity=false flag. By default the operator spreads replicas across different Kubernetes nodes, exactly what you want in production. But minikube is a single node, so without this flag the replica would sit Pending forever. On a real multi-node cluster, leave anti-affinity on.

Describe the database you want

kubectl -n cpo apply -f - <<'EOF'
apiVersion: cpo.opensource.cybertec.at/v1
kind: postgresql
metadata:
  name: pg-cluster
spec:
  dockerImage: 'containers.cybertec.at/cybertec-pg-container/postgres:rocky9-18.4-1'
  numberOfInstances: 2
  postgresql:
    version: '18'
  resources:
    requests: { cpu: 250m, memory: 1Gi }
    limits:   { cpu: '1',  memory: 1Gi }
  teamId: acid
  volume:
    size: 1Gi
EOF

numberOfInstances: 2 is the whole HA story: one leader, one streaming replica. Wait for them:

bash
kubectl -n cpo wait --for=condition=Ready pod \
  -l cluster.cpo.opensource.cybertec.at/name=pg-cluster --timeout=360s
# pod/pg-cluster-0 condition met
# pod/pg-cluster-1 condition met

The "it's actually HA" moment

Ask Patroni, which runs inside every database pod, and what it sees:

kubectl -n cpo exec pg-cluster-0 -- patroni
[...]

All Your GUCs in a Row: jit_debugging_support, jit_dump_bitcode, and jit_profiling_support
Posted by Christophe Pettus in pgExperts on 2026-08-18 at 01:00
Inspect the LLVM bitcode PostgreSQL generates with `jit_dump_bitcode`, or wire JIT-compiled functions into GDB and perf with `jit_debugging_support` and…

Failover slot synchronization in PostgreSQL
Posted by Ajin Cherian in Fujitsu on 2026-08-18 at 00:43

High availability is essential for logical replication environments, but until recently, failover could still leave subscribers disconnected from the replication slots they depend on. PostgreSQL 17 addressed this by introducing failover slot synchronization, allowing logical replication slots to be kept ready on standby servers and reducing the need for full subscriber resynchronization after promotion.

How to Prevent Duplicate Form Submissions in Next.js with Idempotency Keys
Posted by uzair aslam on 2026-08-17 at 20:00

Several duplicate form submissions converging through an idempotency gateway into one database record and one set of downstream integrations

A production-ready approach to preventing duplicate leads and side effects with stable idempotency keys, PostgreSQL constraints, transactional outbox events, safe retries, and reconciliation.

A visitor fills out a form, presses Submit, and sees nothing happen. They press it again. The first request actually succeeded, but its response was delayed. The result can be two leads, two confirmation emails, two CRM updates, and two analytics events from one human action.

This is easy to dismiss as a frontend problem, but duplicate submission is a distributed-systems problem in miniature. Browsers retry, mobile connections fail after the server has committed, serverless functions time out, queues redeliver work, and reconciliation jobs intentionally retry failures. The server cannot infer whether two matching requests represent one action or two deliberate actions unless the client gives both attempts the same identity.

Why disabling the submit button is not enough

Disabling the button is still worthwhile. It improves the interface, stops impatient double-clicks, and tells the visitor that work is in progress. It does not protect the system from a refreshed page, a second browser tab, an automatic client retry, a proxy retry, a function timeout after commit, or a worker processing the same event twice.

The browser guard and the server guarantee solve different problems. Use both, but treat the database guarantee as the source of truth. Anything that depends only on React state disappears when the page reloads and can be bypassed by any direct API client.

The idempotency contract

For every logical submission, the client generates one unpredictable key. Every retry of that submission reuses the key. A genuinely new submission gets a new key. The server scopes the key to

[...]

Sixteen Locks Ought to Be Enough for Anybody
Posted by Christophe Pettus in pgExperts on 2026-08-17 at 16:00
Every query locks every index on a table, even ones it doesn't use.

CNPG Recipe 27 - Running OpenBao on Kubernetes with a CloudNativePG PostgreSQL backend
Posted by Gabriele Bartolini in EDB on 2026-08-17 at 08:48

A walkthrough of running OpenBao on Kubernetes with CloudNativePG as its PostgreSQL storage backend. Every layer of this stack is open source, with no vendor lock-in: Kubernetes and CloudNativePG are both CNCF projects, authenticated entirely over TLS client certificates via the 1.30 DatabaseRole CRD, with no passwords anywhere in the stack. Co-authored with Rob Kenefeck from ControlPlane.

All Your GUCs in a Row: jit_above_cost, jit_inline_above_cost, and jit_optimize_above_cost
Posted by Christophe Pettus in pgExperts on 2026-08-17 at 01:00
PostgreSQL's JIT compiler fires based on estimated query cost, but that estimate measures data volume, not expression complexity.

Why Does PostgreSQL Skip My Index?
Posted by Alexander Ioffe on 2026-08-17 at 00:00
...because your vendor's Cost Model Is from 2002. Since random_page_cost = 4.0 is for spinning disks and hasn't changed in 25 years, setting it to 1.1 cuts this query from 125.98ms to 68.69ms.

How Fast Are Postgres 19 Graph Queries? Part 1: What Are They Actually Doing?
Posted by Alexander Ioffe on 2026-08-17 at 00:00
Postgres 19 adds SQL/PGQ graph queries. Measured against a PostgreSQL 19beta1 build, the fixed-depth graph query compiles to the exact same plan as a hand-written join, and the variable-depth traversal that graph databases were built for still falls to a recursive CTE. Apache AGE runs the same indexed traversal under a Cypher wrapper. Numbers from ExoBench in local mode.

JSONB Paths or GIN or Columns?
Posted by Alexander Ioffe on 2026-08-17 at 00:00
Columns beat JSONB+GIN at everything except multi-key containment on PostgreSQL 17

What Does a Covering Index Cost You?
Posted by Alexander Ioffe on 2026-08-17 at 00:00
'Covering indexes hurt your writes' is an architectural maxim with no number attached. Here is the number: +28% on INSERTs, +25% on UPDATEs, 1.26x faster reads, and covering wins below ~4,300 writes per analytical read. Measured on PostgreSQL 17 at 2M rows.

What Flyway validate actually checks
Posted by Maki Majima on 2026-08-17 at 00:00

Tool capabilities and edition boundaries described here are accurate as of publication. Both vendors move these lines; check current documentation before making decisions based on this post.

There’s a specific moment this post is written for: your pipeline runs flyway validate, everything is green, and you conclude that your database matches your migrations.

That conclusion doesn’t follow. Not because Flyway is broken, but because validate answers a different question than the one you’re asking.

What validate does

When Flyway applies a migration, it computes a checksum of the file (CRC32 for SQL migrations) and stores it in the flyway_schema_history table alongside the version, description, and execution details.

validate recomputes checksums for the local migration files and compares them against what’s stored in the history table. It also checks that applied migrations still exist locally and flags pending or missing ones.

In other words, validate answers: “Have the migration files changed since they were applied, and is the file set consistent with the recorded history?”

It’s a file-integrity check. A good one — it catches the classic incident where someone edits an already-applied migration (even just fixing a typo in a comment) and every environment that applied the original version now disagrees with the repository.

What it never looks at

Notice what’s absent from that description: the schema itself.

validate reads exactly one thing from your database — the history table. It never inspects your actual tables, columns, indexes, or constraints. So:

  • Run a manual ALTER TABLE in production → files unchanged, history unchanged → validate passes
  • Another tool adds an index → validate passes
  • Someone drops a constraint during an incident and forgets → validate passes

None of this is a bug. The tool is doing precisely what it’s scoped to do. The problem is the widespread belief that it’s scoped to do more.

A useful way to hold it in your head:

[...]

All Your GUCs in a Row: jit_expressions and jit_tuple_deforming
Posted by Christophe Pettus in pgExperts on 2026-08-16 at 01:00
PostgreSQL's JIT compiler has two jobs: compiling expressions and deforming tuples. Here's how to isolate JIT bugs with two simple boolean toggles.

pgsonify: Hearing PostgreSQL Health as Elephant Sounds
Posted by Dinesh Kumar on 2026-08-16 at 00:00
pgsonify is an experimental MIT-licensed tool that sonifies PostgreSQL health metrics as real elephant recordings. How it maps stats views to sound.

The agent is not the system. Postgres is.
Posted by Payal Singh in Instaclustr on 2026-08-15 at 21:00

The numbers here come from my own audit and design records as of 2026-08-15. Everything described as a redesign is a plan I have started building and have not proven yet.

Since June I have been building Looper, an experimental system for running long-lived autonomous loops against real work. In July I wrote about the control-theory core: every loop is a closed-loop controller, and the actuator must never reach its own sensor. This post is about the layer above that, and about a change in my mental model that came from measuring the system rather than admiring it. I spent most of the summer designing the organization of the agents, and what turned out to matter was the mechanism that keeps work alive after any particular agent disappears. In the rebuild that mechanism is a Postgres schema: a campaign row per open piece of work, leases with fencing tokens, a state machine enforced by triggers, append-only hash-chained events, and a stored-function API as the only write path. The agents became replaceable workers that Postgres wakes, hands a claim to, and outlives. If you read one section, read "Postgres as the coordination layer." The rest of this post is the evidence for that sentence and what I rebuilt because of it.

What I built, and what held up

The idea, from June, was that I own the goals and everything below me is loops: controllers that sense, act, verify and adjust, each one a small lifecycle that is born from a goal, runs, learns and is retired. Many of them together would form what I called a civilization. I wrote a constitution for it, 18 articles on sensing honesty, independence, containment, lifecycle and the one seat a human never delegates. In August I added a section on warrants, eight more articles: signed, bounded, expiring grants of operational authority that flow down a chain from me to project heads to worker loops.

A good part of that has held up. Thinking in terms of an organization gave me:

  • separation of powers: the thing that acts never grades itself, and the judge c
[...]

The curious case of Google's AlloyDB
Posted by Radim Marek on 2026-08-15 at 15:45

Google launched AlloyDB in 2022. They claimed it is fully compatible with PostgreSQL. Can be up to 100 times faster for analytical queries than vanilla Postgres. Four years later, I haven't personally seen it gain significant traction. But it comes in discussions. When people ask me what AlloyDB actually is, I was able to pin point the features, but wasn't really sure what it delivers.

Over the past 12 months, I’ve evaluated AlloyDB. This article shares my key findings. I tried to keep it as objective as the topic allows, and where it isn't, the text says so. I won't pretend to be objective about the verdict. It depends less on one feature and more on where compatibility ends. And as it goes, "it depends" a lot on your workload and needs.

Let's start with the first claim. What does "fully compatible" mean? In this case it covers the wire protocol. Your psql connects, ORMs work, migration means changing connection string and you are done. What it does not cover is nearly everything you know about the Postgres storage internals and query executor. The 8KB pages that define storage layout for vanilla engine, are no longer the durable representation of your data. The WAL is no longer a recovery mechanism. It becomes the database. VACUUM is there, but runs inside storage layer you don't know and and schedule you can't control. And the tuning options differ from what you are be used to.

This creates the curious case. The compatibility claim is true, and the engineering behind AlloyDB backs it up. It's just narrower than the word "fully" migth suggest. AlloyDB is a different database behind the PostgreSQL protocol.

AlloyDB’s compatibility claim holds at the wire protocol, but the underlying engine diverges immediately at the storage layer.

Gartner defines HTAP, or hybrid transaction/analytical processing, as a new application architecture. It "breaks the wall" between transaction processing and analytics. This allows for better decision-making and real-time insights in business.
The short vers
[...]

Top posters

Number of posts in the past two months

Top teams

Number of posts in the past two months

Feeds

Planet

  • Policy for being listed on Planet PostgreSQL.
  • Add your blog to Planet PostgreSQL.
  • List of all subscribed blogs.
  • Manage your registration.

Contact

Get in touch with the Planet PostgreSQL administrators at planet at postgresql.org.