Supabase is an open-source Firebase alternative that gives you a PostgreSQL database, authentication, real-time subscriptions, edge functions, and file storage — all from one dashboard with a generous free tier. It is the backend of choice for modern full-stack applications because it combines the power of PostgreSQL with the developer experience of Firebase, without vendor lock-in.
This tutorial walks through building a complete full-stack application with Supabase and Next.js, from database design to deployment.
What Is Supabase?
Supabase wraps PostgreSQL — the world's most trusted relational database — with a modern API layer, authentication system, and developer tooling. Instead of building your backend from scratch (setting up a database, writing an API, implementing auth, configuring file storage), you get all of it from one platform with one SDK. The key difference from Firebase is that Supabase uses standard SQL and open-source technology, so your data is never locked into a proprietary system.
What You Get With Supabase
PostgreSQL Database
Full SQL support, JSONB columns, full-text search, vector embeddings, and 50+ extensions.
Authentication
Email/password, magic links, OAuth (Google, GitHub, Apple, 20+ providers), and phone auth.
Real-time
Subscribe to database changes via WebSockets. Build live dashboards, chat, and collaborative features.
Setting Up a Supabase Project
Project Creation
Create Account and Project
Go to supabase.com and sign up with GitHub. Click "New Project," choose an organization, name your project, set a strong database password (save it somewhere secure), and select the region closest to your users. The project provisions in about 2 minutes.
Get Your API Keys
Go to Settings > API. You need two values: the Project URL (NEXT_PUBLIC_SUPABASE_URL) and the anon public key (NEXT_PUBLIC_SUPABASE_ANON_KEY). The anon key is safe to expose in frontend code because Row Level Security controls what each user can access. Never expose the service_role key in frontend code — it bypasses RLS.
Install the SDK
In your Next.js project, install the Supabase client: npm install @supabase/supabase-js @supabase/ssr. The @supabase/ssr package handles server-side rendering authentication with cookies. Create a .env.local file and add your URL and anon key.
Database Tables and Schema Design
Supabase gives you a full PostgreSQL database with a visual table editor. You can create tables through the dashboard UI or write raw SQL. For production applications, always define your schema in SQL migration files so changes are version-controlled and reproducible.
Schema Design Best Practices
Use UUID Primary Keys
Always use uuid_generate_v4() for primary keys instead of auto-incrementing integers. UUIDs are globally unique, prevent enumeration attacks (users cannot guess other record IDs), and work seamlessly with Supabase Auth (which uses UUIDs for user IDs).
Link Tables to auth.users
Create a foreign key from your table's user_id column to auth.users(id). This ensures data integrity and makes Row Level Security policies simple to write. Every user-owned table should have a user_id column that references the authenticated user.
Add Timestamps
Include created_at (default now()) and updated_at columns on every table. Create a trigger that automatically updates updated_at on row changes. These columns are invaluable for debugging, sorting, and building features like "recently modified."
Authentication
Supabase Auth supports email/password, magic links, phone/SMS, and 20+ OAuth providers out of the box. No third-party auth service needed. Auth integrates directly with your database, so you can write RLS policies based on the authenticated user.
Auth Setup for Next.js
Server-Side (App Router)
Use the @supabase/ssr package to create a server-side Supabase client that reads auth tokens from cookies. This is required for Server Components and Route Handlers in Next.js App Router.
Create a utility function that initializes the Supabase client with cookie-based session handling for each server request.
Client-Side (Browser)
Create a browser Supabase client for client components that need auth state (login forms, protected UI). The client automatically handles session refresh and token storage in cookies.
Use createBrowserClient from @supabase/ssr to initialize the client with your project URL and anon key.
Supported Auth Providers
Row Level Security (RLS)
Row Level Security is the most important Supabase concept to understand. RLS lets you define access policies at the database level, so even if someone bypasses your frontend, they cannot access data they should not see. Without RLS enabled, anyone with your anon key can read and write every row in your database.
Common RLS Policy Patterns
Users Can Only Read Their Own Data
The most common pattern. The policy checks that the row's user_id matches the authenticated user's ID.
CREATE POLICY "Users can view own data" ON tasks FOR SELECT USING (auth.uid() = user_id);
Public Read, Authenticated Write
For content like blog posts or product listings where anyone can read but only logged-in users can create.
CREATE POLICY "Public read" ON posts FOR SELECT USING (true);
CREATE POLICY "Auth write" ON posts FOR INSERT WITH CHECK (auth.uid() IS NOT NULL);
Team-Based Access
For multi-tenant apps where users belong to teams/organizations and can access team data.
CREATE POLICY "Team members can view" ON projects FOR SELECT USING (team_id IN (SELECT team_id FROM team_members WHERE user_id = auth.uid()));
Critical: Always Enable RLS
When you create a new table, RLS is disabled by default. This means anyone with your anon key can read and write all data. Always enable RLS immediately after creating a table, even if you have not written policies yet. A table with RLS enabled and no policies blocks all access, which is safer than no RLS at all.
Real-Time Subscriptions
Supabase real-time lets your frontend subscribe to database changes and receive updates instantly via WebSockets. When a row is inserted, updated, or deleted, every subscribed client receives the change within milliseconds. This powers live features like chat, notifications, collaborative editing, and live dashboards.
Real-Time Use Cases
Live Chat
Subscribe to the messages table filtered by chat room. New messages appear instantly for all participants without polling.
Notifications
Subscribe to a notifications table filtered by user_id. Show a badge count and toast notification when new rows appear.
Live Dashboards
Subscribe to analytics or metrics tables. Charts and numbers update automatically as new data comes in. No manual refresh needed.
Collaborative Editing
Track presence (who is online) and broadcast cursor positions. Supabase Realtime supports presence channels for this use case.
Edge Functions
Supabase Edge Functions are server-side TypeScript functions that run on Deno Deploy at the edge (close to your users). Use them for logic that should not run in the browser: calling third-party APIs with secret keys, processing webhooks, sending emails, and running background tasks.
When to Use Edge Functions
Third-party API calls
Call OpenAI, Stripe, Resend, or any API that requires a secret key. Edge functions keep secrets server-side.
Webhook handlers
Process Stripe webhooks, GitHub webhooks, or any incoming event from external services.
Scheduled tasks (Cron)
Run functions on a schedule using pg_cron. Send daily email digests, clean up old data, or sync with external systems.
Complex data processing
Transform data, generate PDFs, resize images, or run any compute-intensive logic that should not block the frontend.
Storage
Supabase Storage handles file uploads (images, documents, videos) with the same RLS policies as your database. Files are organized in buckets, and you can set access policies per bucket or per file path. The free tier includes 1 GB of storage with 2 GB bandwidth.
Public Buckets
For assets that anyone can access: profile pictures, product images, public documents. Files get a permanent public URL you can use in img tags and links.
Private Buckets
For sensitive files: user uploads, invoices, private documents. Access requires authentication and passes through RLS policies. Generate signed URLs with expiration times for temporary access.
Integrating With Next.js
Supabase and Next.js are the most popular full-stack combination in 2026. The integration is straightforward: Supabase handles your backend (database, auth, storage), Next.js handles your frontend and API routes, and Vercel deploys both.
Integration Architecture
Server Components
Fetch data directly in React Server Components using the server-side Supabase client. Data loads on the server, so the page arrives fully rendered with zero client-side loading states. Use this for page content, metadata, and SEO-critical data.
Client Components
Use the browser Supabase client for interactive features: real-time subscriptions, form submissions, file uploads, and auth state changes. Wrap these in "use client" components and use React hooks for state management.
Route Handlers (API Routes)
For server-side logic that needs the service_role key (admin operations, webhooks), use Next.js Route Handlers in the app/api directory. These run on the server and can perform privileged database operations.
Middleware
Use Next.js middleware to refresh auth sessions on every request. This ensures the session cookie stays fresh and prevents users from being unexpectedly logged out. Supabase provides a helper function for this.
Deployment
Push Code to GitHub
Commit your Next.js project to a GitHub repository. Make sure .env.local is in .gitignore so your keys are not exposed.
Connect to Vercel
Import the repository in Vercel. Add your Supabase environment variables (URL, anon key, and any other secrets). Vercel detects Next.js automatically and configures the build.
Configure Auth Redirect URLs
In the Supabase dashboard, go to Auth > URL Configuration and add your Vercel deployment URL to the allowed redirect URLs. This is required for OAuth and magic link authentication to work on your deployed site.
Deploy Edge Functions
If you use Supabase Edge Functions, deploy them with the Supabase CLI: supabase functions deploy function-name. Set any required secrets with supabase secrets set. Functions deploy in seconds.
Frequently Asked Questions
Is Supabase really free?
Supabase offers a generous free tier that includes 50,000 monthly active users for authentication, 500 MB database storage, 1 GB file storage, 2 million edge function invocations, and 2 GB bandwidth. This is enough to build and run a production app with thousands of users. The Pro plan starts at $25/month when you need more resources. Unlike Firebase, Supabase pricing is predictable because it is based on provisioned resources, not per-read/write charges, so you will not get surprised by a massive bill from a traffic spike.
Should I use Supabase or Firebase in 2026?
Supabase is the better choice for most new projects in 2026. It uses PostgreSQL (the most popular database in the world) instead of a proprietary NoSQL database, which means your data is portable and you can use standard SQL. Supabase is open source, so you can self-host if needed. Row Level Security gives you fine-grained access control at the database level. The main reasons to still choose Firebase are: if you need Firebase ML Kit, if your team is deeply invested in the Google Cloud ecosystem, or if you need Firestore's offline-first sync capabilities for mobile apps.
How do I handle database migrations in Supabase?
Supabase supports database migrations through the Supabase CLI. Run "supabase migration new" to create a new migration file, write your SQL changes, and run "supabase db push" to apply them to your remote database. For production environments, use "supabase db diff" to auto-generate migration files from changes you made in the dashboard. The CLI also supports branching, so you can test migrations on a preview branch before applying to production.
Can Supabase handle real-time features?
Yes, real-time is a core Supabase feature. You can subscribe to database changes (inserts, updates, deletes) on any table and receive updates via WebSockets in milliseconds. This powers features like live chat, collaborative editing, notifications, and dashboards that update automatically. Enable real-time on a table in the dashboard under Database > Replication, then use the Supabase client library to subscribe. Real-time works with Row Level Security, so users only receive updates for rows they have permission to see.
How do I deploy a Supabase + Next.js app?
The simplest deployment is Supabase for the backend (hosted by Supabase) and Vercel for the Next.js frontend. Push your Next.js code to GitHub, connect the repo to Vercel, and add your Supabase environment variables (NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY) in the Vercel dashboard. Vercel deploys automatically on every push. For edge functions, deploy them with "supabase functions deploy" via the CLI. The entire setup takes under 10 minutes and scales automatically.
Complete Creator Academy - All Courses
Master Instagram growth, AI influencers, n8n automation, and digital products for just $99/month. Cancel anytime.
All 4 premium courses (Instagram, AI Influencers, Automation, Digital Products)
100+ hours of training content
Exclusive templates and workflows
Weekly live Q&A sessions
Private community access
New courses and updates included
Cancel anytime - no long-term commitment
✨ Includes: Instagram Ignited • AI Influencers Academy • AI Automations • Digital Products Empire