r/PostgreSQL

Make sure to upgrade your PostgreSQL to the latest minor version ASAP

A friendly reminder to everyone: if you have not done it already then upgrade your PostgreSQL to the latest minor versions, as they include a fix for a high-impact CVE: CVE-2026-14669.

reddit.com
u/jooosep — 15 hours ago

pgColumnar 1.0-alpha2 released: Iceberg support, Object Storage and more!

Release date: 2026-08-18
Previous release: 1.0-alpha (2026-08-04)

pgColumnar 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.

This release requires one upgrade command. See "Upgrading" at the end.

Highlights

  • Apache Iceberg, read-only. Read an Iceberg table at its current snapshot three ways: by metadata path, through a REST catalog, or as a foreign table. Row-level deletes of all three kinds (position, equality, and format-version-3 deletion vectors) are applied under their sequence rules, columns resolve by schema field id, and the foreign-data wrapper prunes whole data files from a query predicate.
  • Object storage. The Parquet and Iceberg readers, the Parquet export functions, and the foreign-data wrapper read from and write to s3://, http://, and https:// URLs. Remote access goes through a separate module, is confined to an operator-set endpoint allow-list, and refuses link-local addresses.
  • Maintenance and operations. A new pgcolumnar.autovacuum daemon performs online upkeep, pgcolumnar.maintenance_due reports what a table needs, and a stripe flush can run across background workers.
  • Security and hardening. Six memory-safety and denial-of-service fixes on the read and object-store paths, several from an adversarial audit, each with a regression test and a proof that removing the fix reintroduces the failure.

Apache Iceberg support (read-only)

  • Filesystem tables. pgcolumnar.iceberg_scan(metadata_path) reads a table given a column definition list. It resolves each output column to a schema field id, so a data file written before a column rename still reads. It applies position deletes, equality deletes, and format-version-3 deletion vectors (Puffin roaring bitmaps), each under its own sequence and scope rule, and verifies deletion-vector checksums, offsets, and cardinality. A data file with no field ids is bound by the table's schema.name-mapping.default; one with neither field ids nor a name mapping is refused rather than guessed. Only Parquet data files are read. Recorded paths are rebased onto the table's actual location and refused if they resolve outside it. Introspection functions iceberg_current_snapshoticeberg_data_filesread_avro_manifest, and read_manifest_list are included.
  • REST catalog. pgcolumnar.iceberg_rest_scan(catalog_uri, namespace, table_name) resolves a table through a catalog and reads it with the same projection and delete rules. The first argument may instead name a foreign server of the pgcolumnar_iceberg_catalog wrapper, which holds the catalog URI in server options and the bearer token or OAuth2 client credentials in a user mapping, so one role's secret is private from another and never appears in a function argument or the statement log. When the catalog vends short-lived storage credentials in its load-table reply, the reader uses them for the data files. iceberg_rest_namespaces and iceberg_rest_tables list a catalog.
  • Foreign-data wrapper. A foreign table over an Iceberg table (pgcolumnar_iceberg, option metadata_path) receives the query predicate and prunes whole data files before opening them: by partition value for identity, bucket[N]truncate[W], and the temporal transforms, and by stored minimum and maximum for integer and boolean columns. Pruning only removes files that cannot match, so results are unchanged, and EXPLAIN (ANALYZE) reports Files Pruned.

Object storage

  • The Parquet read and export functions, the Parquet foreign-data wrapper, and the Iceberg reader accept s3://http://, and https:// URLs wherever they accept a local path. s3:// requests are signed with AWS Signature Version 4; https:// verifies the server certificate when the object-store module is built with OpenSSL.
  • Remote access lives in a separate module, pgcolumnar_objstore, loaded on first use, so no second TLS stack enters the main server process by default.
  • pgcolumnar.objstore_allowed_endpoints lists the endpoints remote access may reach. It is empty by default, which refuses every remote endpoint, and it is superuser-only. Link-local and instance-metadata addresses are refused after name resolution.
  • Object-store credentials come from the server process environment, never a function argument or a log line.

