Open-source project
supabase/pg_graphql avatar
supabase/pg_graphql

pg_graphql: A GraphQL Layer That Lives Inside PostgreSQL

GraphQL support for PostgreSQL

3,355 stars143 forksRustApache-2.0

At a glance

What is it?
pg_graphql reflects a GraphQL schema from an existing SQL schema and resolves queries on the database server itself. It suits Postgres-first teams who want GraphQL without a separate Node or Rust service in front of the database.
Who is it for?
Adopt pg_graphql if your schema is already the source of truth and you want GraphQL without a separate resolver service; skip it if you need custom resolver logic, subscriptions or a schema that is not derived from tables.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What pg_graphql solves, and for whom

Most GraphQL servers sit in front of a database. A Node process holds the schema, resolvers translate fields into SQL, and the database answers. pg_graphql removes that process. The README states that it "reflects a GraphQL schema from the existing SQL schema" and keeps "schema translation and query resolution neatly contained on your database server". Any language that can open a PostgreSQL connection can then send GraphQL, with no additional servers, processes, or libraries.

The audience is narrow and specific. It fits teams whose PostgreSQL schema is the authoritative model, who are comfortable with the generated naming conventions, and who want one deployable instead of two. It does not fit teams that need hand-written resolvers calling third-party APIs, or a schema that diverges from the tables. If your GraphQL types are a curated view of many sources, this extension is the wrong shape: it derives the schema from tables, foreign keys, enums and comments, and that is the whole contract.

How the schema reflection actually works

The extension reads the SQL schema and produces GraphQL types. Each table receives an entrypoint in the top-level Query type, described in the README as "a pageable collection with relationships defined by its foreign keys". Tables also receive Mutation entrypoints that enable bulk insert, update and delete. A foreign key becomes a relationship field, so joins are expressed in the GraphQL query rather than in resolver code.

Naming is generated, not hand-written. The README's quickstart adds a schema comment to turn on inflection: it "automatically renames snake_case to PascalCase for type names, and snake_case to camelCase for field names". That single comment changes every generated name, which is convenient until you have an existing client expecting different casing.

The implementation is a Rust extension built with pgrx. The Cargo.toml declares crate-type cdylib and pins pgrx at =0.19.2, with feature flags pg14 through pg18 and pg18 as the default feature. The extension is compiled against a specific PostgreSQL major version, so the binary you build is tied to that version. That is the mechanism behind most installation failures.

Installing pg_graphql and running a first query

There is no package manager step in the README. The project points to its documentation site and source repository, and the repository ships a docker-compose.yaml that builds a database image from ./dockerfiles/db/Dockerfile with PG_VERSION 17, maps port 5406 to 5432, and loads ./dockerfiles/db/setup.sql as an init script. The same compose file runs PostgREST on port 3001 and an nginx-served GraphiQL on port 4000. That is the shortest path to a working instance without compiling pgrx yourself.

If you build from source, the feature flags in Cargo.toml decide the target server. Selecting the wrong one produces an extension that will not load.

bash
docker compose up

The README's quickstart then defines the schema. This is the DDL from the README, including the comment that enables inflection.

sql
create table account(
    id serial primary key,
    email varchar(255) not null,
    created_at timestamp not null,
    updated_at timestamp not null
);

COMMENT ON SCHEMA public IS e'@graphql({"inflect_names": true})';

After the extension is enabled and the schema exists, the README states each table appears as a pageable collection under Query. A first query against the account table looks like this.

sql
select graphql.resolve($$
  {
    accountCollection(first: 10) {
      edges {
        node { id email }
      }
    }
  }
$$);

The response is JSON. If the extension is not installed in the database, or was compiled for a different PostgreSQL major version, the function call fails before any GraphQL parsing happens. That is the first thing to check when nothing works.

Where pg_graphql stops being the right tool

The extension derives everything from the SQL schema. That is a constraint, not a feature you can switch off. If you need a field that calls an external service, computes from request context, or merges two unrelated sources, there is no resolver hook in the README's model. You would be adding a GraphQL server in front anyway, at which point pg_graphql is redundant.

