-
-
Notifications
You must be signed in to change notification settings - Fork 143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow long-running transactions at the client side or do relational inserts #219
Comments
Another alternative might be doing PostgREST/postgrest#818 (comment). I've been noticing that most of the transaction needs are because of inserts on tables that are related through foreign keys. Doing it this way would save the need for exposing a generic transaction interface and avoid any potential issues with clients leaving transactions open for too long. An insert + update + update(use case from supabase/supabase-dart#60) could also be solved with a "relational upsert" interface. Related: |
I totally agree with the viewpoint. So db.runTransaction(() { the above transaction functionality is urgent needed as the standard equipment for supabase.dart. I appreciated!! |
Hi! What's the status of this issue? |
Also interested in if there has been any progress made on this? We are deciding on the backend for our stack and the lack of transactions will likely rule out supabase unless it is on the roadmap for this year. |
@dreinon @cory-weiner I'll revisit this one after launch week(August). |
@steve-chavez imho this feature is very important. I can't think of any non-trivial RDBMS use-case that can work without transactions - except simple apps without many relationships. |
Also wanted to agree with the previous comment that supabase without transactions is borderline unusable. |
Do you have an update on this? really curious! |
Yeah, I made a proposal here for the API side. As a first step it will only allow doing multiple mutations(update, insert, delete) on a transaction. |
dear, one month has passed now, do you have any idea if this great feature is being picked up? :) |
friendly reminder, really curious! :) |
It's been quite a while since any update, any headway on development and/or direction on this? Been keeping an eye on this as well as PostgREST/postgrest#286 and PostgREST/postgrest#818 (which I believe are all trying to solve the same/similar issue) and haven't seen anything yet. Handling relationships in supabase is pretty awful (imo) without this, would love to see this come to being. |
This is a deal breaker for my project. Everything I have to do, has some sort of transaction use cases. Writing complex bits of logic inside the database is scary and awful. Simple updates as triggers and all are fine, but anything beyond this is just very difficult. |
This is really important for the backend development experience, we eagerly await this! 😄 |
Also throwing my vote in. This might end up being a dealbreaker on a significant project I'm about to embark on, sadly 😢 It's a shame; virtually everything else about supabase would make it a perfect fit |
Supabase Team, you must be out of your mind to not give this issue more attention. A feature that is so integral, so critical to an RDBMS is missing from your stack. And the lack of requisite attention is astonishing. For us, this is a deal breaker. We will be steering clear of Supabase for the foreseeable future when picking a BaaS for any of our projects, until we find that transactions have been added to the client SDKs - especially Javascript. |
To be fair, you could always use a database function for that and trigger it via client SDK. This is how we did it. So its technically possible, just a bit inconvenient. |
In our particular case, "bit inconvenient" is an understatement. For the complex business logic we're currently employing, using database functions is borderline infeasible. |
I wanted to be polite. Yes, using transactions from the client SDK would be huge. |
@adifyr Another alternative would be to use a supabase edge function with a different client library such as https://github.com/porsager/postgres which supports transactions. You can keep your complex business logic in JS and use it there. Might be easier than trying to translate to plpgsql. |
@evelant We recently tried incorporating a third-party library (not the one you linked to), and had a less than ideal experience. Nevertheless, thanks for the link. Will try out your library as well. |
The Supabase client seems more geared toward exposing the base of Postgres's features (via PostgREST). Hence, requesting client-side transactions is more of a DX issue since one can get For some context, database transaction handling is not a trivial feature. Even some full-fledge dedicated ORMs and query builders struggle with this feature and often even define their APIs around the limitations and requirements of transactions. I've used JS/TS ORMs like Prisma, TypeORM, Sequelize, Knex, and believe me; transactions are not easy. Implementation and maintenance of this feature are critical since faulty logic can have very detrimental and even catastrophic consequences to data performance and integrity (DB deadlocks, loss of data, connection pooling issues, etc). I am sure the Supabase team knows this well, and they probably would rather leverage PostgREST if it solves this problem. So here are my suggestions, given the complexity of the feature and unknown timeframe:
To the Supabase team, if DX is the issue, perhaps dedicating time to ease the pain of developers wanting to leverage PostgreSQL fully can help a lot. 😃 Some ideas that come to mind are:
|
I would argue that as transactions are a Postgres feature, it's within the scope of Postgrest/Supabase. It's for sure a more complicated feature to implement safely, which has been discussed, but I'd argue the fundamental idea of exposing Postgres features to the client side doesn't exclude this. It's a choice to not support in favour of RPC. If RPC didn't exist, would you make the same arguement?
I'm sorry, but I disagree completely with this idea. The issue is not that it's scary to use SQL, it's about keeping a consistent workflow and allowing for abstraction. Neither are possible when you're storing queries on RPC. Context switching from JS/TS to SQL is a pain generally, but if you've gotten so far into writing a query, then realised you need to use a transaction, something which should be trivial from a user's perspective, is not a great time to then need to rewrite in SQL. - if that's how we're to do things, why not write everything as an RPC? I imagine you'd experience less pain. It's silly. RPC's are a workaround, not a solution. Additionally, Supabase's entire pitch is that it's an open source Firebase alternative, of which Transactions are available.
I think this would be very helpful in the mean time while waiting on transaction support. |
I agree it would be a great feature. Still, my point is that the client isn't built as a full-fledge ORM, but a set of abstractions using other open-source tools made for Supabase, particularly the DB interface uses
Again, it's important to clarify |
I don't think anybody is asking for the js library to be a full-fledged ORM, neither do I believe transaction support would make it so.
Steve (the owner/maintainer of postgrest) works at Supabase so it quite literally would. Though admittedly I don't know to what capacity their relationship exists or whether Supabase dictates priority of certain issues/features Steve picks up. Given the previous discussion in this issue and related, it sounds like it's on their todo list, I just don't think it's helpful to downplay the importance of such a feature. "use RPC" is not a solution, it's a bite-your-tongue-and-deal-with-it workaround. RPC should ideally be used for times where you need to circumvent row-level permissions, or execute SQL in a controlled way that you wouldn't want to just expose to the client-side... As an alternative to transactions? That makes real-world usage incredibly painful for even the most basic of relational data. Also just to make it clear, I'm incredibly grateful for the work Steve does, and the Supabase team with developing PostREST and Supabase. I'm very much eagerly waiting in excitement for when I can take advantage of these features which I think are essential to real-world usage, as I said, I just don't want to downplay how important I think they are. Edit: @bombillazo After re-reading, just want to apologise if I came across a little hostile, I don't mean to be. Just felt quite strongly. |
@evelant Postgres.js is working just fine for us in the mean time. Thanks for the link. Awaiting updates from the Supabase Team on the inclusion of transactions natively in PostgREST. |
No worries, no hard feelings 🙂 I don't take things personally. I understand the frustration from the lack of this super convenient feature and the desire to get help to move this forward. Hopefully, they can invest the time in a solution that makes the Supabase client stack up with Firebase and other ORMs alternatives. |
The more I use supabase the more I realize most database operations are better done on the server anyways, so good to know we can still just access the database directly and get transaction support with something like postgres.js. |
any updates on it ? |
This is very, very, very important to my project. Anyone here have time to prompt (ask) AI for a solution... |
would be a very nice feature, dropping a comment later i'll check |
+1 would like to see transactions for Supabase |
@bombillazo Here are my arguments to understand the breadth of this issue further and I do have an inclination towards one solution approach that I would like to suggest here. Reply to your suggestions
Sincere apologies if the above come of as rude / too strong. My Solution ProposalTLDR: Make two implementations of the same sdk interface, one for use in the edge functions and the other for use in the frontend apps.
What would this enable?This way we can write code that is in a consistent syntax. Potentially we can move code written in the frontend to the backend when we need to without making any change. Can use full DB power in application code by using Atomic Transactions when in the edge functions. For frontend you can still use the PostgREST endpoints. Potential pitfalls
|
Hey, first, I have no stake in Supabase as a company or technology; ultimately, I have no personal matter in any current position in this issue other than the desire as a developer to get this feature. I may come off as dismissive, but I am being pragmatic and non-optimistic. I fully support resolving this issue to ease the development of transactional logic in my backend. That said, I am not holding my breath that this will be available anytime soon, nor am I architecting my solutions with that expectation. My observation was a raw, objective assessment of the technology, how it stands, and how it's been managed since this issue was created. It's been four months since my original post, with the issue nearing two years, and I still see no signs of it being resolved anytime soon. My points are the practical alternatives ( given Supabase's approach to its client lib) while transactions are resolved. Your suggestions on point 4 sound idealistic; the Supabase client should become (or behave like) an ORM. However, that goes back to one of my initial points: I don't think Supabase ever set out to build a custom ORM that incorporates all the advanced features. The Supabase team consciously decided to leverage PostgREST with its virtues and flaws to provide a solution. As I mentioned before, changing or adding the ORM paradigm in parallel is a lot of work. It's the ideal solution, but it's probably years off. As soon as I see any signs from Supabase that they are working on an ORM-like solution or PostgREST somehow resolves the transactional limitations, my sentiment about the delivery of this feature will change (hopefully, the Supabase team is secretly refactoring the whole client/approach and introducing another architecture apart from PostgREST). So, after using Supabase for months now, I've come to the following conclusions:
If these are deal breakers, then yeah, Supabase made technological choices that do not provide the features you require to have the DX/programming experience you desire, and adding those features could be years away. While we wait for this feature, you can program around it with the alternatives I've shared or not use Supabase. Not the ideal state we want, but it's where we are now. |
This comment was marked as outdated.
This comment was marked as outdated.
On the ORM/db library point, I chose to use Kysely for all our Deno backend logic, and it's been a great experience, what I initially expected from the Supabase client. Is it "clean" to have to manage two clients in tandem? No, but hey, it works and is a practical alternative given the options and "solves" this while we get native support from a Supabase client. |
I would love to pay if the feature is on. |
Hey there! It's been 2 years since this current thread, and longer since this solution was initially requested. |
any updates? |
I WILL become a carpenter if this doesn't get solved. You've been warned. |
Would also appreciate if this gets built. Has anyone figured out a workaround for this? Is there a way to "finish" an insert, then pass off execution to update a foreign key in a different table using another supabase execution thread? (after initial insert has "completed") |
maybe this is enough for you https://supabase.com/docs/reference/javascript/rpc |
The canonical Supabase way of doing that in a transaction is using RPCs; there is no way to use the JS client transactionally. You can still mount that workflow logic with multiple JS client statements, but there will be no rollback/atomicity, and you will need to handle any intermediate states. |
but then how do you deal with authorization? @bombillazo |
According to the Supabase docs, using RLS and the |
transactions please |
Really need transaction |
Most of the discussion so far has been about implementing multi-table data insertion or updating operations. I do agree that transactions are necessary in those cases, and I do agree that stored procedures, while helpful, can be annoying. But that's not what I want to talk about. Not having transaction support in the client causes another nuisance: Supabase apps cannot use locks. In many apps that have a central data repository (you know, a database), it is desirable to prevent concurrent editing of the same data. If you don't do this, you may end up with situations where two users open the same row for editing at the same time, and then user A saves, and then user B saves, overwriting A's changes. So how do you prevent this? There's really two ways: pessimistic or optimistic. In the pessimistic approach, you would lock the row when you start editing:
Then, when the user is done editing, you just do
This doesn't work in Supabase because you can't hold the transaction open. Running There is a possible workaround. What does work is having a separate table In the optimistic approach, you assume that conflicts usually don't happen, and just fail if the data has been edited from under you. When the user opens the row for editing, remember the current version.
Then, when the user submits, download the current version again, check if it's equal to the version you previously saw, and only if it is, then you perform the update.
This doesn't work in Supabase either because without transactions, there is a race condition between the version check and the update: if another user submits after we downloaded Again, a workaround is available: don't ever call Obviously, the pessimistic approach as outlined above has severe scaling problems, and I would understand if that was the reason that the team is hesitant to implement this. However, I'm not certain if maximum "web-scaleness" is what most of Supabase's customers want anyway? Although I suppose it's a pointless discussion, because that's not even a client-side issue: even Supabase's backend doesn't support this, because the load balancer just can't do this. |
@colinemondswieprecht I've opened #581 for the subject you've mentioned, let's continue there. |
Feature request
Is your feature request related to a problem? Please describe.
Transactions are a fundamental concept of all database systems. The essential point of a transaction is that it bundles multiple steps into a single, all-or-nothing operation. The intermediate states between the steps are not visible to other concurrent transactions, and if some failure occurs that prevents the transaction from completing, then none of the steps affect the database at all.
Describe the solution you'd like
Implement an easy way to create transactions. Something like:
Describe alternatives you've considered
Create a rpc function that runs the commands. This is suitable for small apps, but wouldn't work for large apps, since multiple functions would be created.
Additional context
supabase/supabase-dart#60
https://www.postgresql.org/docs/8.3/tutorial-transactions.html
supabase/supabase#526
The text was updated successfully, but these errors were encountered: