These days, I'm taking advantage of PostgreSQL's ability to handle logic, saving me all the work of an entire middleware layer. (Instead, using generalized middlewares like Graphile, Supabase, or Postgrest.)
A little gotcha in the Postgres learning curve has been working out the difference between stored procedures and functions, and realizing that the simpler table trigger
s and constraint
s (using with check
) actually does a lot of what I need.
One place I got stuck is sql transactions, or grouping several sql statements into a group so that if one fails, they all "roll back" as if they didn't happen. PostgreSQL has some specific rules about using transactions in or out of functions and stored procedures -- but I found a simple way out.
It turns out that PostgREST, the middleware Supabase is based on, surrounds rpc() calls in a transaction already. So I could just define a function in sql with:
CREATE OR REPLACE FUNCTION public.topup(user text, amount integer)
RETURNS integer
LANGUAGE 'plpgsql'
AS $$
begin
update users set balance = balance + amount;
insert into "transactions" (user, amount, note) values (user, amount, 'top up');
return 1;
end
$$;
In Supabase and PostgREST, this automatically exposes topup
in the API. When called over the API, it's automatically wrapped in a transaction. (I tested this by placing a contraint on user.balance to not let it go above 100, and when the user's balance was higher than the amount in the rpc call, neither user.balance was updated, nor was a new record added to transactions.)
Now, I can write a lot of logic into the PostgreSQL database itself. This simplifies my middleware a lot, and often enables me to make apps that call Supabase/PostgREST/Graphile calls directly from my front-end components. An entire layer of devops and code removed.
Top comments (1)
Hello, I am implementing Supabase with Angular and I use the Supabase API from Typescript, the problem that I am seeing is that when I want to use a Postgresql function that receives parameters, since the format of the parameters is a JSON, I observe that in the payload of the call to the API endpoint that data is totally visible, therefore totally insecure... do you know if there is something that can be done so that it travels encrypted or something similar. Thanks for your time