Skip to main content
Version: Draft

Requirements

PostGraphile is packaged as a Node.js module, you can install it with any Node package manager such as npm or yarn (depending on your preference) — users tend to have fewer issues with yarn, so we recommend it (but if you use yarn "berry", we recommend using nodeLinker: node-modules in your .yarnrc.yml).

We recommend using the latest LTS version of Node.js and PostgreSQL, but we have limited support for older versions, so long as they are still LTS. Using newer released versions should generally work fine (we don't recommend using with alpha/beta versions though), but if there's any issues let us know in an issue. PostGraphile supports Node.js 22+ and recommends Node.js 24+ for the best experience (including built-in type stripping for .ts files).

Your PostgreSQL database

These aren't exactly "requirements", but they will impact your PostGraphile experience.

  • Use primary keys: if you don't have primary keys on your tables then they won't get the nodeId globally unique identifier interface. Further if you don't have unique constraints then you won't be able to use the automatic update/delete mutations (since they need a way to identify the row to update/delete).
  • Use foreign keys: we infer relations between tables using foreign key constraints; if you don't use these constraints then we won't know there's a relationship between the tables. There are plugins to get around this (using smart comments) but it's highly recommended that you use PostgreSQL's built in relations support.
  • Don't use column-based SELECT grants: column-based grants work well for INSERT and UPDATE (especially when combined with PgRBACPlugin!), but they don't make sense for DELETE and they cause issues when used with SELECT. You cannot SELECT * which makes your life harder, and rules out some of our possible optimization strategies. Computed columns (where we pass the entire record to the function) typically have issues with column-based SELECT grants. It's recommended that you instead split your tables on permission boundaries and use one-to-one relations to join them together again — this also makes writing your RBAC/RLS policies simpler. If you want to omit a column entirely then you can give it the @behavior -* smart tag.
  • Function restrictions: we have pretty good support for PostgreSQL functions, but there's some common function restrictions you should check out.
  • Use unique constraints rather than unique indexes when appropriate: we use unique constraints to create mutations such as updateUserByUsername; note that "PostgreSQL automatically creates a unique index when a unique constraint or primary key is defined for a table." -- PG docs
  • Use the defaults for formatting output; we only run tests for the defaults so if you change them you may face issues. (You may change intervalstyle since we have specific handling code for that.)
  • Use UTF8 encoding: GraphQL operates over the UTF8 character set, using different encodings may impact your ability to store/retrieve certain values.

On top of this, standard PostgreSQL best practices apply: use indexes carefully for performance, use constraints and triggers to ensure your data is valid and consistent, etc.

Unique indexes

PostGraphile treats unique constraints as data guarantees, but unique indexes as optimisations that you might remove later; this is why it only creates accessors and mutations from unique constraints by default.

If your tooling does not understand this subtlety and can only create unique indexes, you might want to opt in to treating unique indexes as if they were constraints by using a plugin. We've included an example plugin to achieve this below.

Click to view plugin to treat unique indexes as constraints.
warning

Only use this if you are confident that all of your unique indexes are true constraints.

plugins/PgUniqueIndexesPlugin.ts
// WARNING: this plugin was reworked from a GitHub issue and is currently untested
// Ref: https://github.com/graphile/crystal/issues/2054

export const PgUniqueIndexesPlugin: GraphileConfig.Plugin = {
name: "PgUniqueIndexesPlugin",
version: "0.1.0",
description: "Treats unique indexes as if they were unique constraints.",
gather: {
hooks: {
async pgTables_PgResourceOptions(_, event) {
const { pgClass, resourceOptions } = event;

if (pgClass.relkind !== "r") return;
if (resourceOptions.parameters) return;
if (!resourceOptions.uniques) return;

const mutableUniques = [...resourceOptions.uniques];
resourceOptions.uniques = mutableUniques;

const indexes = pgClass.getIndexes().filter((idx) => idx.indisunique);

const existingUniqueAttributeSets = new Set(
mutableUniques.map((u) => JSON.stringify(u.attributes)),
);

for (const idx of indexes) {
const attributes = idx.getKeys();
if (!attributes.every((a) => a != null)) continue;
const attributeNames = attributes.map((a) => a.attname);
const hash = JSON.stringify(attributeNames);
if (existingUniqueAttributeSets.has(hash)) continue;
existingUniqueAttributeSets.add(hash);

const { description, tags = Object.create(null) } =
idx.getIndexClass()?.getTagsAndDescription() ?? {};

mutableUniques.push({
isPrimary: idx.indisprimary ?? false,
attributes: attributeNames,
description,
extensions: { tags },
});
}
},
},
},
};

Node.js: use the active LTS

PostGraphile supports Node.js 22+ but recommends Node.js 24+ where possible. We only support LTS versions of Node.js. Once a Node.js version reaches end-of-life we no longer support it, and any future patch release may be incompatible with it. We do not see this as a violation of semver — once a Node.js version reaches EOL no reasonable user should use it, and as such a change to drop support for it is not a breaking change for reasonable users.

TypeScript v5.0.0+ (optional)

We recommend that you use TypeScript for the best experience — auto-completion, inline documentation, etc.

You do not need to use TypeScript to use PostGraphile, but if you do then you must use a version from TypeScript v5.0.0 upward and configure it to support the exports property in package.json, you can do so by adding this to your TypeScript configuration:

    "moduleResolution": "node16", // Or "nodenext"

Instead of configuring TypeScript manually, we recommend that you use the appropriate TSConfig Base for your Node.js version.

tsconfig.json
{
"extends": "@tsconfig/node24/tsconfig.json"
}

If you want to use type stripping (which limits the syntax you can use, but means Node can run your TS files directly), then also add the @tsconfig/node-ts preset and make sure you're running Node 24+ and TypeScript v5.8.0+. To use the LTS version of Node along with type stripping:

tsconfig.json
{
"extends": [
"@tsconfig/node-lts/tsconfig.json",
"@tsconfig/node-ts/tsconfig.json"
]
}

Our adherence to semver does not cover types — we may make breaking changes to TypeScript types in patch-level updates. The reason for this is that TypeScript itself is ever-changing, and the libraries we depend on often make breaking type changes, forcing us to do so too. Further, improvements to types are generally a good thing for developer experience, even if it might mean you have to spend a couple minutes after updating to address any issues.

However, we try and keep the TypeScript types as stable as possible, only making breaking changes when their benefits outweigh the costs (as determined by our maintainer), and we do our best to detail in the release notes how to deal with these changes (if any action is necessary).

Not using TypeScript?

You do not need to use TypeScript to use PostGraphile, but without it you will find editors such as VSCode will highlight your import paths with error notifications. To stop this, you can add the following to jsconfig.json:

jsconfig.json
{
"compilerOptions": {
"moduleResolution": "node16"
}
}

PostgreSQL: use latest

For best results we recommend you use the latest stable release of PostgreSQL that we officially support, however PostGraphile should run well on any earlier version of PostgreSQL that has not yet reached end-of life.

Once a PostgreSQL version reaches end-of-life we no longer support it, and any future patch release may be incompatible with it. We do not see this as a violation of semver — once a PostgreSQL version reaches EOL no reasonable user should use it, and as such a change to drop support for it is not a breaking change for reasonable users.

Currently versions 12 and 13 are EOL according to the PostgreSQL project. They work with PostGraphile and are exercised in CI at time of writing; however, they are not officially supported and may be removed from CI if they hold us back.

PG 12 [unsupported - EOL Nov 2024]

Works well; but not officially supported and support may be dropped in a patch release.

PG 13 [unsupported - EOL Nov 2025]

Works well; but not officially supported and support may be dropped in a patch release.

PG 14 [officially supported]

Works well.

PG 15 [officially supported]

Works well.

PG 16 [officially supported]

Works well.

PG 17 [officially supported]

Works well.

PG 18 [officially supported]

Works well.

Operating system

PostGraphile is developed on *nix operating systems like GNU/Linux and macOS. As far as we know it works on Windows, but since no-one in the core team uses Windows for development our Windows support is "best effort" rather than "officially supported" — please file an issue if you have problems, but we may be asking for your help to fix/test them!