Latest Blog Posts

pg_vexec one month on: ahead of ClickHouse on Parquet, close behind on MergeTree
Posted by Igor Suhorukov on 2026-10-30 at 16:07

It’s been exactly one month since I published my work porting Greenplum to PostgreSQL 19 and isolating the minimal PostgreSQL core patches needed to run this minimal fork. It all started as a way to extract its ORCA analytical query planner and turn PostgreSQL into a modern, vectorized, high-performance DBMS. And I pulled it off! After a month of development, the database keeps getting faster. I’m now working on a GPU version. Even as a rough draft, on my MSI Raider A18 HX A9W laptop it runs queries faster than LTS ClickHouse: on MergeTree, 1.9x faster by geometric mean and 1.3x by total time, and on vexec_parquet, 13x faster by geometric mean and 18x by total query time.

I’d like to share the results of pg_vexec, an experimental vectorized database that beats ClickHouse on query execution time on Parquet and nearly catches up on MergeTree. I’ve published the telemetry from its ClickBench runs. It should be an interesting read, with plenty of charts, metrics, DBMS logs and numbers from deep inside the engine: https://igor-suhorukov.github.io/sql_report/

What pg_vexec is: https://igor-suhorukov.github.io/blog/2026/10/07/vectorized-postgresql-extension/

Source code for the CPU version:

Burnt TOAST
Posted by Shaun Thomas in pgEdge on 2026-10-30 at 16:04

A financial firm hired me in 2010 to revise their Postgres cluster architecture. During my stint there, I learned a healthy respect for their event_log table. But perhaps “respect” is the wrong word here, as it was more of a deep loathing. This table, you see, was the canonical ledger of system events and consisted of several million rows.The high row count wasn’t a problem by itself. We kept a tight visibility window and archived frequently. Unfortunately for us, one of the columns was an unconstrained TEXT type that commonly held a large blob of XML. Thus any fetch from this table was inordinately slow. Writing was equally painful. We went through great pains to shape the application itself to avoid touching it except when absolutely necessary. It was evil incarnate.The performance of this table initially confused and enraged me—until I remembered about TOAST. Postgres likes to innocuously dub this backronym “The Oversized-Attribute Storage Technique” but DBAs in the field maintain a love/hate relationship with the system. Whether that’s justified is a different question.On the surface, it’s a way to store huge blocks of data elsewhere to keep tuples small and avoid exceeding the relatively petite 8KB data page size. Postgres creates a shadow table for the bulky content, splits it up into chunks, and stores a pointer in the original row. It’s an elegant solution to a pressing issue, but there are deep performance implications.So let’s dig into precisely why DBAs secretly dread large text-based columns, shall we?

Getting TOASTy

To really understand what happened in my event_log case, it’s good to reconstruct some semblance of it.And then we can bootstrap the table with 100k rows. Just enough to make it annoying! The data column needs to be big, but not absolutely gigantic. Let’s start with up to 1000 data points:Great! Now where did all of that data go? If you thought, “Into the event_log table of course!” you’re wrong. Instead, Postgres helpfully created a TOAST table for most of it. Let’s check the pg_c[...]

Postgres 19 is late, and it's AI's fault
Posted by Robert Haas in Databricks on 2026-10-30 at 15:53

Over the past decade, the timing of PostgreSQL major releases has become very predictable: no earlier than the middle of September, and no later than the middle of October. This year is going to be different. PostgreSQL 19 most likely won’t be released until November, and it’s not impossible that the project could decide to postpone the release further.

Moreover, this year, several rather large features were reverted quite late in the beta period: UPDATE/DELETE FOR PORTION OF, SQL Property Graph Queries (SQL/PGQ), and ALTER TABLE … MERGE PARTITION/SPLIT PARTITION were all reverted between August 27 and September 15. While major feature reverts are not especially uncommon immediately after feature freeze, which each year occurs on April 8, it is unusual to see multiple major features get pulled from the release at such a late date. So, what happened?

Read more »

PostGIS 3.7.0
Posted by Regina Obe in PostGIS on 2026-10-30 at 00:00

