Postrust vs PostGraphile

PostGraphile generates a GraphQL API from a PostgreSQL schema and puts most of its effort into the quality of that schema and the plan behind it. V5's Gra*fast* engine plans a query once and executes it with far fewer round trips than a naive resolver tree.

It is also the most customisable of these tools. If you want to reshape the generated schema, PostGraphile expects that and has a plugin system built for it.

PostGraphile is written in
TypeScript / Node.js
Licence
MIT
Version compared
V5

Feature comparison

Where a capability has a condition attached, the condition is in the cell.

FeaturePostrustPostGraphile
GraphQL from the schemaYesYes
REST APIYes, PostgREST-compatibleNot supported
SubscriptionsOver LISTEN/NOTIFYBuilt in over LISTEN/NOTIFY; you define the fields
Schema customisationNot extensible at runtimePlugin system, the main design goal
Relay supportNoYes
PermissionsPostgreSQL roles and RLSPostgreSQL roles and RLS
RuntimeSingle static binaryNode.js
Custom logicRust handlers, or SQL functionsTypeScript plugins, or SQL functions
LicenseMITMIT

Measured performance

Produced by scripts/bench-compare.sh, which starts both servers as containers against the same database and runs the same load against each. Where PostGraphile is faster, that is what the table says.

GraphQL

ScenarioPostrust req/sPostGraphile req/sPostrust p95PostGraphile p95Difference
single row by primary key12,44010,2315.1 ms6.7 ms1.2× faster
25-row page8,4776,5937 ms10.2 ms1.3× faster
25-row page + embed5,1933,49511.4 ms16.5 ms1.5× faster

Image size and memory

PostrustPostGraphile
Container image, on disk168MB2.27GB
Memory, before serving a request1.9 MB110.1 MB
Memory, after the benchmark14.8 MB242.1 MB

Memory is resident set size, read the same way for every tool. Image sizes are for the Debian-based build these figures come from. The Alpine build of the same code is 31.7MB.

How this was measured

  • Every server runs as a container on one docker network against the same PostgreSQL instance and the same dataset. No tool gets to skip container overhead.
  • Each tool keeps its own default connection pool and worker settings. Tuning one and not the others measures the tuning, not the tool.
  • Requests are expressed in each tool's own dialect, because the dialects differ. The work asked of PostgreSQL is the same.
  • Every target is warmed before any of them is measured, and the database cache is populated first, so no tool pays to warm the cache for the ones measured after it.
  • Each figure is the median of several runs rather than the best of them, because a best-of-N reports whichever tool got the quietest moment on the machine.
  • These are single-machine numbers from a laptop. They are useful for comparing the tools against each other, not for capacity planning.

Darwin 25.2.0 arm64 · PostgreSQL postgres:16 · bench_items 100000 rows, bench_reviews 300000 rows · 3000 requests at concurrency 50, median of 5 runs after 500 warm-up requests. Full benchmark method

When PostGraphile is the better choice

  • You want to shape the GraphQL schema rather than accept what was generated. This is PostGraphile's central strength and Postrust has no answer to it.
  • Your team writes TypeScript and wants API extensions in the same language as the rest of the stack.
  • You want a Relay-compliant schema, or the connection and node-id conventions that come with it.
  • GraphQL is the API and REST is not needed.

When Postrust fits better

  • You want one process serving both REST and GraphQL.
  • You would rather deploy a static binary than a Node runtime.
  • The generated schema is fine as generated and extensibility is not what you are paying for.

Questions

Why do the GraphQL queries differ between the two in the benchmark?

Field names are inflected differently: Postrust exposes bench_items where PostGraphile exposes allBenchItems with a nodes wrapper. The request asks PostgreSQL for the same rows either way, and both queries are in the benchmark script.

Is Gra*fast* faster than what Postrust does?

Look at the measured table on this page rather than taking either project's word for it. Gra*fast* is a serious piece of engineering and the numbers are the numbers.

Try it against your own schema

Point it at a database and see what it generates. That is a shorter path than reading a comparison table.