Maintenance and operations

  • pgcolumnar.autovacuum is a maintenance daemon for the online upkeep that core autovacuum does not perform on a columnar table.
  • pgcolumnar.maintenance_due(rel, compact_due_fraction, recluster_due_fraction) reports whether a table is due for compaction or reclustering.
  • pgcolumnar.parallel_flush dispatches a stripe flush across background workers.
  • pgcolumnar.fsst_verdict_reuse caches a column's FSST keep-or-drop verdict, so a repeated write does not re-run the substring search.

Statistics and the planner

  • pgcolumnar.analyze() now collects most_common_vals and most_common_freqs, places histogram_bounds at PostgreSQL's own positions, honours the per-column statistics target, and counts null_frac over live rows.
  • EXPLAIN (ANALYZE) reports Columnar Usable Skip Predicates beside the skip counters.
  • The index-fetch cost penalty sizes row groups by a table's effective stripe_row_limit, and the grouped vector aggregate shares the scan node's input-cost estimate, so the planner prices a columnar scan more accurately.
  • The Iceberg foreign-data wrapper estimates a scan's row count from the manifests rather than a constant, so join planning above a large Iceberg table is sound.

Performance

  • A parameterized predicate (col >= $1 from a prepared statement or PL/pgSQL) now drives chunk-group skipping. On a generic plan such a scan previously read every chunk group.
  • Group and per-vector skipping read only the columns a query's predicates reference, rather than every column's zone map. On a wide table a one-predicate scan reads far fewer zone-map rows.
  • Reads of the delete_vector catalog use its index rather than a sequential scan, so a scan of a table with deletes is no longer proportional to the catalog size.
  • The Iceberg foreign-data wrapper decodes only the columns a query references.
  • The ungrouped batch fold gathers only the referenced columns per row, and a columnar scan whose filter cannot be pushed down skips decoding the filtered columns.

Security

  • The native varlena decoder bounds a value's stored length against its buffer, so a corrupt chunk or catalog row is refused with a clean error rather than an out-of-bounds read or a detoast through a bad pointer.
  • The local file read path no longer has a stat-before-open race, and the Iceberg, Avro, Parquet, Arrow, and parallel-copy readers refuse a FIFO or other non-regular file with a non-blocking open rather than a cancel-resistant hang.
  • The Iceberg reader refuses several classes of malformed or hostile table metadata, including a null manifest path that had crashed the backend, a null or negative position-delete ordinal, a null manifest-list sequence number, and a dangling current-schema-id.
  • The Thrift and Avro field-skip loops are interruptible, so a crafted Parquet footer or Avro manifest can no longer spin the backend uncancellably.
  • The object-store client refuses a URL path or host carrying CR or LF, closing an HTTP request-line injection.
  • The native dictionary decode path no longer reads uninitialized memory, and the Parquet dictionary decode path no longer reads out of bounds on a crafted file.

Correctness fixes

  • Concurrent UPDATE or DELETE of the same columnar row serializes on the row identity, so the losing writer gets a retryable serialization failure rather than a lost update.
  • A predicate on a column declared over a domain, and a bigint column compared against an unadorned integer literal, now prune chunk groups.
  • CREATE TABLE ... USING pgcolumnar AS SELECT no longer fails when the source is another access method.
  • pgcolumnar.sort_status works for a non-superuser who owns the table.
  • Failed export_parquet and export_arrow no longer leave a partial file.

Internal changes

  • The extension's exported C symbols are namespaced under pgcolumnar, and the custom scan node is PgColumnarScan. The native encoding-descriptor wire layout and the delete-vector visibility logic are each single-sourced, with the on-disk format unchanged and verified byte-identical.
  • default_version is 1.0-alpha2. Upgrade scripts from both previously shipped versions (1.0-dev, which the v1.0-alpha tag installed, and 1.0-alpha) ship with the extension, so a single ALTER EXTENSION pgcolumnar UPDATE reaches 1.0-alpha2 from either.