The PostGIS Team is pleased to release PostGIS 3.7.0! Best Served with PostgreSQL 19 RC 1 , GEOS 3.15.0 , postgis_tiger_geocoder 2025.2 , and address_standardizer.

This version requires GEOS 3.10+, PostgreSQL 14-19, Proj 6.1+, and libgmp. To take advantage of all postgis extension features, GEOS 3.15+ is needed. To take advantage of all postgis_sfcgal extension features SFCGAL 2.3+ is needed. Python 3 is a new requirement to build the documentation images. Visual examples in the docs are off by default. To build docs with them, configure with --with-visual-examples and make sure you have a running PostgreSQL instance; they are then generated automatically when building the docs (or explicitly with make -C regress visual-examples).

This release contains fixes since 3.7.0 release.

3.7.0

This release is a release candidate of a major release, it includes bug fixes since PostGIS 3.6.4 and new features.

Supabase is one part of your HIPAA compliance
Posted by Munaf Khatri on 2026-10-29 at 12:00

If you store PHI on Supabase, you need a signed BAA and a project set to High Compliance. That takes care of the platform. It doesn't cover your RLS policies, your functions or your audit tables, and a HIPAA review will ask about those too.

Supabase's shared responsibility model says the same. It tells you to "always apply Row Level Security (RLS)" and leaves the access rules on sensitive tables to you.

The part Supabase handles

On the hosted platform, Supabase encrypts data at rest and in transit, signs the BAA and checks your project settings. Its HIPAA guide asks you to turn on Point in Time Recovery, SSL enforcement, network restrictions and Postgres connection logging, and to use MFA on every account that can reach the project. The Security Advisor warns you if any of that gets switched off.

The advisor and the database linter also flag a few risky shapes, like a table in public with RLS turned off. What they don't do is run your policies. They won't tell you whether a nurse at one clinic can read visits from another, or whether a deleted record left a trace in your audit table.

The part you handle

A HIPAA review will ask three things about your database.

  • Who can reach which patient rows?
  • Is every change to that data recorded?
  • Can anyone change that record afterwards?

These map onto the Security Rule. Access control is 164.312(a)(1), which asks that access go "only to those persons or software programs that have been granted access rights". Audit controls are 164.312(b). Integrity, 164.312(c)(1), is about protecting PHI "from improper alteration or destruction". 164.312(d) covers authentication, and 164.308(a)(8) asks you to evaluate all of it from time to time and whenever things change.

On Supabase, nearly all of that lives in SQL you wrote. A screenshot of your policies won't show what the database does when authenticated calls one of your functions.

Getting the evidence from your own project

I built unitautogen hipaa for this part. Run it from y

[...]

Which language should an AI agent use to search its memory: SQL or SPARQL?
Posted by Igor Suhorukov on 2026-10-28 at 09:24

Agent memory has been in fashion ever since agents appeared: it fights hallucinations and lets an LLM base its answers and decisions on your own information. Whether it is better to query that information from tables or from a graph is often decided on faith, after reading posts on the internet, without experiments and measurements of your own. In a study by Sequeda et al., GPT-4 answered questions over an enterprise SQL database correctly 16% of the time, and over a knowledge graph on top of the same database 54% of the time; the graph had an ontology with descriptions, while the SQL schema had only DDL: types and table and column names.

In my GraphRAG, the same information comes in two different forms. I extracted the data from the article “My PostgreSQL is faster than yours and has almost caught up with ClickHouse” into 34 PostgreSQL tables and turned them into a graph with an R2RML mapping. I connected both forms of knowledge to an agent over MCP and asked it 15 questions about the article: through SQL, through SPARQL, and with the agent free to choose between the two. In my experiment, the agent ran on three open-weight LLMs in turn. You can deploy them on your own infrastructure or laptop, and your data and questions won’t end up in the logs of a provider or of an aggregator between you and the LLM.

I also checked and calculated which is better for vector storage and semantic search: Lance or pgvector. I’ll share my measurements on current models of how best to search and where to store knowledge.

In the experiment, I caught DeepSeek coming up with an SQL injection to answer my question.

Two representations of the same data

