Self-hosted service
PostgREST/postgrest avatar
PostgREST/postgrest

PostgREST: a REST API generated directly from a PostgreSQL schema

REST API for any Postgres database

27,685 stars1,229 forksHaskellMIT

At a glance

What is it?
PostgREST turns an existing PostgreSQL database into an HTTP API without writing a server. This review covers how the request path works, where the schema-as-contract model breaks down, and what to check before adopting it.
Who is it for?
Adopt PostgREST when your team is comfortable owning schema design, roles and row level rules in PostgreSQL itself, and when you want the API surface to follow the database rather than the other way round. Do not adopt it if you need server-side orchestration between several data stores, custom non-HTTP protocols, or long-lived business logic that cannot live in SQL.
Can I use it commercially?
Yes. MIT 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 3 days ago.
What is it written in?
Mainly Haskell, according to GitHub's language statistics.

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

Editorial analysis

The problem PostgREST removes: hand-written CRUD servers

Most backend projects spend their first weeks writing the same layer again: route handlers that parse a query string, translate it into SQL, serialize rows to JSON, and check permissions. PostgREST deletes that layer. The README states the goal plainly: it "serves a fully RESTful API from any existing PostgreSQL database" and claims to be "a cleaner, more standards-compliant, faster API than you are likely to write from scratch."

The intended audience is teams that already treat PostgreSQL as the source of truth and are willing to keep it there. If your data model lives in the database and your access rules can be expressed as roles and grants, PostgREST gives you an HTTP surface over it. If your business logic is spread across a service layer in Python or Node, PostgREST does not replace that; it sits underneath it and exposes the tables you choose.

The trade is explicit. You stop writing endpoints and start writing schema. Tables, views, functions and constraints become the API contract, and the server derives routes from them.

How a request becomes SQL inside PostgREST

The architecture is unusual for an API server because the server holds very little state. According to the README, PostgREST is written in Haskell on the Warp HTTP server and uses the Hasql library to talk to PostgreSQL, keeping a pool of database connections and using the PostgreSQL binary protocol. The README also notes the server is "stateless to allow horizontal scaling."

What that means in practice: an incoming HTTP request is parsed into a query plan, executed against PostgreSQL under the identity of the authenticated user, and the response is produced largely by the database. The README lists the work delegated to SQL, including serializing JSON responses directly in SQL, data validation, authorization, combined row counting and retrieval, and posting data in a single command with returning *.

Authentication is handled by the server through JSON Web Tokens, and authorization is delegated to role information defined in the database. The README describes the result as "a single declarative source of truth for security": for the duration of a connection, the server assumes the identity of the authenticated user and cannot do anything that user could not do themselves.

Versioning follows the same logic. Instead of URL version prefixes, the README says PostgREST does versioning through database schemas, so underlying tables can be superseded and hidden behind public facing views. Metadata such as the number of rows returned is reported through range headers.

Installing PostgREST and making a first request

The README does not carry its own install steps. It points to the documentation for how to install PostgREST on your platform and adds that Docker is a supported route, with the install page at docs.postgrest.org covering the Docker section. The repository also publishes an image on Docker Hub under the postgrest organization. Because the README gives no container command, no configuration keys and no port, the only command it does show is the help flag, which confirms a working binary:

bash
postgrest --help

After that, the README sends you to the documentation at postgrest.org for the API guide, and the docs tree in the repository (the docs/ directory) is where those pages are maintained. A first real use is to read a table: the API maps schema objects to paths, so a request to a table returns JSON rows, and the number of rows returned is reported through range headers rather than a wrapper object. The README points to the API guide for the full query syntax.

The self-documentation path is worth trying early. PostgREST generates OpenAPI output for the live API, and the README suggests rendering it with a tool such as Swagger-UI to get interactive documentation and demo requests against the running server. That gives you a check that the schema you exposed is the schema clients will see.

Where the schema-as-API model gets in the way

The same design that removes boilerplate also removes places to put logic. PostgREST does not give you a general application layer. If a request needs to call a payment provider, fan out to a second database, or apply a transformation that is awkward in SQL, that work has to live somewhere else, either in a PostgreSQL function or in a separate service in front of PostgREST. Teams that expect a middleware hook will not find one in the README.

Schema changes become API changes. Because routes are derived from tables and views, a renamed column or a dropped view is not an internal refactor; it is a breaking change for clients unless you have already hidden the table behind a view, which is exactly what the versioning section recommends. The discipline has to be adopted before the first release, not after.

