Supabase: the missing backend for React
The problem Supabase solves
Frontend devs who need a backend have historically had three bad options for an MVP:
Build a server from scratch (Express/Fastify + PostgreSQL). It works, but takes weeks just on setup: configuring auth, modeling the database, creating migrations, storage setup, configuring WebSocket for realtime. Time that should go toward features goes toward infrastructure.
Use Firebase. Quick setup, but heavy vendor lock-in. The database is NoSQL (Firestore), which makes complex queries painful. Want to do a JOIN? Good luck. Want to migrate somewhere else later? Good luck with that too. And the pricing at scale can catch you off guard.
Hire a backend dev. Expensive, not always necessary for initial scale, and adds coordination overhead (frontend waiting on endpoints, backend waiting on screens).
Supabase is the fourth option: real PostgreSQL with auth, storage, realtime and edge functions in a single service. I tried Firebase and PlanetScale before. Supabase was the best fit between control and productivity.
The main difference: Supabase is PostgreSQL. Not an abstraction, not a proprietary database. If I ever need to migrate, I export the database and take it to any PostgreSQL instance in the world. No vendor lock-in.
In practice, this means any tool that works with PostgreSQL works with Supabase. I can connect pgAdmin, DBeaver, or any SQL client directly to the database. I can run pg_dump and have a local backup in minutes. I’m not stuck with a proprietary format or an API that can change without notice.
What comes in the box
Auth
Registration, email/password login, social login (Google, GitHub, Apple), magic link, and MFA. Works with just a few lines of code on the frontend.
On AutoPars, there are 3 profiles (buyer, seller, admin) all managed by Supabase Auth. Each profile has a custom role in the database that determines what they can see and do. Auth goes beyond “logged in or not”. It matters who logged in and what that person can access.
On FitPlan, there are 6 profiles (network owner, board, admin, personal trainer, nutritionist, student). Same auth system, same role structure. Scales without changing the architecture.
Database
Real PostgreSQL. Pure SQL, views, functions, triggers, indexes. If you know PostgreSQL, you know how to use the Supabase database. No proprietary language, no abstraction hiding what’s happening under the hood.
The Supabase dashboard has a built-in SQL editor, table viewer, and query explorer. If you like GUIs, it’s productive. If you prefer code, migrations work like any PostgreSQL setup.
I can create views that calculate AutoPars dashboard metrics (total GMV, platform revenue, active sellers) directly in the database. The query runs in PostgreSQL, not on the frontend. Better performance, less code in React.
Triggers and database functions also handle logic that would normally live in the backend. On AutoPars, when an order is created, a function automatically calculates the platform commission and writes the value to the transactions table. This runs directly in PostgreSQL — it doesn’t depend on an extra frontend call or an edge function.
Storage
File uploads with access control via policies. It’s like AWS S3, but integrated with auth and the database.
On AutoPars, sellers upload photos of auto parts. Each seller can only see and edit their own images. That rule isn’t in the React code — it’s in Supabase Storage via a policy. Even if there’s a bug in the frontend that tries to access another seller’s image, storage blocks it.
Realtime
Native WebSockets. When data changes in the database, the frontend gets notified automatically. No polling, no manual refresh, no configuring Socket.io.
On AutoPars, when an order changes status (confirmed, preparing, shipped), the admin dashboard updates on its own. The admin doesn’t need to hit F5. The seller gets notified in real time when they make a sale.
On FitPlan, when the trainer marks a workout as completed, the student’s dashboard updates instantly.
Edge Functions
Serverless functions in Deno for logic that can’t run on the frontend. Webhook validation (Asaas sends a POST and you need to process it server-side), external API calls with a secret token (can’t expose tokens in the browser), heavy processing that would freeze the client.
On AutoPars, the Asaas webhook hits an Edge Function that validates the signature, processes the event, and updates the database. All server-side, with no logic or tokens exposed on the frontend.
RLS: the part that really sold me
Row Level Security is what actually sets Supabase apart for me. Instead of validating permissions in frontend code or in an API middleware layer, I define policies directly in PostgreSQL.
How it works
Simplified example: a seller can only see their own products.
CREATE POLICY "seller_sees_own_products"
ON products FOR SELECT
USING (seller_id = auth.uid());
auth.uid() returns the logged-in user’s ID automatically. If seller A lists products, PostgreSQL filters and returns only products where seller_id matches their ID. Seller B gets only theirs. Admins have a separate policy that returns everything.
Why this is better than validating in code
Security sits at the lowest possible level. Even if there’s a frontend bug that tries SELECT * FROM products, the database filters it. Data doesn’t leave PostgreSQL without going through the policy. It doesn’t depend on React, doesn’t depend on middleware, doesn’t depend on anything running in the browser.
It’s declarative. The policy says “seller sees only their own”. I don’t need to write if (user.role === 'seller' && product.seller_id === user.id) in every query, every endpoint, every controller. One policy, applies everywhere.
And it’s hard to forget. If I forget to add WHERE seller_id = ? in a query, data leaks. With RLS, the policy applies automatically to every query on that table. You can’t forget — the database won’t let you.
On AutoPars, every table has policies for each profile. Buyer sees active products from all sellers. Seller sees and edits only their own. Admin sees everything. That’s about 20 policies total. Declarative in the database, zero permission logic scattered across the React code.
Another point: RLS works on every operation, not just SELECT. I can define policies for INSERT, UPDATE, and DELETE separately. A seller can insert a new product (INSERT), edit their own (UPDATE filtered by seller_id), but can’t delete a product that already has a sale (DELETE blocked by a policy that checks for linked orders). All of this without a single line of validation in React.
My stack with Supabase
Frontend: React + TypeScript + Tailwind
Backend: Supabase (Auth + PostgreSQL + Storage + Realtime)
Deploy: Vercel (frontend) + Supabase Cloud (backend)
This combo lets me deliver a full webapp working solo. Mariah shipped in 4 hours. AutoPars with 5 integrations in weeks, not months. Supabase removes the need to set up a server, configure auth, manage uploads, and implement WebSocket. It all comes ready and integrated.
The productivity of a solo dev with this stack competes with a team of 2-3 devs using a traditional stack (Express + manual PostgreSQL + JWT + S3 + Socket.io). Not because the stack is magic, but because it cuts out weeks of setup that don’t generate value for the client.
When Supabase isn’t the best choice
It would be dishonest to say Supabase works for everything. It doesn’t.
Projects that need a heavily custom backend: heavy data processing, priority queues (Bull/BullMQ), long-running workers, complex data pipelines. Edge Functions are limited in execution time and resources. For that, you need a dedicated server.
Systems that already have a database running. If the company already has PostgreSQL on AWS with 5 years of data, complex schemas, and a DBA team, it doesn’t make sense to migrate to Supabase. Connect React directly to the existing database via a custom API.
Teams that don’t know SQL. Supabase is PostgreSQL. If nobody on the team knows SQL, they’ll struggle with migrations, RLS policies, and dashboard queries. The visual dashboard helps, but it doesn’t replace a solid SQL foundation.
Multi-region. Supabase runs in one datacenter per project. If you need a database replicated across multiple regions for globally low latency, you need a more robust solution (CockroachDB, PlanetScale, or PostgreSQL with manual replication).
Cost
The free plan handles a lot: 50k requests/month, 500 MB of database, 1 GB of storage, 500 MB of bandwidth. For an MVP in validation, that’s more than enough.
The Pro plan ($25/month) is what I use in production. Includes automatic daily backups, 8 GB of database, 100 GB of storage, and support for more simultaneous connections. That’s what runs AutoPars and FitPlan.
Compared to maintaining a VPS + Nginx + Express + PostgreSQL + managing SSL certificates + manual backups + monitoring, $25/month is cheap. And the time I’d spend maintaining infrastructure is time I spend building features for the client.
When it comes to pricing a full system, Supabase as a backend reduces the client’s investment because it reduces my development time. A backend that would take 3-4 weeks to build from scratch takes 2-3 days on Supabase.
And if the project grows past the Pro plan limits, the next tier (Team, $599/month) kicks in when the operation is already making enough to cover it. I’ve never had a project that needed to leave Pro in the first 12 months. The free plan works for validation, Pro works for production, and the migration between them is a single click in the dashboard with no downtime.