With the help of LLMs, NLP, morphology and other scary words, my data turned into a graph representation and frames bound to RDF quads. The words of the text were broken down into entities, theses, measurements, replies, processes and so on. Each such fragment has its source in the original text, following the W3C Web Annotation standard. A derived layer of data wa

[...]

Dump/restore done. Now what?
Posted by Nikolay Samokhvalov in Postgres.ai on 2026-10-28 at 04:30
After pg_dump and pg_restore, by default the planner statistics and the visibility map are missing. One query: 32.6 s before VACUUM ANALYZE, 23 ms after.

All Your GUCs in a Row: restore_command
Posted by Christophe Pettus in pgExperts on 2026-10-28 at 01:00
PostgreSQL's `restore_command` asks for WAL segments one at a time until the command fails—and that failure marks the archive's end, whether it's real or not. (I consult on PostgreSQL through PGX Inc..)

no pg_hba.conf entry for host: what it means, measured
Posted by Chris van Eijk on 2026-10-28 at 00:00
PostgreSQL's no pg_hba.conf entry for host, measured on 12 to 18 (not 15): the 'no encryption' tail, Docker's gateway address, hostssl, replication and reload.

All Your GUCs in a Row: restart_after_crash
Posted by Christophe Pettus in pgExperts on 2026-10-27 at 01:00
When a PostgreSQL backend crashes, the postmaster can restart itself automatically or exit and wait for external intervention. (I consult on PostgreSQL through PGX Inc..)

SQL vs PL/pgSQL in PostgreSQL: Plan Caching
Posted by Dinesh Kumar on 2026-10-27 at 00:00
SQL vs PL/pgSQL functions in PostgreSQL 16: why a SQL function is re-planned on every loop call, how to reduce plan time.

The PostgreSQL RPM repository needs a lot less EPEL now
Posted by Devrim GÜNDÜZ in EDB on 2026-10-26 at 22:07
For years, installing many packages from the PostgreSQL RPM repository on RHEL and its rebuilds started with the same step: `dnf install epel-release`. PostGIS, pgBackRest, pgcli, patroni, pg_statviz, ora2pg and lots of extensions pulled at least one dependency from EPEL.

Over the last couple of weeks I removed most of those dependencies. On RHEL 8, 9 and 10, the GIS stack, the most popular extensions and almost all of our Python tools now install from the PGDG repositories and the OS repositories (BaseOS, AppStream and CRB) alone.

Continue reading "The PostgreSQL RPM repository needs a lot less EPEL now"

Fostering Inclusivity with the PostgreSQL Europe Diversity Committee
Posted by Karen Jex in Crunchy Data on 2026-10-26 at 11:07

As promised during the session, I'm sharing the slides from the "Fostering Inclusivity with the PostgreSQL Europe Diversity Committee" presentation at the New PostgreSQL Community Members - Summit at PostgreSQL Conference Europe (PGConf.EU) 2026.

Fostering Inclusivity with the PostgreSQL Europe Diversity Committee, Karen Jex, PGConf.EU 2026 New PG Community Members Summit. Large version of the Diversity Committee logo.

The community day sessions weren't recorded, so there won't be a video of this one. I've made an attempt at a transcript to go with the slides!



Headshot of Karen with quote 'Dreams of just quietly getting on with techie stuff'

As with most people in the Postgres community, I wear multiple hats.

  • In my day job, I’m a Senior Software Engineer at Snowflake.
  • I talk about databases at Postgres events and at developer events to help spread the love for Postgres outside of the Postgres community.
  • I’m on the org team for PGConf.EU.
  • I chair the PostgreSQL Europe (PGEU) Diversity Committee.
  • And I dream of "just quietly getting on with techie stuff"!


Different types of diversity

The PGEU Diversity committee wants to encourage increased diversity of all kinds within the Postgres Europe community. Whether that's ethnic diversity, gender diversity, work background, education, socioeconomic situation...



Why? Diversity brings multiple skills and viewpoints and makes the Postgres project better for all of us.

Why do we have a diversity committee?

Because we know that diversity is good for the whole Postgres project. Diverse people bring unique skills and viewpoints, making the Postgres project better for all of us.