Upgrading

Install this build, then run the following in every database that has the
extension:

ALTER EXTENSION pgcolumnar UPDATE;

This is required. The C-symbol rename moves the symbol names each installed
function recorded when it was created; without the catalog update those records
point at symbols the new library does not export, and reading an existing
columnar table fails with could not find function "columnar_handler". No data
is converted and no SQL you write changes. The upgrade replaces catalog entries
only.

See docs/installation.md for the commands, including how to list the databases
that need the update.

Scope and limitations

  • Iceberg support is read-only, at a table's current snapshot, and reads Parquet data files only.
  • Object-storage reads take exact object keys.
  • HTTPS and S3 over TLS require the pgcolumnar_objstore module built with OpenSSL.
  • This is an alpha. Interfaces may change before 1.0.
u/linuxhiker — 2 days ago

x86 vs arm64

Are there any advantages to running Postgres on an arm cloud server vs an x86 one?

I am not referring to cost savings but performance and efficiency advantages where arm can provide benefits over x86 under any specific scenarios.

reddit.com
u/Blues520 — 3 days ago

SELECT * FROM subAccount will silently fail because postgres lowercases unquoted identifiers

if your orm creates tables or columns in camelcase, and at some point you drop into raw sql to query one directly, you'll eventually write select * from subAccount and get "relation does not exist," which is confusing when the table is right there in the migration file.

postgres folds unquoted identifiers to lowercase by default. subAccount unquoted becomes subaccount, and if the actual table was created quoted, which is what most orms do to preserve the case you gave them, subaccount genuinely doesn't exist, only "subAccount" does. the fix is quoting it: select * from "subAccount". every camelcase identifier from your orm needs the same treatment the moment you touch it by hand.

burned an hour on this recently on a table i'd looked at a hundred times, because the error doesn't tell you it's a casing problem, it just tells you the table isn't there.

what's your team's convention, always quote camelcase identifiers by habit, or avoid camelcase in the schema entirely to sidestep it?

reddit.com
u/kumard3 — 3 days ago

Which managed PostgreSQL host is affordable without being unreliable?

I need managed Postgres for a small production app and I’m fine paying for it. I just don’t want to jump straight to RDS/Cloud SQL pricing or manage Postgres myself on a VPS.

Main things I care about:

  • always-on Postgres
  • automated backups
  • updates/maintenance handled
  • predictable monthly pricing
  • easy to move later if needed

Not really looking for free tiers or hobby plans since it has real users. I’d rather pay a reasonable fixed monthly amount and not think about the DB too much.

What are you using in production that has actually been reliable without getting expensive?

reddit.com
u/Soft-Nature-7256 — 6 days ago

How are you managing your Schemas in Database first Project?

I'm mostly coming from a classic programming background (.NET, node, java, ...) where so far I only worked with code-first tools professionally (basically you define the schema of your database in your programming language and the SQL code to generate the database gets generated).

However for my next own project, I want to start database first ... however one problem I'm constantly running into is genuinely a pain in the ass to make changes to your schema, and deploy them ... since in SQL you always have a list statements that need to run in the correct order since they are not stateless (like a class, struct, function, ... declarations in a traditional programming language).

For people who work with postgres professionally, I would be interested what setup you are using for schema and management.

reddit.com
u/faze_fazebook — 7 days ago

I built a free tool that does the pg_stat_statements to EXPLAIN to index recommendation loop for you

RDST (Readyset Diagnostic & SQL Toolkit) is a free desktop app that connects to your Postgres database, ranks the queries actually costing you time, and explains what to do about each one.

The reason I built it is that the tooling Postgres already gives you is genuinely good, but addressing database performance issues is still a highly repetitive process:  

  • pull pg_stat_statements and sort by total time
  • take the top query and run EXPLAIN ANALYZE on it
  • go find the table definitions for whatever it touches
  • check whether the statistics on those columns are current
  • work out whether the index you have in mind already exists under another name
  • decide whether it is worth adding
  • do it again for the next query

