MortarIQStart for free

← All posts

Platforms · September 3, 2026

Is your PostgreSQL data AI-ready? The catalog already knows.

By the MortarIQ Founder · 7 minute read

Every other platform in this series is a warehouse. Postgres usually is not. It is the database underneath the application, and it arrives at the AI conversation from a completely different direction: nobody chose it for analytics, and nobody modelled it for a retrieval corpus. It was chosen because it was the right database for the product, and then one day someone pointed an agent at it.

That origin explains the whole readiness profile. A warehouse was built to be described — its catalog exists so that analysts and governance tools can reason about it. Postgres was built to be served. Its catalog is superb at structural truth, because the query planner depends on it, and nearly silent on everything a governance layer would add. On Snowflake the readiness gap is usually uptake, on BigQuery it is sprawl, on Databricks it is coverage. On Postgres the gap is description: the database was never asked to explain itself to anyone but the application, and an AI workload is the first consumer that needs it to.

Here is what an AI readiness audit can read from a Postgres catalog, what it deliberately cannot, and the patterns that keep showing up.

What the Postgres catalog answers

More than people expect. The system catalogs and information schema carry most of what the six factors need, without a single row being read:

  • Structure and types come from information_schema.columns and information_schema.tables: what exists, what shape it is, and which columns were left as semi-structured blobs an AI workload will have to guess its way through.
  • Documentation comes from pg_description, the catalog behind COMMENT ON COLUMN. This is the single most revealing number in a Postgres assessment, and usually the lowest.
  • Entities and relationships come from information_schema.table_constraints: which tables declare a primary key, which declare foreign keys, and which are joined by convention and tribal memory instead.
  • Temporal scope comes from the presence of date and timestamp columns, which determines whether a corpus can be filtered to a point in time or only taken whole.
  • Access shape comes from pg_index and pg_tables: whether tables are partitioned or carry a secondary index, which decides whether retrieval over them is an operation or an outage.
  • Row-level security comes from pg_policies, and this one is a genuine Postgres strength — see below.
  • Embedding coverage comes from looking for columns whose type is vector, which is how a pgvector installation announces itself.

The pgvector wrinkle

That last check is the one with the most consequence, because on Postgres the retrieval layer is frequently not somewhere else. Teams install pgvector precisely so they do not have to stand up a separate vector database, which means the embeddings and the source data end up in the same instance, often the same schema, sometimes the same table.

That is an entirely reasonable architecture, and it collapses a distance that other platforms preserve. On a warehouse, the raw estate and the AI corpus are usually separated by at least a pipeline, and that pipeline is a place where a filter can live. When the corpus is a column beside the data it was derived from, the only thing standing between an undocumented PII column and an embedding of it is whoever wrote the ingestion query. Knowing which tables carry vector columns, and what else is sitting in those tables, is not a nice-to-have on Postgres. It is the shape of the risk.

One role, no row access

A readiness audit is only worth running if the access it asks for is boring. On Postgres, a MortarIQ scan needs a connection string and a dedicated read-only role:

CREATE ROLE mortariq_reader LOGIN PASSWORD '<strong-password>';
GRANT CONNECT ON DATABASE <db> TO mortariq_reader;
GRANT USAGE ON SCHEMA <schema> TO mortariq_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA <schema> TO mortariq_reader;

The fourth line deserves an explanation rather than a footnote, because it is the one your security reviewer will stop on. On Databricks this assessment needs no SELECT at all. On Postgres it does, for a structural reason: Postgres only exposes catalog metadata for objects the querying role is permitted to see. A role without SELECT does not get a redacted view of your schema, it gets an empty one, and the scan would confidently report a tiny, tidy estate that does not exist.

So the grant makes the catalog visible, and the assessment still never issues a SELECT against your tables. That is a real distinction, and it is also exactly the kind of claim that deserves no benefit of the doubt: the exact SQL each connector runs is published and generated from source, so you can read the queries before granting anything. If the database is not reachable from the internet, the CLI runs the same assessment inside your network and never opens a port.

What Postgres cannot tell you, and where it wins

Core Postgres has no column-masking catalog. Snowflake has masking policies, Databricks has column masks, and Postgres has neither, which means there is no honest way to measure whether sensitive columns are protected. So the assessment does not pretend: the column-masking requirement reports not assessable and returns an inventory of PII-candidate columns instead, identified by naming patterns in the catalog. Candidate is the operative word. A column called email is a strong hint and not a finding, and a scan that never reads values cannot promote it to one.

There is also no lineage. A warehouse can often tell you where a table came from; Postgres has no equivalent, and anything claiming otherwise on core Postgres is inferring, not reading.

