Postrust vs PostgREST
PostgREST is the project that established this idea: point a server at a PostgreSQL schema and get a REST API, with permissions left to the database. Postrust follows its URL grammar deliberately, so `?select=`, `?order=`, the filter operators and the `Prefer` headers mean the same thing in both.
How closely is measured rather than asserted: replaying PostgREST's own test cases against both servers gives 96.7% agreement on status and body, and 94.9% once every header that is part of the answer is compared too. The [conformance report](/docs/conformance/postgrest) says what that covers and where the two differ on purpose.
The differences are not in the query language. They are in what ships in the process and what the deployment looks like.
- PostgREST is written in
- Haskell
- Licence
- MIT
- Version compared
- v16.1
- Their site
- postgrest.org
Feature comparison
Where a capability has a condition attached, the condition is in the cell.
| Feature | Postrust | PostgREST |
|---|---|---|
| REST API from the schema | Yes | Yes |
| Query grammar | PostgREST-compatible | The reference |
| GraphQL | Built in, with the admin-ui build feature | Not supported |
| Subscriptions | GraphQL subscriptions over LISTEN/NOTIFY | Not supported |
| Custom endpoints | Axum handlers in the same binary, needs a rebuild | SQL functions via /rpc |
| Business logic | SQL functions, or Rust in-process | SQL functions |
| Runtime | Single static binary | Single binary |
| AWS Lambda | Native, via the postrust-lambda crate | Container images |
| License | MIT | MIT |
| Maturity | Young. Smaller surface, fewer users. | Years of production use, large community |
When PostgREST is the better choice
- You need the full PostgREST surface. Postrust implements the parts of it that are exercised by its test suite, and PostgREST has had years to grow behaviours that Postrust has not reimplemented.
- You want the answer to an obscure question to already exist. PostgREST's documentation and issue history cover ground a young project has not.
- REST is all you need, and a second API surface is weight rather than value.
- You would rather run software that many organisations have already run in production.
When Postrust fits better
- You want REST and GraphQL from one process rather than two deployments.
- You are deploying to Lambda and cold start matters.
- You want to add an endpoint in Rust next to the generated API instead of pushing everything into SQL.
Moving from PostgREST
- The URL grammar is the same, so existing query strings generally work unchanged.
- Configuration uses the same `PGRST_*` environment variable names, including `PGRST_DB_ANON_ROLE` and `PGRST_JWT_SECRET`.
- Tables are mounted under `/api` by default rather than at the root. Check your base URL before assuming a 404 is something worse. CORS preflight and the `Allow` header work at both mounts.
- NUMERIC columns come back as JSON numbers, as they do from PostgREST, though the scale can differ: 4.2000 where PostgREST gives 4.20. Both parse to the same value.
- Object keys come back alphabetically rather than in select order. Build with the compat-key-order feature to match PostgREST; it is off by default because it costs up to 15% on wide rows.
- `Location` is sent only for `Prefer: return=headers-only`, as PostgREST sends it. A caller taking the row back reads the key out of the body.
- `Prefer: tx=rollback` is not implemented. It is no longer reported as applied either, which it briefly was while committing the write.
- Postrust allows 30 seconds of clock skew on a token's `nbf` and `iat`, and none on its `exp`. PostgREST checks all three to the second.
- Verify the specific PostgREST features you depend on against Postrust's test suite before switching anything that matters. The conformance report says what is measured and where the two disagree on purpose.
Questions
Is Postrust a drop-in replacement for PostgREST?
For the query grammar and configuration, largely yes. For the whole feature surface, no. PostgREST has been developed for years and Postrust implements a subset. Test the endpoints you actually use.
Why does the same request need a different URL?
Postrust mounts generated routes under /api so custom routes and the admin UI can live alongside them without colliding with a table name.
Does Postrust support PostgREST's /rpc functions?
Yes. Functions in the exposed schema are callable, and that is also how vector similarity search works: the ordering happens inside a SQL function rather than through a query parameter.
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.