RDST collapses all of that into one pass, so instead of starting at step one you start at the answer.

Full disclosure - I work for Readyset (which is a caching layer for postgres / mysql), and this tool spawned from a recurring question our caching customers kept asking - which queries should we actually cache? And these same queries are the ones that, even without a caching solution, could heavily benefit from all the relevant performance diagnostics.  

RDST not only helps you discover slow queries and give you the appropriate action plan to improve them, but also provides full re-write suggestions, the ability to benchmark slow queries and track their  performance over time, and even allows you to ask any question about your database/queries in plain english and get helpful responses.

The tool is completely free to use, and we provide free trial tokens for all of the AI powered features. The app is in beta and we plan to release it under an MIT license. It runs locally, stores locally, and everything it does is read-only.  Full privacy related details can be found here: https://readyset.io/docs/readyset-ai/rdst/desktop/privacy

We would love feedback from people who actually spend time wrestling with queries every single day! Particularly:

  • Does it surface the queries you'd investigate first?
  • Are its explanations and recommendations useful, or merely confident-sounding database fan fiction?
  • Would you be comfortable connecting it to a real environment? If not, what would stop you?
  • What's missing from the workflow?

Source:
https://readyset.io/docs/readyset-ai/rdst/desktop
https://github.com/readysettech/rdst

u/Frone0910 — 7 days ago

pgEdge providing false information

Normally I would comment in blogpost, but, (as it seems to be 'trendy' recently) they don't have comments.

So, in their blogpost https://www.pgedge.com/blog/looking-forward-to-postgres-19-syntax-potpourri they mention:

> Well, that all ends with the introduction of GROUP BY ALL.

Well, apparently not, because this change has been rolled back, and it no longer works:

$ select relnamespace, relkind, count(*) from pg_class group by all;
ERROR:  syntax error at or near ";"
LINE 1: ... relnamespace, relkind, count(*) from pg_class group by all;
                                                                      ^

Also, I know that the title is "somewhat" click-baity, but I really want to shame bloggers/companies to add proper way to comment on their posts.

---- UPDATE ----

blogpost was corrected thanks to /u/fullofbones. But (as of 2026-08-12) comments are still not enabled…

reddit.com
u/depesz — 10 days ago

Subtle roles question

One aspect of Postgres roles is that permissions exist on roles themselves, and these permissions provide for certain kinds of transitive grants.

We have a case where we would like a role M to have the option to inherit permissions from role G only when it elects to do so. That is: in a discretionary fashion. Offhand, I cannot construct an arrangement of roles and permissions that would make this possible.

Is there some arrangement I am failing to see, or does this fall outside of what the Postgres role system is able to express?

reddit.com
u/jsshapiro — 11 days ago
▲ 70 r/PostgreSQL+1 crossposts

Anyone who works on a production Postgres knows the feeling. Every command you run, you're walking a tightrope. One typo, one wrong terminal tab, one bug in the app that turned a filter into a full-table query, and now you're doing PITR or restoring from backup at 3am.

I've spent years as a DBA in charge of critical production workloads. Most of the time the rope holds. Sometimes it doesn't.

pg_savior is a Postgres extension that hooks the planner and refuses the obvious dangerous shapes:

  • DELETE / UPDATE without a WHERE
  • CREATE INDEX without CONCURRENTLY
  • DROP DATABASE
  • ALTER COLUMN TYPE that triggers a full rewrite
  • DELETE WHERE id > 0 (planner row estimate gives intent away)

When you really mean it: SET LOCAL pg_savior.bypass = on for the transaction, and the guard steps aside.

It's an extension, not a proxy — psql against a local socket, ORMs, migration tools, cron jobs, AI agents with DB credentials all hit the same hook. Nothing routes around it.

Three hooks do the work: post_parse_analyze_hook, ExecutorStart_hook, ProcessUtility_hook.

What other dangerous queries should pg_savior catch? Also, curious if you have best practices to catch these mistakes.