The compensation is real, though, and it runs the other way. Postgres has had row-level security since 9.5 in 2016, years before the major warehouses added equivalents, and teams that adopted it did so in the application layer where the access decisions actually live. When an estate scores well on pg_policiescoverage, it is usually not a governance initiative — it is a product requirement that happened to leave excellent evidence behind. That is the rare case where the operational origin of a Postgres database makes it more ready than a warehouse, not less.

What to expect in a Postgres estate

The recurring shape is a database that is structurally excellent and semantically empty. Constraints are in good order, because the application would break otherwise. Primary keys are nearly universal. Foreign keys are common. Types are precise. And column comments are close to zero, because a comment has never once made an application work.

That combination is specific to operational databases and it is exactly the profile that fails an AI workload. The schema is trustworthy and unexplained: status is an integer with five valid values documented in a TypeScript enum three repositories away, and flags is a bitfield whose meaning left with a contractor. A human engineer navigates this fine, because they can read the application code that gives the columns meaning. A retrieval pipeline cannot. It sees a well-formed table it has no way to interpret, and interprets it anyway.

The second pattern is scope. Because Postgres is an application database, its estate contains things a warehouse would never hold: session tables, job queues, framework migration tables, soft-deleted rows that are still rows. None of it belongs in an AI corpus, and none of it is labelled as excluded, because nothing ever needed to exclude it before.

The honest boundary

A metadata scan has a ceiling on Postgres, same as anywhere: it cannot verify values. A comment can be stale, a constraint can be declared and then worked around in application code, a fresh-looking table can be full of duplicates, and a scan that never reads rows cannot tell you otherwise; this one never reads rows by design. Value-level truth needs tooling with data access inside your perimeter, and the two views complement rather than compete. What the readiness assessment gives you is the structural truth of the estate: what exists, what is documented, what is constrained, what is fresh, what carries a policy, what already holds embeddings, and what your chosen workload requires that is missing. It prepares evidence. It does not certify compliance, and no tool that reads only metadata honestly can.

Gartner's 2025 AI Hype Cycle analysis (July 2025) found that 57% of organizations estimate their data is not AI-ready. On Postgres the diagnosis is rarely that the data is bad. It is that the database was never asked to describe itself — and the catalog can tell you, in minutes, exactly how much of that description is missing.

Frequently asked questions

What access does an AI readiness scan need on PostgreSQL?

A dedicated read-only role with CONNECT on the database, USAGE on the schemas in scope, and SELECT on their tables. The SELECT grant is unavoidable on Postgres and worth understanding: Postgres only exposes catalog metadata for objects a role is permitted to see, so without it the scan would report an empty estate rather than an honest one. The grant makes the catalog visible; the assessment still never issues a SELECT against your tables, and the exact SQL each connector runs is published so a security team can verify that rather than take it on trust.

Does the scan read any rows from my PostgreSQL tables?

No. Every query targets the catalog: information_schema.columns and tables for structure and types, information_schema.table_constraints for primary and foreign keys, pg_description for column comments, pg_index and pg_tables for access optimization, pg_policies for row-level security, and a udt_name lookup for pgvector columns. Column names are read; column values are not. The PII inventory is built entirely from naming patterns in the catalog, which is also why it is a candidate list rather than a finding.

Can a readiness scan check whether PII is masked in Postgres?

Not on core Postgres, and the assessment says so rather than guessing. Postgres has no native column-masking catalog the way Snowflake or Databricks does, so the column-masking requirement reports not assessable and returns an inventory of PII-candidate columns instead. Row-level security is the exception and is genuinely measurable: pg_policies shows which tables carry an RLS policy, and this is one area where a well-run Postgres estate scores above the warehouses.

Does this work with RDS, Aurora, Cloud SQL, Neon, and Supabase?

Yes. The assessment runs against self-hosted Postgres and the managed flavors: Amazon RDS and Aurora, Cloud SQL, Azure Database for PostgreSQL, Neon, Supabase, Railway, and Heroku. Supabase has one wrinkle worth knowing in advance: connect with the Session pooler string rather than the direct db.<ref>.supabase.co hostname, which is IPv6-only unless the project has the IPv4 add-on; the Session pooler works from any IPv4-only network (see Supabase docs). If the database is not reachable from the internet at all, the CLI runs the same metadata-only assessment from inside your network.

Get your readiness score.

Connect read-only credentials and see your score and biggest blocker in minutes. Metadata only. Starts free.

Run the free scan

Or see a sample report on a fictional estate

This is the fourth platform in this series, after Snowflake, BigQuery, and Databricks. It runs against self-hosted Postgres and the managed flavors — RDS, Aurora, Cloud SQL, Azure Database for PostgreSQL, Neon, Supabase, Railway, Heroku. Want to see the output before granting anything? Read a sample readiness report built entirely from metadata, or the connection guide for the exact setup steps.

© MortarIQ
AboutBlogDocsFAQSecurityPrivacyTermsDPA

All product names, logos, and brands are property of their respective owners and are used for identification purposes only.