Naming is the second friction point. Inflection renames types and fields automatically, and the README documents the behaviour on its configuration page rather than offering per-field overrides. Teams with an established client contract will either accept the generated names or write translation code, which defeats part of the purpose.

Version coupling is the third. The Cargo.toml pins pgrx and exposes one feature per PostgreSQL major version. An extension built for pg17 will not load into a pg18 server. Upgrading PostgreSQL means rebuilding the extension against the matching feature flag, and the repository files do not describe a rollback path if a rebuilt extension misbehaves. The README does not document rollback.

Finally, the README does not mention subscriptions. If your clients depend on GraphQL subscriptions for live updates, this is not the layer that provides them.

pg_graphql compared with PostGraphile

PostGraphile is the closest well-known alternative and it appears in the related searches for this project. Both reflect a GraphQL schema from a PostgreSQL schema, so the pitch sounds similar. The difference is where the translation runs. PostGraphile is a Node server that connects to PostgreSQL and compiles GraphQL into SQL from outside the database. pg_graphql runs inside the database as an extension, so there is no Node process, no connection pool between the API layer and the database, and no separate deployable to keep in sync with schema changes.

That difference cuts both ways. PostGraphile's position outside the database gives it a place to put custom resolver logic, plugins and middleware without touching the extension's Rust code. pg_graphql has no equivalent extension point here: the schema is the API, and changing the API means changing the tables or the schema comment. If your team already runs Node and expects to write resolver code, PostGraphile asks less of you. If your team wants the database to be the only moving part, pg_graphql is the smaller system.

Maintenance, licensing and upgrade cost

The repository is not archived and the last push was on 2026-09-03. Releases are not rapid: v1.6.0 on 2026-04-30, v1.6.1 on 2026-05-07, and v1.6.2 on 2026-08-26. The Cargo.toml version matches the v1.6.2 release tag, and pg_graphql.control sits at the repository root alongside sql/ and src/, which is the normal layout for a PostgreSQL extension.

The upgrade cost is dominated by the PostgreSQL major version, not by the extension's own release cadence. Because pgrx is pinned with = and each PostgreSQL version is a separate feature, moving from pg17 to pg18 in your cluster requires a rebuild with the pg18 feature and a reinstall of the extension into the new server. That is a build pipeline concern as much as a database concern.

Licensing is Apache-2.0, per the LICENSE file referenced in the README badge. Apache-2.0 is permissive and includes an explicit patent grant, which matters if you redistribute a bundled build. This is a description of the licence identifier, not legal advice; have your own counsel review distribution obligations if you ship the extension inside a product.

Editorial conclusion

Adopt pg_graphql if your schema is already the source of truth and you want GraphQL without a separate resolver service; skip it if you need custom resolver logic, subscriptions or a schema that is not derived from tables. Before committing, verify the pg_graphql extension is available for your exact PostgreSQL build, check how the default inflection comment behaves on your naming, and confirm that the version you install matches the pg_graphql.control file in the release you download.

Frequently asked questions

Can GraphQL be used with PostgreSQL?

Yes. pg_graphql adds GraphQL support directly to a PostgreSQL database by reflecting a GraphQL schema from the existing SQL schema and resolving queries on the database server.

What is pg_catalog in PostgreSQL?

The README does not describe pg_catalog, and pg_graphql's documentation covers schema reflection from user tables and comments rather than system catalog internals.

Is PostgreSQL obsolete?

No. pg_graphql is built as a PostgreSQL extension targeting PostgreSQL 14 and newer, with feature flags for pg14 through pg18 in its Cargo.toml.

What does pg_stat_activity show?

The README does not cover pg_stat_activity. It focuses on reflecting a GraphQL schema from an existing SQL schema and resolving queries on the database server.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. supabase/pg_graphql on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/supabase-pg-graphql.svg)](https://hysenlabs.com/projects/supabase-pg-graphql)