Readit News logoReadit News
kiwicopple · 2 years ago
hey hn, supabase ceo here

the Val Town team were kind enough to share this article with me before they released it. Perhaps you know from previous HN threads that we take customer feedback very seriously. Hearing feedback like this is hard. Clearly the team at Val Town wanted Supabase to be great and we didn’t meet their expectations. For me personally, that hurts. A few quick comments

1. Modifying the database in production: I’ve published a doc on Maturity Models[0]. Hopefully this makes it clear that developers should be using Migrations once their project is live (not using the Dashboard to modify their database live). It also highlights the options for managing dev/local environments. This is just a start. We’re building Preview Databases into the native workflow so that developers don’t need to think about this.

2. Designing for Supabase: Our goal is to make all of Postgres easy, not obligatory. I’ve added a paragraph[1] in the first page in our Docs highlighting that it’s not always a good idea to go all-in on Postgres. We’ll add examples to our docs with “traditional” approaches like Node + Supabase, Rails + Supabase, etc. There are a lot of companies using this approach already, but our docs are overly focused on “the Supabase way” of doing things. There shouldn’t be a reason to switch from Supabase to any other Postgres provider if you want “plain Postgres”.

3. That said, we also want to continue making “all of Postgres” easy to use. We’re committed to building an amazing CLI experience. Like any tech, we’re going to need a few iterations. W’re building tooling for debugging and observability. We have index advisors coming[2]. We recently added Open Telemetry to Logflare[3] and added logging for local development[4]. We’re making platform usage incredibly clear[5]. We aim to make your database indestructible - we care about resilience as much as experience and we’ll make sure we highlight that in future product announcements.