Authorization is only as good as your role layout. The README is direct that the server cannot exceed the permissions of the authenticated user, which is a strong property, but it also means every access rule must be expressible as grants and database-side policy. A team with an ad hoc grant setup will expose more than it intends. The README does not describe a built-in audit trail or request-level policy editor, so reviewing grants is your responsibility.

Finally, the project is Haskell. That is a strength for the runtime and a barrier for contributors. A team that wants to patch server behaviour in place needs Haskell skills; otherwise they are consumers of releases, not maintainers of a fork.

PostgREST compared with an ORM-backed framework

The natural alternative is a conventional web framework such as FastAPI with an ORM, where you define models in application code, write route handlers, and generate SQL from those models. The direction of derivation is reversed. In a framework, the application code is the contract and the database follows it. In PostgREST, the database is the contract and the HTTP surface follows it.

That difference decides several things at once. With a framework you can insert arbitrary Python between the request and the query, which makes third-party integrations and multi-store orchestration straightforward. With PostgREST, that space does not exist, and the equivalent work goes into database functions or a separate service. In exchange, PostgREST gives you one place to define permissions and constraints, and the README argues this is why "no application can corrupt your data (including your API server)."

A framework also lets you evolve the API independently of the schema, which PostgREST deliberately does not. If your team ships schema migrations and API changes on different schedules, the framework model is easier. If your team already reviews migrations carefully and wants API changes to be visible in the same review, PostgREST fits better.

Maintenance, releases and the MIT licence

The repository is not archived, and the last push was on 2026-09-19. Releases arrive on more than one line at once: v16.3 on 2026-09-11, v16.2 on 2026-08-21, and a v14.18 release on 2026-09-10. The presence of a maintained v14 line matters if you are pinned to an older major version, because it suggests backports are still being cut rather than only the newest branch receiving fixes.

Upgrade cost depends on how much of your API is derived from schema objects. A release that changes how a view or function is exposed can change client-visible behaviour without any change to your own code, so reading the changelog before bumping is not optional. The repository keeps a CHANGELOG.md at the top level, and the README links to it. Configuration is a separate concern: the project is configured through a file rather than compiled per deployment, so a schema change generally means reloading the server rather than rebuilding it.

PostgREST is MIT licensed. That is permissive: you can use it commercially, modify it, and redistribute it, provided the licence and copyright notice are preserved. It is not a copyleft licence, so it does not force you to publish your own application code. This is a description of the licence text, not legal advice; confirm obligations with your own counsel if you redistribute a modified binary.

Editorial conclusion

Adopt PostgREST when your team is comfortable owning schema design, roles and row level rules in PostgreSQL itself, and when you want the API surface to follow the database rather than the other way round. Do not adopt it if you need server-side orchestration between several data stores, custom non-HTTP protocols, or long-lived business logic that cannot live in SQL. Before committing, verify three things: that your PostgreSQL version is supported by the release you intend to run, that your role and grant layout is explicit enough to express every access rule you need, and that your deployment can reload configuration when the schema changes, since the API is derived from the schema rather than from application code.

Frequently asked questions

What is PostgREST and what does the name stand for?

PostgREST is a server that exposes a RESTful HTTP API over an existing PostgreSQL database. The name combines PostgreSQL with REST, and the README describes its purpose as serving a fully RESTful API from any existing PostgreSQL database.

How do I install PostgREST on Ubuntu or with Docker?

The README directs readers to the documentation for how to install PostgREST on each platform and notes that Docker is also supported. The repository publishes an image on Docker Hub under the postgrest organization, and the docs install page has a Docker section.

How do I use PostgREST?

You point it at a PostgreSQL database and it derives HTTP routes from the tables, views and functions you expose. The README gives postgrest --help as the first command, and the API guide at postgrest.org covers the query syntax for reading and writing rows.

How does PostgREST handle authentication and authorization?

It handles authentication through JSON Web Tokens and delegates authorization to role information defined in the database. The README states that the server assumes the identity of the authenticated user and, for the duration of the connection, cannot do anything that user could not do themselves.

Is PostgREST the same thing as PostgreSQL?

No. PostgreSQL is the database; PostgREST is a separate server that sits in front of it and turns schema objects into HTTP endpoints. The README describes it as serving an API from an existing PostgreSQL database rather than replacing it.

Official sources

  1. License: MIT
  2. PostgREST/postgrest on GitHub
  3. Project website
  4. README
  5. Releases
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/postgrest-postgrest.svg)](https://hysenlabs.com/projects/postgrest-postgrest)