What are our goals? 'Everyone should feel welcome, represented and valued within the PostgreSQL community.'

One of our main goals is to make sure that everyone feels welcomed, represented, and valued within our community. and I know that the vast majority of people in the Postgres community also want everyone to feel welcome.

But if you look around, and you don’t see anyone else who looks like you, or who does the same type of job as you, or who has the same type of background as you, it can sometimes be hard to believe that you really belong.



2025 Conference Org Team and Lineup. Two drawings, each representing headshots of 6 white men, with and without head hair and facial hair.

This is an anonymised but sadly pretty accurate picture of the org team and the speaker lineup for a Postgres event in Europe in 2025, so it’s easy to see why sometimes not everyone feels represented.

Fortunately, the vast majority of the folks in the Postgres community really do wan

[...]

Your backups are green. That does not mean you can restore.
Posted by semab tariq in Stormatics on 2026-10-26 at 10:54

Most teams I work with have a backup dashboard, and most days it is green. The job ran; it finished; nothing failed. That green tick feels like safety, and it is the reason nobody thinks about backups again until the day they need one. Then something breaks, someone asks how long it will take to get the database back, and the room goes quiet. Nobody knows. The backups have been running for a year, and nobody has ever brought one back. 

I am writing this because that gap, the space between having backups and being able to recover, is the most common serious problem I find in production PostgreSQL, and hardly anyone is measuring it.

A Monday that goes badly

Here is the shape of it. I have put this timeline together from the kind of incident customers keep running into, so treat it as a pattern rather than one company’s story.

  • At 09:38, a new feature is rolled out. One statement drops a column that still holds live data. 
  • At 09:44, support tickets start coming in because customer records look incomplete. 
  • At 10:05, after trying a few smaller fixes, the team decides to restore to just before 09:38. 

The backups have been green for fourteen months, so everyone is fairly relaxed.

  • At 10:20, they find out there is no restore host. Nobody had ever needed one. Someone starts building it. 
  • At 13:50, the restore finishes and recovery stops earlier than it should, because a WAL segment from months ago is missing from the archive. 
  • At 16:30, they give up on the exact point in time, recover to a copy that is six days old, and spend the next two days putting the difference back by hand.

The business had expected this to take about an hour, with no visible data loss. Instead, the restore took more than two

[...]

Read-Your-Writes at the Proxy: LSN Session Consistency for PolarDB
Posted by Vadim Yatsenko in Awide Labs on 2026-10-26 at 07:55
Most database proxies that do read/write splitting get one thing wrong: after a client writes a row and immediately reads it back from a replica, the read can return stale data.

Zero-Copy I/O for the Shared Storage Daemon: Removing the Last Copy from the WAL Path
Posted by Vadim Yatsenko in Awide Labs on 2026-10-26 at 07:54
Every commit in PolarDB ends the same way: the WAL record must reach shared storage. On the way there, the bytes move from a WAL buffer, through the shared-storage daemon, to a device.

All Your GUCs in a Row: reserved_connections
Posted by Christophe Pettus in pgExperts on 2026-10-26 at 01:00
PostgreSQL 16's `reserved_connections` reserves slots for your monitoring and backup roles when the application exhausts the pool. (I consult on PostgreSQL through PGX Inc..)

Building a Table Access Method, Part 6: TRUNCATE
Posted by Mats Kindahl on 2026-10-25 at 18:34

In the previous two posts you could see how to manage storage for create and drop and also to work with transactions. In this post you’ll learn how to handle TRUNCATE, which replaces the arena of a table with a new one. Doing that safely means choosing which arena to release based on how the transaction ends. This post handles the normal path, the in-place path Postgres takes for tables created in the same (sub)transaction, and the rollback cases for both.

In Part 5 you could see how the arena of a table was tied to the outcome of the transaction, so that CREATE TABLE and DROP TABLE neither leak nor lose an arena when a transaction or a savepoint rolls back. When TRUNCATE is called, relation_set_new_filelocator is called for a table that already has an arena, and it should replace that arena with a new one.

The normal TRUNCATE path