I’ll finish with something that I think we did well: migrating away from Supabase was easy for Val Town, because it’s just Postgres. This is one of our core principles, “everything is portable” (https://supabase.com/docs/guides/getting-started/architectur...). Portability forces us compete on experience. We aim to be the best Postgres hosting service in the world, and we’ll continue to focus on that goal even if we’re not there yet.

[0] Maturity models: https://supabase.com/docs/guides/platform/maturity-model

[1] Choose your comfort level: https://supabase.com/docs/guides/getting-started/architectur...

[2] Index advisor: https://database.dev/olirice/index_advisor

[3] Open Telemetry: https://github.com/Logflare/logflare/pull/1466

[4] Local logging: https://supabase.com/blog/supabase-logs-self-hosted

[5] Usage: https://twitter.com/kiwicopple/status/1658683758718124032?s=...

pcthrowaway · 2 years ago
> I’ll finish with something that I think we did well: migrating away from Supabase was easy for Val Town, because it’s just Postgres

Y'all are saints in this space. Every other managed db provider does everything possible to make leaving as difficult as possible. Definitely gives me a lot more confidence using Supabase in the future

tr3ntg · 2 years ago
Appreciate this well-thought out response. As someone who has built several proof-of-concepts on Supabase (but never going far enough to test its limits), articles by Val Town here and responses like yours all work towards my analysis of the platform for future projects.

It's funny that threads like these bring up comments like "Well I use XYZ and it solves all of my problems." As if a one-time mention of a new PaaS is enough to bank on it for future projects. Although I can't lie - I do bookmark every PaaS that I see mentioned on HN.

Regardless, I'd much rather put my faith in a platform like SB that has been battle-tested in public, even if it doesn't work out perfectly every time.

Always glad to see you and the team showing up for the discussions and improving SB.

refulgentis · 2 years ago
+1, paradoxically, I’m even more likely to use supabase after this. Really thoughtful
primitivesuave · 2 years ago
Let me just say that (for me) Supabase is one of the most exciting startups of the past couple years and I'm sure these issues will get ironed out eventually. I believe in your overall mission and am inspired by how much progress you all have made in just three years.
crooked-v · 2 years ago
I feel like the issue with the Supabase dashboard and database modification is more one of your general approach. You put editing stuff all right up front when at best it should just be an emergency hatch, and the only place to find info on migrations is by going and looking around in the docs.
kiwicopple · 2 years ago
yes, I agree. We're working on ways to make the Migration system more prominent in the Dashboard. Preview Databases will help with this too.

> just be an emergency hatch

I would go as far as saying that migrations should still be used beyond the initial development. The Maturity Models linked above include 4 stages: Prototyping, Collaborating, Production, Enterprise. After "Prototyping", everything should be Migrations.

The exception is that you can use the Dashboard for local development. When you run "supabase start", you can access the Dashboard to edit your local database. From there you can run "supabase db diff" to convert your changes into a migration.

replwoacause · 2 years ago
Love this response. The Val Town article was balanced, but your reply to it was too. Well done.
kebsup · 2 years ago
Hi, I've recently gave supabase a shot to as an alternative to firebase because I needed SQL. One thing that I've struggled with from the start is that supabase seems to ignore backends completely.

I don't want to use supabase edge functions, since I want to keep it simple with a single express backend and don't want to be vendor-locked.

In firebase, the Admin SDK https://firebase.google.com/docs/admin/setup solves this, but seems to be missing in supabase. For example, for a simple JWT verification, I had to go to old github issues, rather than finding the answer in the docs. https://github.com/supabase/supabase/issues/491#issuecomment...

hnrodey · 2 years ago
Currently only a hobbyist but so far I really enjoy using Supabase and have appreciated the generous free tier. Maybe some day, if I'm lucky, I'll prioritize my projects further and pursue monetization. It would be a great personal development if I needed to graduate to the paid tier.

Anyways, thank you. Supabase isn't perfect but it's pretty damn good.

yesimahuman · 2 years ago
Just wanted to add I’ve been using the local development and migrations workflow and it has been fantastic. Honestly the only issue I’ve really had is how frustratingly difficult it is to change an id field from int8 to uuid if I mistakenly don’t choose the right one at first and the migrations get stuck on that and I have to resort to manual hacking. Setting up local/staging/prod with this new system seems really easy. Nice work!
kiwicopple · 2 years ago
thanks Max, I'm also a fan of ionic. fwiw, I usually start with uuids now that they're natively supported: `id uuid primary key default gen_random_uuid()`. Changing a PK/FK type on a database definitely isn't trivial.
Munksgaard · 2 years ago
Really appreciate this response.

Looking at your first link, there's a link to this page which currently resolves to a 404: https://supabase.com/docs/guides/platform/docs/guides/platfo...

brylie · 2 years ago
Hey, I’d love to try out Supabase as a backend for Flutter apps. However, the docs and scaffold code, like authentication flows, are a bit lacking for Flutter. What are the plans for improving the Flutter-related documentation and packages? Are there any good first issues on GitHub related to Supabase + Flutter?
dshukertjr · 2 years ago
Hi there, Supabase Flutter SDK maintainer here. Appreciate the feedback here. Specifically what auth flow is under documented you think?
petrocrat · 2 years ago
Echoing most of the comments here: Love your product! This feedback in the article isn't even a setback, just a learning opportunity that Supabase users know will only make it better. You guys/gals at Supabase are crushing it!

Dead Comment

ilrwbwrkhv · 2 years ago
I also had the same experience with Supabase.

Even though it looks like a great product initially, it has a lot or errors and bugs when you are trying to actually build something more robust than a toy app.

Local development is a massive pain with random bugs.

The response time of the database also varies all over the place.

But the most important problem that we faced, was having so much of application logic in the database.

Row level security is their "foundational piece", but there is a reason why we moved away from database functions and application logic in database over a decade ago: that stuff in unmaintainable.

There is also really poor support and at the end of the day, the whole platform felt like a hack.

I think now, for most apps with up to 500_000 users (with 10_000 concurrent realtime connections) PocketBase is the best PaaS out there having tested a bunch of them.

A single deployable binary which PocketBase provides is a breath of fresh air.

Anything more than that, just directly being on top of bare metal or AWS / GCP is much better.

jgraettinger1 · 2 years ago
> Row level security is their "foundational piece", but there is a reason why we moved away from database functions and application logic in database over a decade ago: that stuff in unmaintainable.

Funny. In my experience, application-level authorization checks are very error-prone, easy to accidentally omit, and difficult to audit for correctness."Unmaintainable", I suppose.

Whereas RLS gives you an understandable authorization policy with a baseline assurance that you're not accidentally leaking records you shouldn't be.

mfalcao · 2 years ago
RLS is great, but it's not that hard to shoot yourself in the foot or miss stuff. E.g.:

  ALTER TABLE bookmarks ENABLE ROW LEVEL SECURITY;
  CREATE POLICY bookmarks_owner ON bookmarks USING (owner_id = auth.uid());
  CREATE VIEW recent_bookmarks AS SELECT * FROM bookmarks ORDER BY created_at DESC LIMIT 5;
The above may look fine at first glance, but recent_bookmarks actually bypasses RLS.

xrd · 2 years ago
I agree. I would love to see more articles on pocketbase. It's phenomenal and ganigeorgiev is an animal about responding to bugs and discussions. He's got to be a hybrid human and ChatGPT robot.
ilrwbwrkhv · 2 years ago
What's also really cool is that you can also just use PocketBase as a Go library and just build your app around it like any normal web framework, while still having a great UI for quick prototyping. And when you need more custom behaviour instead of database functions, you just write some Go code while still compiling everything down to a single binary that you can copy over.
datavirtue · 2 years ago
"Local development is a massive pain"...that's enough to kill it for me. No need to point out anything else.
dingledork69 · 2 years ago
I don't use supabase, but am a big postgres fan:

> that stuff in unmaintainable

Wrong. Version your functions and use something like liquibase to apply migrations.

koromak · 2 years ago
Way less friendly than writing code IMO
ilrwbwrkhv · 2 years ago
And handwrite xml? No thanks. Again, if I wanted to do any of this management myself, I wouldn't be using a PaaS.
another_story · 2 years ago
Could you be more specific what is difficult about local development? I've used it locally and had little difficulty.
dbmikus · 2 years ago
Personally, I had a really easy time getting Supabase to work locally. However, we use `dbmate` to manage our migrations instead of built-in Supabase migrations.

Also curious to hear from others on this:

> After a bit of sleuthing, it ended up that Supabase was taking a database backup that took the database fully offline every night, at midnight.

This seems like a terrible design decision if true. Why not just backup via physical or logical replication?

And totally hear the issues here with database resizing and vacuuming and other operations. That stuff is a big pain when it breaks.

crooked-v · 2 years ago
Supabase daily backups just use pg_dump. If their database was going offline, then something else was broken.
kiwicopple · 2 years ago
(supabase ceo)

To give context, Val Town have a particularly write-heavy setup, storing a lot of json strings. The nightly backups were causing write-contention, even at their relatively small size. We didn’t detect errors because they were application-level. We should have moved them to PITR as soon as they mentioned it since the timing was so obviously coinciding with backups. We’re investigating moving everyone to PITR (including the free tier). At the very least, we’ll add more control for backups - allowing users to change the maintenance window, or possibly disabling backups completely if they are managing it themselves.

Ethan_Mick · 2 years ago
How do people on HN like Row Level Security? Is it a better way to handle multi-tenant in a cloud SaaS app vs `WHERE` clauses in SQL? Worse? Nicer in theory but less maintainable in practice?

fwiw, Prisma has a guide on how to do RLS with it's client. While the original issue[0] remains open they have example code[1] with the client using client extensions[2]. I was going to try it out and see how it felt.

[0]: https://github.com/prisma/prisma/issues/12735

[1]: https://github.com/prisma/prisma-client-extensions/blob/main...

[2]: https://www.prisma.io/docs/concepts/components/prisma-client...

doctor_eval · 2 years ago
I use both for defence in depth. The SQL always includes the tenant ID, but I add RLS to ensure mistakes are not made. It can happen both ways: forget to include the tenant in the SQL, or disable RLS for the role used in some edge case. For multitenancy, I think it’s absolutely critical to have cross-tenancy tests with RLS disabled.

One of the things I think is important is to make the RLS query is super efficient - make the policy function STABLE and avoid database lookups, get the context from settings, etc.

RLS is pretty great as a backstop, but I found Supabase over-reliant on RLS for security, when other RBACs are available in regular PG. I can’t remember the details now.

I’ve found RLS is great with Postgraphile which uses a similar system to Supabase but is a bit more flexible.

spiffytech · 2 years ago
I found RLS challenging to work with when I prototyped an app with it and postgraphile.

I had seemingly-simple authz rules that RLS made challenging to express. I needed some operations honor the user's row access privileges, but with different column SELECT/UPDATE privileges. E.g., a user can only change a value after the backend validates and processes the input, or they shouldn't be allowed to retrieve their password hash.

Expressivity was challenging, but was compounded by security being implicit. I couldn't look at any given spot in my code and confirm what data it's allowed to access - that depends on the privileges of the current DB connection. Once you mix in connections with cross-user privileges, that's a risky situation to try to secure.

crooked-v · 2 years ago
The main issue we've had with it is that it's just plain slow for a lot of use cases, because Postgres will check the security for all rows before filtering on the joins, doing anything with WHERE clauses, doing anything to even tentatively take LIMIT into account, etc.

Imagine a 1-million-row table and a query with `WHERE x=y` that should result in about 100 rows. Postres will do RLS checks on the full 1 million rows before the WHERE clause is involved at all.

jgraettinger1 · 2 years ago
I'm having a hard time relating to this comment given our own experience.

We use RLS extensively with PostgREST implementing much of our API. It _absolutely_ uses WHERE clauses and those are evaluated / indexes consulted before RLS is applied. Anything else would be madness.

steve-chavez · 2 years ago
> because Postgres will check the security for all rows before filtering on the joins, doing anything with WHERE clauses, doing anything to even tentatively take LIMIT into account, etc.

Note that the above only happens for non-inlinable[1] functions used inside RLS policies.

Going from what you mentioned below, it seems your main problem are SECURITY DEFINER functions, which aren't inlinable.

It's possible to avoid using SECURITY DEFINER, but that's highly application-specific.

[1]:https://wiki.postgresql.org/wiki/Inlining_of_SQL_functions#I...

kiwicopple · 2 years ago
With PostgREST you can use the pre-fetch method to solve this: https://postgrest.org/en/stable/references/transactions.html...

You can use that to inject your ACL/permissions into a setting - set_config('permissions', '{"allowed":true}'). Then in your RLS rules you can pluck them out - current_setting('permissions'::jsonb).

This should make your RLS faster than most other options, in theory, because of data co-location

notyograndma · 2 years ago
Hi - We're an analytics solution for a specific vertical, so this is probably not appropriate for everyone but - what we did was create partitioned data tables that are named using a hash of the user UUID and other context to create the partition table name upon provisioning data tables for the user. The parent table is never accessed directly. We're using Supabase, but we don't use Supabase's libraries to operate this.
atonse · 2 years ago
It is highly appealing to have that defense in depth. However, when building a prototype or a product, not having experience in it causes me to worry that we will end up being stuck with a choice where it's very hard to pull ourselves out of.

So instead we've stuck to having that filtering logic in the application side. The main concern is how user auth/etc works in Postgres. (lack of knowledge, not lack of trust).

Because we also have complex filtering like, "let me see all the people in my team if I have this role, but if i'm a public user, only show this person" etc

esafak · 2 years ago
I use a database that supports unlimited databases, tables, and views. Makes it easy to separate tenants.
plugin-baby · 2 years ago
Is it Postgres? Schema-per-tenant + table inheritance?
simonw · 2 years ago
The documentation section here applies to so many products I've battled in the past.

> The command supabase db remote commit is documented as "Commit Remote Changes As A New Migration". The command supabase functions new is documented as "Create A New Function Locally." The documentation page is beautiful, but the words in it just aren't finished.

Great documentation is such a force multiplier for a product. It's so worthwhile investing in this.

Don't make your most dedicated users (the ones who get as far as consulting your documentation) guess how to use your thing!

kiwicopple · 2 years ago
this is very fair criticism. We hired a Head of Docs in March. I hope the improvements are evident since he joined, both in content and in usability.

We have a long way to go, but we're working on it.

pluto_modadic · 2 years ago
yeah, most golang/rust/API documentation in products seems to think that "the function name is documentation", which.... no it's not. that's a tooltip in an IDE, not a docs website.
t1mmen · 2 years ago
I hadn’t touched SQL for almost 7 years, but dipped my toes back in to build a PoC using Supabase. Despite some initial pains around RLS, I’ve grown to love it.

Sure, Supabase has some awkward quirks and issue, and author has some good points. But when it works like it should, it’s pretty awesome. I think of it as a powerful wrapper around solid services that make for great DX, in _most_ cases.

If Supabase could provide a great way to handle migrations and RLS, that’d be the biggest improvement to most people’s workflows, I’d bet.

I really wish I could just define my scheme, tables, functions, triggers, policies etc as typescript, then have migrations generated from that.

jononomo · 2 years ago
> I really wish I could just define my scheme, tables, functions, triggers, policies etc as typescript, then have migrations generated from that.

I've recently been using the Django ORM, which automatically generates migrations, and it is absolutely awesome.

t1mmen · 2 years ago
Thanks for the tip, that sounds exactly what I’m looking for (outside of node ecosystem, but I’ll take what I can get)
joshghent · 2 years ago
Echo all the words from the author here, and kudos for being transparent.

I’ve faced exactly the same problems building my new product. But, on the other hand, Supabase was incredibly easy to setup, and meant I could worry about infrastructure later.

Pros and cons like with everything, and always wise to understand the flaws of the tech you’re using.

omeze · 2 years ago
The local development & database migration story is Supabase's biggest weakness. I hate having to do migrations live in prod. The admin dashboard is just so much better than any alternative Postgres tooling that it's been worth using despite that. Takes care of the stuff I'd normally be sweating over when writing migrations like nullable fields / FK constraints / JSON formatting for default fields. Would be great if Supabase allowed for a "speculative migration" in its UX where it spit out a file you could use locally to test beforehand.
kiwicopple · 2 years ago
Please don't use the Dashboard to edit your database in production. We're working on Preview Databases which will help enforce this. For now this fits into our Shared Responsibility Model:

https://supabase.com/docs/guides/platform/shared-responsibil...

You are responsible for a workflow that's suitable for your application. Once you get into production, you should be using Migrations for every database change. I have a more thorough response here: https://news.ycombinator.com/item?id=36006018

searchableguy · 2 years ago
> Please don't use the Dashboard to edit your database in production.

You should make the default editor read only and allow switching to write mode with a big warning. This would discourage people from writing SQL or using UI to modify in production.

The dashboard has always screamed "use me to edit" and I have used supabase in the beginning and very recently too. Nothing has changed to discourage it so far.

Maybe something like mode button which is present at top and you can click to switch between development and production mode?

This would also change a couple more things which you do not want to touch in production by accident.

crooked-v · 2 years ago
If you use the CLI, `supabase start` spins up a Docker instance built from all your migration .sql files [1].

If anything, I think the admin dashboard encouraging directly doing operations on the database is the biggest weakness of Supabase. I would much prefer being able to lock it down to purely CI-driven migrations.

[1]: https://supabase.com/docs/guides/getting-started/local-devel...