[HN Gopher] PostgREST - Serve a RESTful API from any Postgres da...
       ___________________________________________________________________
        
       PostgREST - Serve a RESTful API from any Postgres database
        
       Author : thunderbong
       Score  : 219 points
       Date   : 2022-12-29 13:04 UTC (9 hours ago)
        
 (HTM) web link (postgrest.org)
 (TXT) w3m dump (postgrest.org)
        
       | jmull wrote:
       | This is great in a lot of ways... A robust and far more
       | comprehensive version of something I do in db-based apps.
       | 
       | But...
       | 
       | I'm leery of basing the auth on postgres' auth. It just doesn't
       | seem up to expressing auth rules based on dynamic, app-specific
       | business rules. (Maybe I just don't know postgres' auth mechanism
       | well enough, though.)
       | 
       | Also, it's perhaps overly complicated in pointless ways. A _lot_
       | of this is mapping HTTP requests to SQL... why not just accept
       | SQL and cut out all the unnecessary mapping? E.g. (real encoding
       | not show for clarity)
       | 
       | GET /theapi?sql=SELECT name, age FROM Person WHERE age >=
       | :1&p1=21
       | 
       | It seems crazy to me that it defines an entire HTTP-based query
       | language when SQL is right there to be used directly. Going to
       | SQL directly makes the API far simpler and more powerful.
        
         | ruslan_talpa wrote:
         | Because queries like this will kill any db, and you don't need
         | any privileges
         | 
         | SELECT crypt( encode(digest(gen_random_bytes(1024), 'sha512'),
         | 'base64'), gen_salt('bf', 20) )FROM generate_series(1, 1000000)
         | 
         | More explanations here https://www.freecodecamp.org/news/stop-
         | calling-postgrest-mag...
        
           | RhodesianHunter wrote:
           | Wouldn't it be much easier to disable/restrict certain sql
           | functions than do all of the http->sql mapping?
        
             | 411111111111111 wrote:
             | No, as there are countless ways to do the same.
             | Whitelisting is more effective if your code is running on
             | untrusted devices (frontend)
        
         | jmull wrote:
         | (Replying to own post)... thanks for the info about Postgres
         | RLS/row-level security. I guess I should not be so leery...
         | 
         | Looking at the last project I did, the app-level db-middleware
         | basically consists of two things: (1) plumbing boilerplate; (2)
         | enforces app-level auth rules, either by preventing
         | unauthorized operations or adding required filters. It looks
         | like I should probably look at RLE and can likely move anything
         | app-specific out of the middleware... which might let it
         | collapse to something entirely generic, and therefore entirely
         | reusable, and quite possibly something I don't have to write
         | myself.
        
         | aljarry wrote:
         | Why not just accept SQL? It's a matter of contract. With REST
         | APIs you specify a contract, it gets robust with time, and
         | other software can expect only what's in the contract. SQL
         | allows you to run arbitrary functions over data in the
         | database, so the whole schema and parts of the content in a way
         | become your contract - and your options to modify the schema
         | (or how you use the database) get very constrained.
        
           | dragonwriter wrote:
           | You can limit the visible schema, and thus the contract, per
           | role with SQL.
        
           | lelanthran wrote:
           | Yeah, but _this_ particular contract /API is pretty much "run
           | arbitrary select/insert/update/delete statements" _anyway!_
           | 
           | If you're using the postgrest language your options to
           | stabilise the interface are minimal anyway, so why not just
           | go with SQL and a whitelist?
        
           | officialchicken wrote:
           | >Why not just accept SQL?
           | 
           | Sanitize your inputs. I'll let little bobby tables link to
           | the XKCD
        
             | jmull wrote:
             | Who says don't sanitize inputs?
             | 
             | I'm just suggesting to not invent another query language,
             | especially where a rather obvious and natural one already
             | exists. You can and should sanitize untrusted input
             | regardless.
        
         | somat wrote:
         | I did the oppisite, I needed auth in a toy application I was
         | writing and was dreading writing and getting correct the whole
         | auth layer, so I thought to myself "self, postgres has a very
         | rich and through auth system, why not just use that" So I did
         | just that, I just pass the user credentials straight through to
         | to the database connection and let the database decide what
         | access the user gets to the data.
         | 
         | I am not sure if I would do this on something serious, but it
         | was a lot of fun to set up and saved me a lot of code by
         | reusing the comprehensive auth system that lives with the
         | actual data in question.
        
           | SoftTalker wrote:
           | The nice thing about this approach is that if you ever
           | develop other applications or front-ends to this database,
           | even in some other framework, the user auth and access rules
           | are already there.
           | 
           | It's been a while but does postgres let you re-auth on an
           | existing connection? I was able to do that in Oracle and that
           | allowed the use of connection pools rather than one
           | connection per user, which can become a bottleneck.
        
             | timando wrote:
             | You can use SET ROLE to become another user you have
             | permission to become (I think you need to be in the same
             | group or something) and RESET ROLE to go back to your
             | original user. If the initial connection was made with a
             | superuser or whatever, you could change to the user in the
             | connection manager and reset when the connection goes back
             | in the pool.
        
         | giraffe_lady wrote:
         | Postgres's row level security is absolutely sophisticated
         | enough to model arbitrary business security rules, probably
         | with more precision than almost any other auth system in
         | widespread use.
         | 
         | The issue with using it is more around its complexity, and
         | difficulty verifying the constraints without building custom
         | tooling for that. You almost need something like formal methods
         | to model your security model.
         | 
         | But it's an extremely powerful security tool that if you're
         | using postgres at all, is probably worth the effort spent
         | learning and maintaining. And if you're going that far, you
         | already have the skills and tools to run all your auth on it so
         | why not.
        
         | mildbyte wrote:
         | > why not just accept SQL and cut out all the unnecessary
         | mapping?
         | 
         | You might be interested in what we're building: Seafowl, a
         | database designed for running analytical SQL queries straight
         | from the user's browser, with HTTP CDN-friendly caching [0].
         | It's a second iteration of the Splitgraph DDN [1] which we
         | built on top of PostgreSQL (Seafowl is much faster for this use
         | case, since it's based on Apache DataFusion + Parquet).
         | 
         | The tradeoff for allowing the client to run any SQL vs a
         | limited API is that PostgREST-style queries have a fairly
         | predictable and low overhead, but aren't as powerful as fully-
         | fledged SQL with aggregations, joins, window functions and
         | CTEs, which have their uses in interactive dashboards to reduce
         | the amount of data that has to be processed on the client.
         | 
         | There's also ROAPI [2] which is a read-only SQL API that you
         | can deploy in front of a database / other data source (though
         | in case of using databases as a data source, it's only for
         | tables that fit in memory).
         | 
         | [0] https://seafowl.io/
         | 
         | [1] https://www.splitgraph.com/connect
         | 
         | [2] https://github.com/roapi/roapi
        
         | edmundsauto wrote:
         | I started using RLS in the Supabase offering and am now a total
         | fan of it. The supabase implementation, in particular, allows
         | you to expose the API to javascript which is cool! When you use
         | RLS that way, users get their own tokens to pass in the session
         | which limits the records in the db they have access to. So, if
         | you had a token stolen - the db would limit access to just that
         | account.
        
           | 015a wrote:
           | I'll second this; Supabase obviously popularized this whole
           | method of doing things, but once you've worked in it it
           | genuinely feels like the first step forward this industry has
           | had in five years.
           | 
           | One of my related pocket theories for the next ten years:
           | many people keep saying AI is going to eat jobs. Probably not
           | in engineering, at least for a while. But, we're starting to
           | see a new generation of software companies being built on
           | these kinds of truly new-way-of-doing-things technologies,
           | whether that's Postgrest/RLS, functions as a service, or no-
           | code tools like Retool. The productivity and efficiency
           | advantage that these companies will have over the incumbents
           | is incomprehensible.
           | 
           | I think a lot of legacy programmers won't adjust. Its hard to
           | admit to yourself that, honestly, we're spending most of our
           | days doing really freakin similar things as other engineers
           | as other companies; and we as an industry are starting to
           | solve these problems in more and more off the shelf ways.
           | 
           | Which is all to say, the three-fold theory/prediction is:
           | "backend engineering" will experience the least growth, or
           | even highest decline, in job openings of any software
           | engineering specialty over the next ten to fifteen years. The
           | effort involved in it will move left-and-right on the
           | spectrum: higher demand for frontend engineers, and higher
           | demand for DevOps/Cloud/etc. We will see billion dollar
           | software companies selling software as a service with the
           | vast majority of their "backend stack" having no code
           | (potentially some number of serverless functions to plug gaps
           | in no-code capabilities).
        
         | zX41ZdbW wrote:
         | We do it exactly this way in ClickHouse, and it works
         | perfectly.
         | 
         | You can even expose the database server to the internet and get
         | away with it if you configure the user access control, quotas,
         | and limitations on query complexity.
         | 
         | For example, these services:
         | 
         | https://play.clickhouse.com/play?user=play
         | 
         | https://ghe.clickhouse.tech/
         | 
         | https://pastila.nl/
         | 
         | https://aretestsgreenyet.com/
         | 
         | work this way by querying ClickHouse directly.
         | 
         | ClickHouse has REST API as a first-class feature.
        
           | yladiz wrote:
           | How do you determine query complexity? Do you go off of the
           | query plan or something like looking at the columns, joins,
           | etc.?
        
             | zX41ZdbW wrote:
             | There are only a few ways to determine it before running
             | the query - by the amount of rows/bytes to scan. But most
             | of the logic happens when query is already started - by the
             | possibility to stop it and throw exception if some metrics
             | became too large.
             | 
             | For example, this query will not start, because the amount
             | of rows to scan is greater than the limit: https://play.cli
             | ckhouse.com/play?user=play#U0VMRUNUICogRlJPT...
             | 
             | This query will fail with the error: https://play.clickhous
             | e.com/play?user=play#U0VMRUNUICogRlJPT...
             | Code: 160. DB::Exception: Estimated query execution time
             | (580.1882010677873 seconds) is too long. Maximum: 60.
             | Estimated rows to process: 9946243959: While executing
             | MergeTreeThread. (TOO_SLOW) (version 22.13.1.294 (official
             | build))
        
               | yladiz wrote:
               | I see. How do you determine when to kill the query before
               | running it then? Of course you could do "if the process
               | is running longer than X seconds kill and returns NNN
               | status code" but that feels somewhat wasteful if you can
               | be smarter when calculating the possible cost.
        
         | jeff-davis wrote:
         | If someone can write their own SQL, it would be trivial to DoS
         | the system. My guess is that the sublanguage is meant to
         | prevent that (but it's just a guess).
        
           | vbezhenar wrote:
           | This sublanguage will either be useless or will not prevent
           | DoS.
           | 
           | The proper way to prevent DoS is to implement some kind of
           | resource constraints for database queries.
           | 
           | AFAIK for postgres every connection launches a separate
           | database process. So in theory you can craft some kind of
           | ulimits or cgroup limits which would restrict a process to a
           | limited amount of RAM, CPU or IOPS. So if a given process
           | will eat more RAM, it'll be killed, if it wants to mine
           | bitcoins, it'll be throttled and killed by timeout
           | eventually.
        
             | taffer wrote:
             | > This sublanguage will either be useless or will not
             | prevent DoS.
             | 
             | Thinking in absolutes is not very helpful. PostgREST's API
             | is designed to prevent DoS and it is flexible enough for
             | most of your queries and when it isn't you can write a
             | custom function and PostgREST will expose it for you as
             | '/rpc/<my_function>'.
        
           | jmull wrote:
           | I think that's separate from the language though. I'm not
           | saying it would process any SQL... it can be restricted to
           | whatever function and SQL patterns that are deemed
           | acceptable. Realistically, though, your language is going to
           | be seriously inflexible or allow DoS... In fact I think
           | you're typically more likely to hit seriously inflexible
           | before excluding the possibility of DoS. So I think you're
           | going to need something besides the query language to prevent
           | DoS anyway.
        
         | [deleted]
        
         | smallnamespace wrote:
         | PostgreSQL row-level security (which PostgREST defers to) is
         | very flexible, more or less anything expressible as a SQL query
         | can be used to filter what the user can see.
         | 
         | You can see an example here:
         | https://postgrest.org/en/stable/auth.html#roles-for-each-web...
         | 
         | The main downside of RLS is that complex queries may require
         | hand-optimizing.
        
       | remram wrote:
       | How hard would it be to do the opposite? Expose a postgres API
       | that people can use by sending "SELECT" queries from psql or a
       | postgres connector?
       | 
       | Postgres has access control and an extension mechanism. Would the
       | easiest be to use a real postgres server?
        
         | awb wrote:
         | I thought about this too, but there are a few things to
         | consider:
         | 
         | 1) you need to separate any non-queryable data into it's own
         | table. So you'd need _public and _private tables for most data
         | types
         | 
         | 2) any type of filter query will need a JOIN, which leaves you
         | vulnerable to malicious long running queries
         | 
         | 3) some tables you don't want people to run SELECT * on,
         | otherwise they can get your entire site data
         | 
         | 4) you need to be really careful with DELETE, UPDATE and INSERT
         | queries to prevent malicious behavior
         | 
         | Maybe one way would be to write a bunch of whitelisted regex
         | patterns for allowed queries, but you're definitely playing
         | with fire allowing someone to send SQL queries to your DB.
        
         | sigstoat wrote:
         | maybe foreign data wrappers would be relevant to your
         | interests? i believe there are already a number of them which
         | expose non-databasey things.
        
       | gregwebs wrote:
       | These projects look great for reading data (although there are
       | times where I would prefer to transform the data server side,
       | that's not a deal breaker). However, they always seem lacking to
       | me for writing data if I need to add business logic (I don't want
       | to do this with triggers).
       | 
       | Then if I am going to write an API for writing data, just adding
       | some for reading data doesn't seem like much effort, although I
       | see the value proposition as frontend development getting a very
       | consistent API without having to ask the backend to develop APIs.
        
         | Twisell wrote:
         | You should be able to implement business logic sever side with
         | stored procedures in plain PL/pgSQL OR with various supported
         | procedural languages depending on your need (included with base
         | distribution or through extensions).
         | 
         | Same for transformation server side, unless I'm wrong, you are
         | not limited to ORM like construct. You can call a stored
         | procedures and only the result of server side computation is
         | sent back.
        
         | agentultra wrote:
         | You can use a library like
         | https://github.com/agentultra/postgresql-replicant or similar
         | to hook in a control plane and use PostgREST as a data plane.
         | 
         | Your business logic works on the event stream that comes from
         | the WAL.
        
           | gregwebs wrote:
           | I want synchronous validation with business logic. After the
           | synchronous validation event streaming could be useful.
        
         | dventimihasura wrote:
         | Why don't you want to write triggers?
        
           | majkinetor wrote:
           | They are considered GOTO of db. Good luck debuging complex
           | trigger hierarchy.
        
             | dventimihasura wrote:
             | They are considered that by whom? Not by me, they're not.
             | Personally, I've never encountered a complex trigger
             | hierarchy and I see no good reason why I ever would, and I
             | write lots of triggers. But, that's just me. Your results
             | may vary.
        
               | majkinetor wrote:
               | Experts: https://www.red-gate.com/simple-
               | talk/databases/sql-server/t-...
        
               | dventimihasura wrote:
               | "When I work with TRIGGERs, which is rare"
               | 
               | Evidently, even some experts do use triggers.
               | 
               | "I normally limit them to at most one per operation per
               | TRIGGER"
               | 
               | Great! So do I! So far so good. I guess I'm still in the
               | good graces of some experts.
               | 
               | "in full ANSI/ISO SQL, we do have schema level
               | constraints, the CREATE ASSERTION statement, but that is
               | another topic"
               | 
               | Not in PostgreSQL, we don't. Evidently some experts may
               | not be perfect experts.
        
       | kiwicopple wrote:
       | PostgREST 11 is in pre-release too - Steve (the maintainer) wrote
       | about some of the upcoming features here:
       | 
       | https://supabase.com/blog/postgrest-11-prerelease
       | 
       | (Disclosure: this points to the supabase blog and I work at
       | supabase (as does Steve))
       | 
       | Some of the features include
       | 
       | - Spreading related tables - similar to a JS "..." spread
       | operator to flatten a response
       | 
       | - Order by on related tables
       | 
       | - "Anti-Joins" - e.g. filter the rows where the related table is
       | null.
        
         | MuffinFlavored wrote:
         | I'm kind of confused why GROUP BY and "DISTINCT" aren't
         | prioritized as features. I know the workaround (create a view)
         | but I'm a little curious why it isn't seen as a "I expected
         | this to already be there" shortcoming for these rather "basic"
         | features.
         | 
         | I'm well aware the open source attitude means "go and fork it +
         | PR it yourself if you want it so bad". Easier said than done as
         | an outsider into a massive Haskell codebase.
         | 
         | Transactions (2015):
         | https://github.com/PostgREST/postgrest/issues/286
         | 
         | GROUP BY/DISTINCT (2017):
         | https://github.com/PostgREST/postgrest/issues/915
        
       | MuffinFlavored wrote:
       | For how often Nix is mentioned here on HackerNews, has anybody
       | looked at the Nix config files for this repo to build it locally?
       | 
       | https://github.com/PostgREST/postgrest/blob/main/cabal.proje...
       | 
       | https://github.com/PostgREST/postgrest/blob/main/default.nix
       | 
       | https://github.com/PostgREST/postgrest/blob/main/shell.nix
       | 
       | https://github.com/PostgREST/postgrest/tree/main/nix
       | 
       | I couldn't for the life of me figure out how to play with this. I
       | kind of don't believe "docker build ." is worse but I might be
       | missing something.
       | 
       | After I ejected out of playing with it on Mac OS, I found:
       | https://github.com/NixOS/nix/issues/458#issuecomment-1019743...
       | 
       | Over 13 parts to remove NixOS from Mac OS, involving reboots,
       | /etc/fstab, OS level users, daemons, etc.
        
       | majkinetor wrote:
       | I highly recommend this. Its so fast that it is crazy. I got 2k
       | req/s on basic tests.
       | 
       | Its filtering DSL is awesome, and should probably get supported
       | by commune: https://postgrest.org/en/stable/api.html#operators
       | 
       | Note that I didn't use it yet in production settings, but intent
       | to. Auth do seem a bit complex.
       | 
       | For anybody wanting a quick test on Windows:
       | https://github.com/majkinetor/postgrest-test
        
       | valstu wrote:
       | Are there any "api from postgres db" projects that are written in
       | Node.js?
        
         | fulafel wrote:
         | Out of curiosity why would you prefer a DB foundation
         | implemented in Node over a mature project in Haskell?
        
         | adamnemecek wrote:
         | Are you aware of supabase? It's rather nice.
        
         | smt88 wrote:
         | Yes, but like most large FOSS Node projects, they're dead or
         | under-maintained (huge number of GitHub issues). There are none
         | I'd use today.
        
         | AprilArcus wrote:
         | Graphile (https://www.graphile.org/) and Prisma
         | (https://www.prisma.io/)
        
           | Sujan wrote:
           | Prisma has pivoted to be "just" a Node.JS ORM a few years ago
           | (I work there). You can still use it to build an API of
           | course, but you will need some additional tool or libraries.
        
         | redmacaron wrote:
         | Directus is actually one. You get the front end which is
         | basically an admin UI, but you also get a full blown fully
         | featured REST API
         | 
         | https://directus.io/
        
         | aobdev wrote:
         | I was about to say "but this one is!" and realized I had
         | confused PostgREST with PostGraphile. If you're interested in
         | GraphQL, you can check out PostGraphile here:
         | https://github.com/graphile/postgraphile
         | 
         | It's interesting to me that PostgREST and Hasura are written in
         | Haskell, but PostGraphile is not. Given the complexity in
         | parsing arbitrary GQL queries I think I assumed that Haskell
         | was a better fit for the job, hence the mixup!
        
       | defanor wrote:
       | At work, we've finally replaced a large part of a custom
       | (mostly-)web backend with PostgREST recently, and that's quite a
       | relief: considerably less code to maintain in that project now,
       | and that was a rather awkward code. Something akin to PostgREST's
       | "Embedding with Top-level Filtering" [1] had to be provided for
       | all the tables, with OpenAPI schema and a typed API (Haskell +
       | Servant); I avoided manually writing it all down, but at the cost
       | of poking framework internals, and maintainability suffered. It
       | was particularly annoying that the code doesn't really do
       | anything useful, except for standing between a database and an
       | HTTP client, and simply mimics the database anyway. Whenever a
       | change had to be introduced, it was introduced into the database,
       | the backend, and the frontend simultaneously, so it wasn't even
       | useful for some kind of compatibility.
       | 
       | Now PostgREST handles all that, and only a few less trivial
       | endpoints are handled by a custom backend (including streaming,
       | which I'm considering replacing with postgrest-websocket [2] at
       | some point).
       | 
       | During the switch to PostgREST, the encountered minor issues were
       | those with inherited tables (had to set a bunch of
       | computed/virtual columns [3] in order to "embed" those), and with
       | a bug on filtering using such relations (turned out it was an
       | already-fixed regression [4], so an update helped). Also a couple
       | of helper stored procedures (to use via /rpc/) for updates in
       | multiple tables at once (many-to-many relationships, to edit
       | entities along with their relationships, using fewer requests)
       | were added (though the old custom backend didn't have that), the
       | security policies were set from the beginning, the frontend was
       | rewritten (which allowed to finally switch without adding more
       | work), so it was only left to cleanup the backend.
       | 
       | Not using views, since as mentioned above, database changes
       | usually correspond to frontend changes, and the API doesn't have
       | to be that stable yet.
       | 
       | Happy with it so far.
       | 
       | [1] https://postgrest.org/en/stable/api.html#embedding-with-
       | top-...
       | 
       | [2] https://github.com/diogob/postgres-websockets
       | 
       | [3] https://postgrest.org/en/stable/api.html#computed-virtual-
       | co...
       | 
       | [4] https://github.com/PostgREST/postgrest/issues/2530
        
       | FlyingSnake wrote:
       | Shameless plug: I once went down the PostgREST rabbit hole and
       | loved it. I wrote a series of articles on how to use it to create
       | a full fledged mobile app. I hope this helps someone trying to
       | wet their feet in Postgrest.
       | 
       | https://samkhawase.com/blog/postgrest/
        
       | password4321 wrote:
       | Previous mentions of / requests for something similar for SQLite:
       | 
       | https://news.ycombinator.com/item?id=33894995#33897716
       | 
       | https://news.ycombinator.com/item?id=33484693#33485145
       | 
       | https://news.ycombinator.com/item?id=33078798#33119873
       | 
       | https://news.ycombinator.com/item?id=30636796#30637326
       | 
       | https://news.ycombinator.com/item?id=24442294#24442876
       | 
       | Any recommendations or anecdotes today?
        
       | AnEro wrote:
       | Big fan of Supabase and bigger fan of PostgRest, I have so many
       | weird side projects I wouldn't have done if it wasn't quick and
       | easy to set up this stuff.
        
         | turbobooster wrote:
         | I have an old Django web app that needs to go REST since it's
         | coupled withe the front end I now want to use Vue. The problem
         | is the dang views/controllers. I would have to rewrite those?
        
           | umangsh wrote:
           | DRF (https://www.django-rest-framework.org/) provides a lot
           | of functionality out of the box for REST views. In addition,
           | DRF braces (https://django-rest-framework-
           | braces.readthedocs.io/en/lates...) helps share form and
           | serializer objects reducing a lot of duplicate effort.
        
           | AnEro wrote:
           | I'd say you could either just use vue + django and have use
           | AJAX to fetch data from your Rest API of a database. Theres
           | ways to handle auth aswell but its annoying. Or just not use
           | vue with this project, personally I think we've overestimated
           | how much interactivity/real time updates are needed in an
           | MVP. I personally prefer to rewrite stuff entirely, cause
           | there is always newer shinier solutions, but I also try to
           | keep my projects small or scrappy because of this*
           | 
           | *when it comes to side projects and fun projects that I am
           | the primary user
        
           | melony wrote:
           | Have young'uns these days not heard of _ajax_?
        
           | clintonb wrote:
           | https://www.django-rest-framework.org/
        
           | sidmitra wrote:
           | Instead of Vue, have you considered htmx with django-rest-
           | framework? See https://htmx.org/essays/spa-alternative/
        
       | shinycode wrote:
       | The French government has a open data GitHub with open source
       | projects. One of the project which list all the data for
       | entreprise addresses uses Postgrest (open data SIRENE de
       | l'INSEE).
       | 
       | Full fledge project implemented, interesting use of PostgREST
       | 
       | https://github.com/etalab/annuaire-entreprises-sirene-api
        
       | jpdb wrote:
       | I don't really understand the value of a project like PostgREST.
       | 
       | It feels like you're coupling your application schema to your
       | database schema, which is something you generally want to avoid.
       | 
       | Is this only for niches where you are ok with the db schema being
       | tightly coupled? Do you use specific views to decouple the two
       | schemas? In that scenario it seems like you might eventually get
       | to a point where your view is more complicated than setting up a
       | more traditional application.
        
         | xemoka wrote:
         | In the past, I've used a specific 'api' schema that contains
         | the views and functions that modifies a 'data' schema. You can
         | then have multiple versions of the 'api' schema for versioning
         | (with a different postgrest instance pointing at each versioned
         | api schema). It's possible...
        
         | justsomehnguy wrote:
         | There are niches where db schema IS the app schema.
         | 
         | Some time ago I wrote a REST wrapper for the .NET SQL
         | connectors which allowed me to post and query data from the
         | database. It was more than enough for my usage and I could
         | interact with that 'service' from anywhere in the network
         | without bothering on installing and configuring the SQL
         | connector on the endpoints.
        
         | pyuser583 wrote:
         | Speed. There might be other advantages, but it will be much
         | faster than any non-DB framework.
         | 
         | I'd want to limit it to simple schemes.
         | 
         | But if you're only exposing one table- it would be pretty darn
         | fast.
        
         | jeff-davis wrote:
         | I'll answer in _theory_ , because I haven't used it. And I
         | assume there are lots of ways this theory breaks down in
         | practice.
         | 
         | The first (theoretical) benefit is that it removes a lot of
         | redundancy. Databases already offer a lot of things
         | applications do for themselves, and typically it's a best
         | practice to do those things in the database anyway to guard
         | against application bugs. For instance, defining CHECK
         | constraints is a best practice regardless of application
         | validation. (There's a lot of disagreement over where the
         | DB/app boundary is and how much overlap there should be.)
         | 
         | Second, databases can be declarative because they are managing
         | the data itself. The presence of a constraint makes a guarantee
         | about the data regardless of history (versions, changes, bugs,
         | etc.). Similarly for declarative authorization (GRANT, RLS,
         | etc.).
         | 
         | Third, these benefits compound when dealing with many smaller,
         | hastily-written applications.
        
         | taffer wrote:
         | The recommended way to use Postgrest is to put a layer of views
         | and optionally stored functions on top of your schema to
         | decouple it from your API. Take a look at this Postgrest
         | starter kit[1] which uses a separate API schema for this
         | purpose.
         | 
         | [1] https://github.com/subzerocloud/postgrest-starter-kit
        
           | [deleted]
        
         | ravenstine wrote:
         | I could see this or something similar to it being beneficial
         | for generating a REST API _initially_ when the schema just
         | happens to pretty closely fit what the REST API should be.
         | 
         | But after that initial step, I wouldn't want my API dependent
         | on the schema (directly), nor would I want my database schema
         | dependent on the API code. As a side note, that's one reason I
         | didn't take a liking to Django.
         | 
         | Honestly, I'd rather have an RPC based API in the year 2023
         | than a REST API. REST, I think, was a bit of a mistake in terms
         | of a source for data that would be sent to a stateful frontend
         | as JSON. REST makes sense for webpages, but nothing about data
         | is inherently page-like. I've run into enough quirks dealing
         | with RESTful APIs and the libraries that claim to handle them
         | that I think we should be looking for a better fit.
        
         | majkinetor wrote:
         | The value is that you can get ultra peformant CRUD app
         | supporint bunch of filtering operations OTB within an hour or
         | so. If you developed one youreself, it would probably be slower
         | TBH. Depending on what you do, this can be lifesaver or thing
         | to avoid.
        
         | mike_hearn wrote:
         | If you aren't writing a web app then you can potentially scrap
         | the web server tier entirely, which can yield security and
         | simplicity benefits in some cases. For example, any app where
         | the userbase size is well known and stable e.g. internal apps,
         | apps for medical, military, industrial use cases. In such a
         | two-tier architecture you implement your business logic using
         | either SQL or server extensions like PL/Java
         | (https://tada.github.io/pljava/) and then provide users with a
         | desktop or mobile app to access the database directly.
         | PostgREST is useful for languages without good DB drivers, or
         | where you need to traverse HTTP only firewalls/proxies.
         | 
         | Advantages:
         | 
         | * Get back all the time spent boilerplating and bikeshedding
         | ad-hoc app specific REST protocols.
         | 
         | * Eliminates the (near) superuser privileged web servers that
         | pose a security risk if compromised. Eliminate SQL injection,
         | XSS, XSRF as bug classes.
         | 
         | * Allows smart users like business analysts to bypass the UI
         | partially or completely and go straight to a SQL console,
         | because end users = db users 1:1 and ACLs are understood by the
         | RDBMS directly.
         | 
         | * Use UI frameworks and languages that aren't JavaScript. Use
         | context menus, menu bars, hotkeys OS services or whatever else
         | makes your users productive.
         | 
         | * Use multi-threading, files, special hardware as part of your
         | core app architecture if you need it.
         | 
         | * If you can afford the server side resources: align DB
         | transaction length with UI "transaction" length.
         | 
         | Obviously there are also downsides. I wouldn't write Instagram
         | this way. Postgres doesn't scale very well to lots of
         | connections. Oracle/MSSQL scale a lot better and have other
         | advantages like much better blob support, but you'd have to get
         | comfortable with the idea of building new apps on them.
         | 
         | You can mix and match, it doesn't have to be purist. Retain a
         | thin, simple and rarely updated web server that just handles
         | the requests you don't send directly to the DB e.g. for things
         | like ElasticSearch. Or if you can (i.e. not on Supabase) write
         | custom Postgres extensions that let you use SQL stored
         | procedures as your RPC protocol. It has some advantages over
         | HTTP.
         | 
         | Lately I've been experimenting with this design a bit. The
         | traditional hassle has been non-web distribution to desktops.
         | https://conveyor.hydraulic.dev/ fixes that. If you're using
         | something like Electron or the JVM you can do a build+release
         | cycle for Win/Mac/Linux in about 60 seconds all from your dev
         | laptop, and you can make installed clients do a fast update
         | check on each launch just like a web app would. There are some
         | open questions about the best way to handle user authentication
         | when connecting direct to a DB if you don't want passwords. The
         | nice thing is you can e.g. bind the results of SQL query or an
         | ORM directly into your UI toolkit. JSON, REST, custom paging
         | code and all the other goop CRUD apps end up with just boil
         | away.
        
         | marcosdumay wrote:
         | The database schema is much harder to change than anything on
         | the application layer. That's unarguable.
         | 
         | From there people mostly decide on two philosophies: "I'll
         | write an adapter layer so that it's easy to change my data" and
         | "I'll take those robust, fixed facts and write my application
         | around handling them".
         | 
         | Honestly, I have no idea if one of those is any better than the
         | other. I can't even say with confidence that one will lead to
         | problems that another won't; they look equivalent to me. The
         | choice seems to be always made based on worldview, and it's not
         | even one of those "fast and loose" vs. "methodical" choices.
         | All the differences I see people pointing are false ones.
        
           | giraffe_lady wrote:
           | I've actually worked on a large complex postgrest-based
           | backend and the cons are all based on practical
           | considerations imo:                 - the dev workflow on a
           | db-as-codebase system is less familiar, less well understood,
           | with tooling general several years behind "normal" code work.
           | - branching and deployments similarly are just different in
           | ways it's hard to prepare for, leading to low confidence in
           | the deployed system.       - testing and debugging: pgtap has
           | different constraints than normal unit testing, debugging sql
           | functions is tricky and awkward. again the tooling is missing
           | or far behind.       - in most profitable applications I've
           | seen, the DB is the single largest cost and the most likely
           | to become a bottleneck you can't loosen by throwing money at
           | servers. having all your logic in there won't *necessarily*
           | make this worse but it certainly won't make it better.
           | 
           | DBAs have dealt with all of these things for decades and they
           | have skills and tools and mental models for them. But devs
           | and DBAs practice different disciplines with different goals,
           | and not everything crosses over easily. Engineers working on
           | a system like this from either side will end up acquiring a
           | degree of competence even expertise in the other one. Making
           | them desirable for other employers and difficult to replace.
           | 
           | Overall I don't strictly prefer this approach, but it
           | definitely has under appreciated strengths and should
           | probably be used more. It's hard to say how it could end up
           | if more resources were put into actually developing the
           | tooling necessary to back it up.
        
             | taffer wrote:
             | > having all your logic in there won't _necessarily_ make
             | this worse but it certainly won 't make it better.
             | 
             | Logic is a _very_ broad term, and as long as you 're
             | talking about number crunching / machine learning, I'd
             | agree. But most web or LOB applications have pretty simple
             | logic. According to Michael Stonbraker[1], a typical OLTP
             | DBMS spends only 4% of its processing time doing useful
             | work, which includes any kind of business logic, among
             | other things. The rest is spent on housekeeping tasks such
             | as context switching and transaction management.
             | 
             | The more business logic you move out of the database, i.e.
             | to the middle tier, the more roundtrips you need per
             | transaction. During roundtrips, transactions can't do any
             | meaningful work, which means more idle transactions, larger
             | connection pool, more locking, and context switches.
             | 
             | In other words, for typical OLTP workloads, each
             | transaction should ideally occur in a single roundtrip,
             | which requires the logic to reside within the DBMS.
             | 
             | [1] https://blog.jooq.org/mit-prof-michael-stonebraker-the-
             | tradi...
        
         | KronisLV wrote:
         | > It feels like you're coupling your application schema to your
         | database schema, which is something you generally want to
         | avoid.
         | 
         | This is an interesting statement that probably should be
         | expanded more upon!
         | 
         | I agree with it, because it can be nice to be able to change
         | how certain data is returned to any consumers of your API, for
         | convenience or maybe some business rules. For example, you
         | might want to aggregate data from multiple tables into a single
         | list of JSON objects for filling out a table in some
         | application downstream. Furthermore, you might be interested in
         | being able to change the underlying DB schema without affecting
         | how your API returns data, since its consumers don't
         | necessarily care about how you name your tables or what
         | references what internally.
         | 
         | At the same time, I do disagree with my own point somewhat,
         | because you can just use a DB view for pretty much the same
         | outcome. There's no reason why MyAppUserListViewEntity couldn't
         | match my_app.user_list_view in your database 1:1, I'd actually
         | argue that such a mapping for reading data would be really easy
         | to reason about and the discoverability would be pretty good,
         | while at the same time still letting you introduce changes as
         | necessary.
         | 
         | Furthermore, there's something really nice about codegen: being
         | able to tell some generator where your local development
         | instance of your database is running and generating application
         | entities with all of the mappings (for example, JPA) with a
         | single command, or doing the opposite and creating the schema
         | from your entities. Sadly in most cases such technologies are
         | underutilized and for whatever reason many out there still
         | write their ORM mappings manually for something like Hibernate
         | (or write dynamic SQL manually, with something like myBatis).
         | 
         | In the end, I'm not sure. Coupling might mean issues down the
         | road, but decoupling _now_ might mean introducing a level of
         | abstraction /indirection that might just be needless cruft,
         | like the tendency that you sometimes see in Java projects,
         | along the lines of: MyBusinessObject/Dto <--> SomeMapper <-->
         | MyEntity <--> MyEntityDao <--> MyEntityMapper/Repository; Not
         | saying that that's necessary OR that it's a bad approach, Java
         | just has lots of codebases out there that end up with many
         | abstractions, hence the example.
        
         | dventimihasura wrote:
         | I don't want to avoid that.
        
           | vore wrote:
           | Then I think you are in for a world of pain when you need to
           | e.g. change how the underlying storage of your data looks but
           | don't want to change the end user API.
           | 
           | A lot of the time, the access patterns of an end user talking
           | to your backend really don't match up to the access patterns
           | of your backend talking to your database.
        
             | dventimihasura wrote:
             | I have a layer of indirection between my end user API and
             | my underlying storage, so that I can change the storage
             | without changing the API. There's no pain involved.
        
               | sokoloff wrote:
               | How does that square with:
               | 
               | > I don't want to avoid [coupling my application schema
               | to my database schema]
               | 
               | It seems like you built a layer of indirection to
               | specifically allow the thing you said you didn't want to
               | do a couple posts up. (I think your indirection layer is
               | a good idea; I'm curious what your previous post meant in
               | light of that.)
        
               | dventimihasura wrote:
               | It doesn't. I wasn't addressing "coupling your
               | application schema to your database schema." I was
               | addressing "change how the underlying storage of your
               | data looks but don't want to change the end user API" in
               | the parent comment.
               | 
               | > It seems like you built a layer of indirection to
               | specifically allow the thing you said you didn't want to
               | do a couple posts up
               | 
               | No, because my layer of indirection is in the database in
               | the form of views and procedures. I could be wrong, but I
               | took "coupling my application schema to my database
               | schema" to be something like "having your HTTP API depend
               | on objects in the database", which it does because of the
               | way that postgREST works. If that's the kind of coupling
               | we're talking about, then that's the kind of coupling I
               | would rather embrace than avoid.
        
               | vore wrote:
               | Then... why not just use Postgres directly from your end
               | user API's backend? You might as well use an ORM and cut
               | out a layer of overhead from having to marshal data in an
               | out of PostgREST and point of failure from having to run
               | it.
        
               | dventimihasura wrote:
               | PostgreSQL + PostgREST IS my "API backend." They're one
               | and the same. There are no other layers. Using an ORM
               | would ADD a layer, not subtract one.
               | 
               | Perhaps what you're asking is, "Why not just have your
               | user interface connect directly to PostgreSQL and issue
               | SQL statements?"
        
         | arnsholt wrote:
         | We're considering it for a use case at work. In our case, it's
         | to allow a team of analysts to be more or less self sufficient
         | in publishing some data for external consumption without
         | needing to deal with deployments and the like. This way,
         | changing requirements can be handled by the analysts themselves
         | by updating the tables or views published by PostgRest, without
         | needing to think about changing a REST service and such.
        
           | maerF0x0 wrote:
           | Sounds like a security nightmare, highly recommend pairing
           | them with a dedicated security minded person to ensure
           | correct configurations of access control (networklayer/hosts,
           | row level, resource denial of service etc)
           | 
           | at the very least have a read of
           | https://postgrest.org/en/stable/admin.html
        
             | arnsholt wrote:
             | The idea is to have the IT folks managing the configuration
             | of both Postgres and PostgRest, the analysis folks will
             | obviously be working in SQL only.
        
               | maerF0x0 wrote:
               | > SQL only.
               | 
               | I assume you mean readonly SQL then... (perhaps creating
               | views too)
        
         | dimmke wrote:
         | So, I'm in the middle of building a backend for the first time
         | and I was evaluating PostgREST just yesterday.
         | 
         | Here's the value prop: Your database is the "source of truth"
         | but can be accessed in many, MANY different ways. Usually via
         | some kind of ORM system.
         | 
         | This can give you a head start on building a more carefully
         | considered REST API - where it gives you the base CRUD routes
         | for every table in an acceptable format and you can build on
         | top of it. Or if you're accessing your DB through some other
         | interface for your web app but need something quick to build a
         | new face for the service like a mobile app.
         | 
         | I recently ditched building a traditional REST API in favor of
         | just using what my ORM provides to interact with my DB.
         | Something like this will come in handy if I ever need one.
        
       | PreInternet01 wrote:
       | Previously discussed: 7 years ago:
       | https://news.ycombinator.com/item?id=9927771 3 years ago:
       | https://news.ycombinator.com/item?id=21435195 2 years ago:
       | https://news.ycombinator.com/item?id=25159097 1 year ago:
       | https://news.ycombinator.com/item?id=29389576
       | 
       | It's an insanely cool project, but I've yet to find a truly
       | fitting use case for it. In theory, PostgREST combined with
       | something like https://marmelab.com/react-admin/ should give you
       | a free back-end and admin panel for most projects, but in
       | practice, I've always found that all kinds of 'small details'
       | won't be quite right out of the box, and that customization is
       | really hard...
        
         | tomberek wrote:
         | I've used Prest (the Go reimplementation of PostgREST) because
         | I could more easily customize or bring it in as a library in a
         | larger application.
        
           | gregwebs wrote:
           | how do you customize it and use it as a library? Using it as
           | a framework is deprecated now? I didn't see docs talking
           | about this.
        
             | tomberek wrote:
             | Pretty sure I started with this:
             | https://github.com/prest/prest/blob/main/cmd/root.go
             | 
             | And from there you can execute your own command and add
             | handlers or other things as you wish.
        
           | euroderf wrote:
           | I wonder if there's an SQLite version somewhere.
        
             | __oh_es wrote:
             | More feature rich but perhaps this? Been dying to toy with
             | this and fslite
             | 
             | https://github.com/pocketbase/pocketbase
        
               | xrd wrote:
               | Absolutely love pocketbase.
               | 
               | And, interesting to note that using stored procedures
               | within pocketbase isn't well supported because they do a
               | dry run insert to check against constraints and then
               | delete it if the constraint fails.
               | 
               | https://github.com/pocketbase/pocketbase/discussions/650#
               | dis...
               | 
               | I mention this because the OP inquired about stored
               | procedures.
               | 
               | Still, pocketbase is so amazing.
        
             | jhd3 wrote:
             | https://datasette.io/?
        
         | IceWreck wrote:
         | Is supabase what you're describing?
         | 
         | I could be wrong but I think they use postgREST underneath.
        
           | the_duke wrote:
           | Yes, it definitely does.
        
         | esquire_900 wrote:
         | I've always wondered about this without trying it myself. Isn't
         | this be something that looks ideal to start with, but as the
         | project progresses and the edge cases keep stacking, you end up
         | writing a complete middle layer, which effectively turns out to
         | be your own framework?
        
           | CuriouslyC wrote:
           | Most of the edge cases can be handled using stored procedures
           | on the database, which can be called in PostgREST using a
           | generic '/rpc/<name>' endpoint. You can use foreign data
           | wrappers to handle almost all the remaining edge cases,
           | though that has diminishing returns in terms of time savings
           | vs having a separate service as cases increase in complexity.
        
             | pvillano wrote:
             | Complexity is often unavoidable. The question is where do
             | you put it?
        
             | lelanthran wrote:
             | > Most of the edge cases can be handled using stored
             | procedures on the database,
             | 
             | This is what actually turned my off about it when I used it
             | for a small hobby project: the tooling around programming
             | in SQL is absolute crap.
             | 
             | Expressing business logic in stored procedures is great in
             | theory, but in practice only the very simplest business
             | logic will be written as stored procedures, because
             | anything non-trivial is impossible to debug, impossible to
             | log properly and there is _never_ a call-stack available
             | when the inevitable runtime error /exception occurs.
             | 
             | If the tooling for writing, debugging, deploying and
             | testing stored procedures were up to the level of what
             | Turbo Pascal was in the 80s, I'd do it in a heartbeat.
             | 
             | As things stand, the only way to figure out bugs in the
             | system is to visually inspect the stored procedure source
             | code.
        
         | dang wrote:
         | Thanks! Macroexpanded:
         | 
         |  _Building single-page-apps with PostgREST_ -
         | https://news.ycombinator.com/item?id=30132947 - Jan 2022 (84
         | comments)
         | 
         |  _PostgREST 9.0_ -
         | https://news.ycombinator.com/item?id=29389576 - Nov 2021 (121
         | comments)
         | 
         |  _PostgREST: REST API for any Postgres database_ -
         | https://news.ycombinator.com/item?id=25159097 - Nov 2020 (205
         | comments)
         | 
         |  _PostgREST_ - https://news.ycombinator.com/item?id=21435195 -
         | Nov 2019 (237 comments)
         | 
         |  _PostgREST - A fully RESTful API from any existing PostgreSQL
         | database_ - https://news.ycombinator.com/item?id=13959156 -
         | March 2017 (87 comments)
         | 
         |  _PostgREST - REST API from any PostgreSQL database_ -
         | https://news.ycombinator.com/item?id=9927771 - July 2015 (204
         | comments)
         | 
         |  _Automatic REST API for Any Postgres Database_ -
         | https://news.ycombinator.com/item?id=8831960 - Jan 2015 (68
         | comments)
        
       | twistedcheeslet wrote:
       | Does anyone have experience integrating 3rd party auth systems
       | (ex Keycloak) with Postgrest? How did that experience go?
        
         | liamconnell wrote:
         | I think you can integrate it with nginx, which would work well
         | with postgrest.
        
         | fulafel wrote:
         | Not exactly the personal experience you asked for but
         | https://postgrest.org/en/stable/ecosystem.html has receipes for
         | oauth2 including Keycloak.
        
         | awalias wrote:
         | we integrated Gotrue with PostgREST at Supabase and it works
         | beautifully together https://github.com/supabase/gotrue (forked
         | from Netlify)
        
         | nick__m wrote:
         | I did it with Azure AD application roles in oauth tokens, it
         | was a non event.
        
       | anonu wrote:
       | This is getting close to a feature I've enjoyed in KDB for some
       | time. The open port in KDB is overloaded to handle different
       | protocols, like HTTP.
        
       | nesarkvechnep wrote:
       | Not RESTful at all. Not a mention of hypermedia.
        
       | college_physics wrote:
       | has any django fan used this project as an alternative to the
       | django rest framework? (using postgres as the backend to django
       | and serving the REST API directly). any thoughts about advantages
       | / disadvantages?
        
       | davidjfelix wrote:
       | I love PostgREST and have deployed it several times alongside
       | existing postgres databases to improve developers lives.
       | 
       | That being said, I think it's a little funny because it
       | epitomizes APIs that I see people build where ACID compliance is
       | a huge "must" for their database choice and then they expose
       | resources which can only be independently updated in a manner
       | that fails to expose ACID beyond the scope of individual
       | resources. I think this is funny because it really makes you
       | question if they ever actually needed full mutli-table
       | transactions at all or if they could have used a different
       | database all together.
       | 
       | Anyways, it's a really cool tool.
        
       | sigmonsays wrote:
       | When does this hurt your scaling ability?
       | 
       | From my experience, scaling a typical site has always been
       | bottlenecked in the database. http workers are generally
       | stateless and easily scalable. Where it gets tricky is optimizing
       | the database reads, caching, and invalidation.
       | 
       | Is the intended use case just simple CRUD of data that it not
       | under extreme read or write loads?
       | 
       | It seems like you could quickly build CRUD for tables in
       | _language of choice_ and still have the ability to optimize reads
       | with caching later..
        
         | cpursley wrote:
         | You can cache the API responses.
        
       ___________________________________________________________________
       (page generated 2022-12-29 23:00 UTC)