Postgres assumes that you truncate a table by giving it a new relfilenode and let the old one be reclaimed. For pg_memtable it is necessary to either create a second arena and point the relfilenode at it, or truncate the arena in-place. It is not possible to blindly truncate the existing arena, and you will soon understand why.

To deal with TRUNCATE, the memtable_ProcessUtility function is extended to call the finalize function for TRUNCATE in the same way as is done for CREATE. Because the finalize function ignores relations that have no cache entry, tables that use other table access methods are unaffected and the finalize function can be called blindly without checking the table access method.

static void memtable_ProcessUtility(PlannedStmt* pstmt, const char* queryString,
                                    bool readOnlyTree,
                                    ProcessUtilityContext context,
                                    ParamListInfo params,
                                    QueryEnvironment* queryEnv,
                                    DestReceiver* dest, QueryCompletion* qc) {
  Node* parsetree = pstmt->utilityStmt;

  if (prev_ProcessUtility)
 
[...]

Speech at PGDay Israel 2026:Durability, Consistency, and Performance
Posted by Vadim Yatsenko in Awide Labs on 2026-10-25 at 11:16
AwideLabs Tech Column: How we took PolarDB from a promising open-source project to production-ready Awide Polar.

DataMax: A Dedicated WAL Log-Store Node for Near-Synchronous Durability
Posted by Vadim Yatsenko in Awide Labs on 2026-10-25 at 11:15
Every durable database change in PolarDB passes through one place before it is safe: the write-ahead log. A replica is just a machine that stores that log and replays it. But how if a cluster need a pure copy of the WAL?

Commit Sequence Number (CSN) MVCC: Lock-Free Snapshot Acquisition
Posted by Vadim Yatsenko in Awide Labs on 2026-10-25 at 11:15
Every time PostgreSQL decides whether a row is visible to your query, it asks the same question: was the transaction that wrote this row already committed when my snapshot was taken?

All Your GUCs in a Row: remove_temp_files_after_crash
Posted by Christophe Pettus in pgExperts on 2026-10-25 at 01:00
Protect your disk from orphaned temporary files after a backend crash. (I consult on PostgreSQL through PGX Inc..)

CNPG Recipe 28 - Generated and rotating PostgreSQL user passwords in CloudNativePG 1.31
Posted by Gabriele Bartolini in EDB on 2026-10-24 at 16:34

A first look at what CloudNativePG 1.31 will bring to PostgreSQL credentials: a DatabaseRole can now generate its own password, keep it in a Secret the operator owns, shape it with criteria and rotate it on a schedule, with PostgreSQL enforcing the lifetime through VALID UNTIL. The feature is merged but not yet released, so this recipe anticipates 1.31 and shows how to try it today on the latest development snapshot.

Contributions for week 41 & 42
Posted by Cornelia Biacsics in postgres-contrib.org on 2026-10-24 at 09:20

On 12 October, the PostgreSQL User Group Vienna met, organized by * Cornelia Biacsics * Ranjeet Kumar

Speakers:

  • Mayur B.
  • Radim Marek

On 13 October, the San Francisco Bay Area PostgreSQL Meetup Group met online. Christophe Pettus delivered a talk. The meetup was organized by:

  • Katharine Saar
  • Stacey Haysler
  • Christophe Pettus

On 13 October, Devrim Gündüz and Pavlo Golub staffed the PostgreSQL booth at DATA STACK CONF 2026.

On 14 October, the PostgreSQL Istanbul User Group met

Organizers:

  • Devrim Gündüz,
  • Gülçin Yıldırım Jelínek
  • Bilge Korkmaz Erdim

Speakers:

  • Melih Mutlu (Tiger Data)
  • Mehmet İnce (Prodaft)

On 14 October, Claire Giordano and Aaron Wislang hosted and published a new podcast episode “From Oracle DBA to Postgres contributor with Karen Jex" from the Talking Postgres series.

On 15 October, the PostgreSQL User Group Edinburgh met, organized by Jimmy Angelakos. Elizabeth Garrett Christensen delivered a talk.

On 16 October the PostgreSQL Ghana User Group met, organized by Ezra Yendau and Julius Boakye. Ezekiel Sebastine delivered a talk.

From 20-23 October, PostgreSQL Conference Europe 2026 took place.

Organized by:

  • Andreas Scherbaum
  • Chris Ellis
  • Dave Page
  • Ilya Kosmodemiansky
  • Karen Jex
  • Magnus Hagander
  • Marc Linster
  • Martin Marques
  • Samed Yildirim
  • Stefan Fercot
  • Valeria Kaplan

Talk Selection Committee:

  • Samed Yildirim
  • Floor Drees
  • Gülçin Yıldırım Jelinek
  • Jan Wieremjewicz
  • Mayuresh Bagayatkar
  • Andrei Lepikhov
  • Jan Karremans
  • Priyanka Chatterjee
  • Stefanie Janine Stölting

Code of Conduct Committee:

  • Stacey Haysler
  • Ellyne Phneah
  • Pavlo Golub
  • Samed Yildirim

Speakers:

  • Andres Freund
  • Alexander Korotkov
  • Alexander Kukushkin
  • Alicja Kucharczyk
  • Andreas Karlsson
  • Andrei Lepikhov
  • Ants Aasma
  • Ashutosh Bapat
  • Bertrand Drouvot
  • Boriss Mejias
  • Chris Ellis
[...]

All Your GUCs in a Row: recursive_worktable_factor
Posted by Christophe Pettus in pgExperts on 2026-10-24 at 01:00
PostgreSQL 15's `recursive_worktable_factor` helps you fix slow recursive CTEs by tuning a single estimate. (I consult on PostgreSQL through PGX Inc..)

PolarFS: Disk-Paxos RW Leases That Keep Shared Storage Out of Split-Brain
Posted by Vadim Yatsenko in Awide Labs on 2026-10-24 at 00:00
PolarDB separates compute from storage. Many machines can reach the same block device. Exactly one of them may write to it. A second read-write mount corrupts data, and there is no recovery from it.

pg_acm at PGConf.EU
Posted by Henrietta Dombrovskaya on 2026-10-23 at 17:57

Yesterday, I spoke about pg_acm at PGConf.EU. Speaking at the biggest Postgres conference in the world is an honor in itself, and it’s not that I have a chance to present there every year, so I am incredibly thankful to the CfP committee for choosing this talk.

This talk has a long history of rejection and denial of the fact that something could be wrong with Postgres, which made me appreciate this opportunity even more.

My presentation earlier this year at Tallinn PUG definitely helped me shape it better, and I think it went as well as it could have.

Is it too much to ask?!
Can we have this option on Postgres?

Not only do I have a dream, but I also have a request: please try pg_acm and give me feedback! From my perspective, the tool is complete, but I am sure other people will find issues. If you find them, please let me know! Please open an issue on GitHub!

https://github.com/hettie-d/pg_acm

Zero Downtime Rolling Major PostgreSQL Upgrades on a Distributed PostgreSQL Cluster
Posted by Ahsan Hadi in pgEdge on 2026-10-23 at 11:15

Every major PostgreSQL upgrade I have done on a single primary came with the same conversation: how long can the application be down?  is fast, but it is still an outage, and you still have to rebuild or resync the standbys afterwards.A multi-master cluster gives you a different option. Spock is pgEdge's open-source PostgreSQL extension for multi-master logical replication, and with it every node takes writes, so you never have to upgrade a node in place. You add a brand new node on the new major version, let it join the cluster, move traffic to it, and retire the old one. Repeat for every node and the cluster ends up on the new version without the application ever losing a writable endpoint.Starting with PostgreSQL 19, community Postgres offers a blue-green style upgrade built on ,  and the new sequence sync. This is not really ZERO downtime upgrade because the writes need to be paused for a certain period of time. At cutover, writes have to stop while the last changes drain, sequences are synced and the application is switched over. For a critical application, that pause is still an outage.I tested this end to end on my two node pgEdge test cluster running PostgreSQL 17.10 with Spock 5.0.12, adding a PostgreSQL 18.6 node next to them. This post walks through exactly what I ran, including the things that tripped me up, so you can do the same thing on your own cluster.One note before we start. pgEdge Control Plane is pgEdge's declarative orchestration tool for managing Postgres clusters. If your cluster runs under it, use its built-in major version upgrade instead. It drives the same zero downtime add node process through its API.

The Starting Setup

Before I touched anything, the cluster was a plain two node Spock setup on PostgreSQL 17, running on two Rocky Linux ARM64 VMs. Both nodes take writes.The database is , with the usual  tables plus a couple of test tables, all in the  replication set. I put n3 and its standby on the same VM as n1 to keep the lab small. In production each node would be its own se[...]

Tuning Postgres for Analytics - PGConf.EU
Posted by Karen Jex in Crunchy Data on 2026-10-23 at 06:05
Tuning Postgres for Analytics, Karen Jex, Senior Software Engineer at Snowflake

Please enjoy the slides and transcript from Tuning Postgres for Analytics at PostgreSQL Conference Europe (PGConf.EU) in Valencia, Spain on 20 Oct 2026.

I'll add a link to the recording once it's available.

I've included just very brief alt-text for each slide image, but I've tried to add any links or other essential information into the body of the blog post.



Introduction

Obviously, I don't know the specifics of your particular Postgres environment. But, as always, there are some generalisations that apply to most systems. So, just for today, we're going to imagine that you're running a small chain of popular coffee shops in Valencia. If you've seen any of my previous talks, you might start to notice a coffee and cake theme in lots of my talks, demos and examples!

You've implemented a state of the art system to manage your sales, stock, customer loyalty program etc. and you've carefully configured your production database for the needs of your day-to-day application workload.

Let's talk about what happens if you then need to run analytics queries against your application data. How can you do that without compromising the performance of your application?



whoami, photo of Karen

First, a quick "about me":

I’ve spent my whole career working with databases; for the first 20 years or so as a database administrator. I’m currently a Senior Software Engineer on the Postgres extensions team at Snowflake, working mainly on the pg_lake set of extensions.

I’m actively involved in PostgreSQL Europe; amongst other things, leading the PGEU Diversity Committee and helping to organise pgconf.eu. I also write and present talks (about databases) at Postgres and Developer conferences.

If you want ideas for non-database-related conversation topics when you meet me in the hallway: I love being creative; crocheting cute things, sewing clothes and accessories, and 3D printing all sorts of random things. I also enjoy getting out and about on one of my bikes in the mountains where I live.



OLTP (Online Transaction Processing)

Back to the presentation.

Let's

[...]

PostgreSQL Indexes: Which Type to Use (10M-Row Benchmark)
Posted by Aleksei Aleinikov on 2026-10-23 at 06:00

PostgreSQL Indexes: Which Type to Use (10M-Row Benchmark)

Every Postgres team eventually types CREATE INDEX in a hurry, and most of them type the same one. B-tree is the right default, but it is not always the right answer. On a table with 10 million rows I found an index that was 3,000 times smaller and only 3 times slower, an index that did nothing at all, and a “covering” index that made queries faster until a routine UPDATE took the advantage away.

This is Part 1 of Postgres in Production, a series about the decisions that matter once a database leaves the tutorial: indexes, VACUUM and bloat, connection pooling, partitioning and JSONB. Each part follows one rule: measure first, then explain. The numbers below come from PostgreSQL 18.6 and an open-source benchmark that you can run yourself.

PostgreSQL index types compared on 10 million rows: B-tree, hash, BRIN and GIN, measured for speed, index size and write cost.

Which PostgreSQL index type to use: the short answer

A PostgreSQL index is a separate data structure that lets the database find rows without reading the whole table. The type decides which questions it can answer and how much space and write time it costs.

Your query Index to use Measured on 10 million rows
WHERE user_id = 42, ranges, ORDER BY B-tree (the default) 158 ms scan, 0.11 ms with the index
Only a rare slice of rows matters (status = 'failed') Partial B-tree 1.8 MiB instead of 301 MiB, same speed
Few columns, many lookups Covering B-tree (INCLUDE) 0.109 to 0.078 ms, at 4.4 times the size
Time range on append-only, ordered data BRIN 72 KiB instead of 214 MiB, 3 times slower
Contains: arrays, jsonb, full-text, LIKE '%x%'
[...]

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.