In this blog I will discuss my views on BaaS. Firebase is very popular, but I will focus mainly on open source BaaS, I will mention it as reference when comparing with others, but not going into much details.
Services
TL;DR
My Choices
Here I only list bullet points. More details (reasons) will be discussed in other sections.
- Convex
- For most use cases
- Need reactive/live queries
- Backend in TypeScript
- PocketBase
- Relatively simple project
- Lightweight “Embedded BaaS”
- Example: wol-web (docker image 17.6MB in total)
- Host backend and frontend (SSG/CSR web app) in a single container
- Example: wol-web (docker image 17.6MB in total)
- Supabase
- Wants a mature database like Postgres
Features
For free tier, I only list the “The shortest plank in the barrel effect”. For full details, check their websites.
Service | Official Cloud Hosting | Free Tier | Self Host | Open Source | Type Safety |
---|---|---|---|---|---|
Supabase | ✅ | 2 free projects; 500MB; | ✅ | ✅ | Good |
Convex | ✅ | 1GB; 1M function calls; | ✅ | ✅ | Perfect |
Firebase | ✅ | 1GB | ❌ | ❌ | No (yes with community) |
PocketBase | ❌ | PocketHost has no Free tier | ✅ | ✅ | No (Community support for TypeScript) |
Hosting
- Pocketbase
- All services except Pocketbase provides official cloud service. You can use PocketHost or Fly.io or Railway, or just a VPS for hosting.
- PocketHost has no free tier now (used to have)
- Firebase
- No self hosting
- Not open sourced
- Supabase
- Only 2 free projects
- Extremely inconvenient for development/experimenting, when there is pretty much zero usage
- Most likely because hosting a single Supabase project requires 10+ containers, the cost of one project is too high
Services
- A Postgres DB
kong
for load balancingsupabase/studio
timberio/vector
: for logssupabase/supavisor
supabase/edge-runtime
for edge functionssupabase/logflare
: for analyticssupabase/postgres-meta
darthsim/imgproxy
: for resizing and converting imagessupabase/storage-api
: for storing filessupabase/realtime
postgrest/postgrest
: supabase-rest container for rest APIsupabase/gotrue
for supabase auth service
- Only 2 free projects
- Convex
- No project limit, only total usage limit
- I like this. It’s more reasonable, and very convenient when I am just experimenting, prototyping or developing
- No project limit, only total usage limit
Developer Experience
Type Safety
Type safety is very very important to me. By type safety I mean
- Auto complete (in TypeScript)
- For table name, query fields, response fields
- TypeScript errors in client when DB schema changed
- So we can always keep the client and DB schema in sync easily
- Pocketbase doesn’t provide types, but you can use open source project pocketbase-typegen to generate types for PocketBase client.
- Supabase provides almost-perfect type safety
- A
database.types.ts
can be generated based on database schema. - But when you call
supabase.select("field1, field2")
there is no auto complete to tell you what fields there are and whether you have typo or wrong field name. There is type for response though. So it’s almost perfect.
- A
- Convex has the best TypeScript support I’ve seen
- Also relies on TypeScript code generation. Will auto generate types files when schema changes. The DB schema is also defined in TypeScript with valibot types.
- But you cannot select a single field, the entire document is returned, you need to write code in backend to get the fields you need to return to frontend.
- This could be a performance problem when there is a field with a large amount of data, and you don’t need it in a queries that returns many rows. e.g. selecting all ids from a table, while the data field contains a large amount of data.
- Only ids will be returned from backend to frontend, but the backend will fetch all the database from DB first, extract ids and return (everything in JS). This could be slow. The backend code is hosted with DB so network delay can be negligible.
Authentication
Auth or OAuth is a very important reason I prefer BaaS over building everything from ground up. Auth generally takes a lot of time to implement, and it’s crucial for auth to be implemented right. All of these BaaS supports Auth. If you are Ok with using a third party service, you can also use Clerk, a more mature Auth SaaS with more features, such as MFA and enterprise SSO. For myself, OAuth with Google and GitHub is good enough, and all of them support it.
As of now, Convex Auth is in beta. Doesn’t seem to work with svelte, only Next.js.
- Convex Auth seems to be the only one that doesn’t have a dedicated management page in their dashboard
- Convex Auth is the only service that doesn’t work out of the box
- You have to read their docs, follow the instructions and write some code
- It’s not too hard, but not as convenient as other options
- Everything is stored as regular tables, including tables for accounts, sessions, rate limit, refresh tokens, verification codes
- These tables are auto created if you use Convex auth’s default setup
- A down side of Convex auth is that it doesn’t seem to support multiple redirect URL
- It relies on
SITE_URL
environment variable to redirect - Which means you can’t use the same convex project for both development and production
- If you force a redirect to
localhost
whenSITE_URL
is the production domain, you will receive an error - Supabase supports redirect to localhost and other domains in the same project
- It relies on
- Convex Auth is the only service that doesn’t work out of the box
- Supabase support multiple redirect URLs, even wildcards
- AppWrite auth seems to have more features
- Features
- labels
- such as
admin
,premium
,mvp
- could be useful for RBAC
- such as
- preferences
- Such as color theme and language preference
- Multi-factor authentication
- Membership
- Sessions
- There is a session tab in web UI. A session can be deleted.
- labels
- These features are nothing special and not too hard to implement, but will require adding an extra table in DB. In AppWrite these features are built-in and available on Web UI.
- Features
Cloud Functions
Here cloud functions mean functions hosted with the BaaS on cloud.
- AppWrite
- Best runtime support
- Node
- PHP
- Ruby
- Python
- Deno
- Dart
- Bun
- Go
- Best runtime support
- PocketBase
- Extend with JS and Go
- JS has much less features. A tiny JS runtime is included.
- APIs like window, fs, fetch, buffer or any other runtime specific API not part of the ES5 spec may not work!
- Most npm packages are either impossible or too hard to integrate with the JS hooks
- With Go you can do pretty much whatever you like. Any Golang library can be imported because you are essentially using PocketBase Golang package as a base web framework like express or spring boot.
- JS has much less features. A tiny JS runtime is included.
- Extend with JS and Go
- Supabase
- The only option is Deno. Write Deno functions locally and deploy to cloud
- Personally I am not a fan of this
- Deno is not as easy to use as node/bun in terms of compatibility
- There is a upload limit of ~10MB, the code is compiled to uploaded to Supabase
- I was coding in a TS monorepo, importing code from another workspace package, and somehow the total size of a function exceeds 10MB and didn’t allow me to upload
- Convex
- Convex uses queries and mutations for everything in backend
- It doesn’t provide a ORM-like sdk that can interact with the DB directly using HTTP. It essentially has a more traditional setup. Just instead of REST API, convex uses their RPC-like design to make type safety and DX better.
My Choices
Supabase
I would pick Supabase when I want
- A regular postgres DB
- A separate REST API with Hono
- Connect to Postgres DB with drizzle instead of using supabase SDK
- Basically using Supabase as a Auth service with a regular Postgres DB
- REST API is supported in every language, could be useful when client apps are in other languages like Rust, C#, etc
- Supabase cloud service seems to be very slow in China, hosting Hono on Cloudflare could speed up network connection everywhere in the world
Convex
Read more in ConvexWhen?
When would I pick this BaaS?
- Most of the time I think I would pick this
- Very convenient for small projects with mostly CRUD operations
- Need live queries
When would I not pick this BaaS?
Link to original
- The app could potentially get a huge amount of data, then this DB may not be as good as mature DB like Postgres
- Mature databases have known solutions for horizontal/vertically scaling through partitioning/sharding
- Need very complex queries
- I am not sure about the performance with this DB against complex queries
- Their filtering/joining/aggregation logic are written in JS/TS
- The queries code is executed within the DB environment though, so there is negligible network latency (which is the largest cost in most simple queries)
- In a traditional backend setup: Frontend → Backend → Database → Backend → Frontend
- If the backend and database are not placed in the same data center the network latency could be higher than actual computation time in DB
- But I doubt if it can be as performant as SQL queries as SQL has been optimized for years
- Convex’s backend is written in Rust BTW