u/vira28 — 12 days ago
▲ 7 r/PostgreSQL+1 crossposts

A globe with PostgreSQL events

Just for fun made a globe with PostgreSQL events: https://pg.whitetown.com - known conferences, meetups and user groups since 2001, with a year slider.
Mobile friendly, but for the full experience use IE4 :-). Feedback welcome - especially if something is missing or wrong.

pg.whitetown.com
u/White_Town — 9 days ago

What happens when an AI coding agent can see the database, not just the code?

I've been thinking about this recently because database problems can be surprisingly difficult for AI coding agents to diagnose.

An agent can look through the application code and see that a query appears correct, but that doesn't necessarily tell it what is happening with the actual PostgreSQL instance.

For example, the code might be fine while the problem is actually a connection issue, incorrect environment variable, migration that didn't run, permission problem, unexpected schema state, or simply a database service that isn't available.

I've been exploring this while working with IQX.DEV. where we're looking at how an AI agent can work with the running application environment instead of treating the source code as the entire picture.

The idea is fairly simple: give the agent useful runtime context so it can understand what is actually happening before suggesting or making a change.

For a PostgreSQL-backed application, that could mean understanding things like database connectivity, application logs, service connections and whether the database is actually reachable from the application.

I'm curious how useful people think this kind of database awareness would be for coding agents.

Would you want an AI agent to be able to inspect PostgreSQL-related runtime information when debugging an application?

Where would you draw the line between observing the database, diagnosing a problem, and actually making changes to the database?

Personally, I'd be much more comfortable with an agent that can explain why it thinks something is wrong before it gets permission to change anything.

reddit.com
u/OwlZealousideal4779 — 11 days ago
▲ 18 r/PostgreSQL+2 crossposts

Polymorphic relationship options for PostgreSQL DB?

I’m trying to create a database that would involve a table referencing one of multiple other tables. From my research it sounds like this would be a polymorphic relationship, but I’ve been seeing a few different options for implementing it and I’m not sure what would be best. These are what I’ve seen so far, so let me know which sounds best, but please let me know if you know of a better one.

The Database: The short and sweet of it is I’m making a database to store diary entries. Each diary entry uses fields such as date range of referenced event, tags (through many to many), etc. Each entry is either done as a video, an audio recording, or a text entry. Each of these entry types would also have their own respective metadata such as video setup or audio setup. Because of that, I thought the best option would
be to separate them into their own tables.

Option 1: Table Type Field - in the diary entry table, have a field for the type and a field for the foreign key, but don’t actually make it a foreign key. Instead setup a trigger to manually enforce referential integrity by checking that the referenced entry exists in the corresponding type table when inserting. I think I’m leaning towards this one the most. Since it’s closest to what PHP Laravel does.

Option 2: Multiple Nullable Foreign Keys - In the diary entry table Have a foreign key for each entry type that references the respective table, but they’re nullable since only one would actually be used for each entry. Add a constraint to check that one of the fields isn’t empty when inserting a record. This apparently might take less storage than having a varchar type field, though that might be splitting hairs.

Option 3: Table Inheritance - I haven’t done as much research into this one so I don’t know what the structure would look like exactly. But apparently PostgreSQL supports table inheritance like with Object Oriented programming. So it would be something like the diary entry table is the base table, and then each entry type inherits from it and adds their own metadata fields. The reason I’m hesitant to do this is I don’t want to permanently lock myself into Postgres, I want the ability to upgrade and changes engines and I’m not sure how hard that would be if the other engine doesn’t support inheritance. For a similar reason I’m using “period start” and “period end” fields for the date range of an entry instead of the Postgres date range data type.

Option 4: Entries Types Reference Diary Entry - Again I haven’t looked into it much, but I saw it mentioned I could reverse the relationship and instead have each entry type reference the diary entry record it belongs to with a foreign key. I’m not sure yet if there’s any additional complexities are requirements that I would have to implement to make it safe.

reddit.com
u/Gamemon_RD — 12 days ago