Deploy Supabase to Production
Complete guide to configuring your Supabase project for production deployment with MakerKit. Covers project setup, migrations, authentication, SMTP, and database webhooks.
Configure your Supabase project for production with Postgres database, Row Level Security (RLS) policies, authentication, and webhooks. This guide covers the complete setup for your MakerKit Next.js Supabase Turbo application.
Complete all steps
Skipping steps will cause authentication failures, missing data, or broken webhooks. Follow this guide completely before testing your application.
Overview
| Task | Purpose |
|---|---|
| Create project | Set up cloud database and auth |
| Push migrations | Create MakerKit database schema |
| Configure auth URLs | Enable OAuth redirects |
| Set up SMTP | Reliable email delivery |
| Update email templates | Fix PKCE authentication issues |
| Link project locally | Enable CLI deployments |
| Configure webhooks | Handle database events |
Create a Supabase Project
If you're not self-hosting Supabase, create a project at supabase.com.
- Sign in to the Supabase Dashboard
- Click New Project
- Choose your organization
- Enter a project name and generate a database password
- Select a region close to your users
Save your database password
Copy the database password immediately. You cannot retrieve it later and will need it to link your local project.
Retrieve API Credentials
Navigate to Project Settings > API to find your credentials:
| Credential | Environment Variable | Usage |
|---|---|---|
| Project URL | NEXT_PUBLIC_SUPABASE_URL | Client and server connections |
| Anon (public) key | NEXT_PUBLIC_SUPABASE_PUBLIC_KEY | Client-side requests |
| Service role key | SUPABASE_SECRET_KEY | Server-side admin operations |

Keep the service role key secret
The service role key bypasses Row Level Security. Never expose it in client-side code or commit it to version control.
Configure Authentication URLs
Set up redirect URLs so authentication flows work correctly.
Navigate to Authentication > URL Configuration and configure:
Site URL
Your production domain:
https://yourdomain.comRedirect URLs
Add this pattern to allow all auth callbacks:
https://yourdomain.com/auth/callback**The ** wildcard matches any path after /auth/callback, which MakerKit uses for different auth flows.
Domain matching
If your production URL includes www, use www in both the Site URL and Redirect URLs. Mismatched domains cause authentication failures.
Configure SMTP
Supabase's built-in email service has strict rate limits (4 emails per hour) and low deliverability. Configure a real SMTP provider for production.
Navigate to Project Settings > Authentication > SMTP Settings:
- Toggle Enable Custom SMTP
- Enter your provider's credentials:
| Field | Example (Resend) |
|---|---|
| Host | smtp.resend.com |
| Port | 465 |
| Username | resend |
| Password | Your API key |
| Sender email | noreply@yourdomain.com |
| Sender name | Your App Name |
Recommended SMTP providers:
- Resend: MakerKit has native integration, simple setup
- SendGrid: High volume, good deliverability
- Mailgun: Developer-friendly, detailed analytics
- Postmark: Excellent deliverability, transactional focus
Update Email Templates
MakerKit provides custom email templates that solve a common Supabase authentication issue.
The Problem
Supabase uses PKCE (Proof Key for Code Exchange) for authentication. When a user clicks a confirmation link in their email and opens it in a different browser than where they signed up, authentication fails because the PKCE verifier is stored in the original browser.
The Solution
MakerKit's templates use token hash URLs instead of PKCE, which work regardless of which browser opens the link.
How to Update
- Find the templates in your project at
apps/web/supabase/templates/ - In Supabase Dashboard, go to Authentication > Email Templates
- For each email type (Confirm signup, Magic Link, etc.), replace the default template with MakerKit's version
- Customize the templates with your branding
For detailed instructions, see the Authentication Emails guide.
Link Your Local Project
Connect your local development environment to your Supabase project using the CLI.
Login to Supabase
pnpm --filter web supabase loginFollow the browser prompts to authenticate.
Link the Project
pnpm --filter web supabase linkSelect your project from the list and enter your database password when prompted.
Verification: Run supabase projects list to confirm the connection.
Push Database Migrations
Deploy MakerKit's database schema to your production Supabase instance:
pnpm --filter web supabase db pushThe CLI displays a list of migrations to apply. Review them and confirm.
Expected tables: After pushing, you should see these tables in your Supabase Dashboard Table Editor:
accounts: Team and personal accountsaccounts_memberships: User-account relationshipssubscriptions: Billing subscriptionssubscription_items: Line items for subscriptionsinvitations: Team invitationsroles: Custom role definitionsrole_permissions: Permission assignments

Configure Database Webhooks
MakerKit uses database webhooks to respond to data changes. The primary webhook handles subscription cleanup when accounts are deleted.
Generate a Webhook Secret
Create a strong secret for authenticating webhook requests:
openssl rand -base64 32Save this as SUPABASE_DB_WEBHOOK_SECRET in your hosting provider's environment variables.
Why Webhooks Matter
When a user deletes their account, MakerKit needs to:
- Cancel their subscription with the billing provider
- Clean up related data
The webhook triggers this cleanup automatically by calling your application's /api/db/webhook endpoint.
Create the Webhook
In Supabase Dashboard, navigate to Database > Webhooks:
- Click Enable Webhooks if prompted
- Click Create a new hook
- Configure the webhook:
| Setting | Value |
|---|---|
| Name | subscriptions_delete |
| Table | public.subscriptions |
| Events | DELETE |
| Type | HTTP Request |
| Method | POST |
| URL | https://yourdomain.com/api/db/webhook |
| Timeout | 5000 |
- Add a header for authentication:
- Name:
X-Supabase-Event-Signature - Value: Your
SUPABASE_DB_WEBHOOK_SECRETvalue
- Name:
Use your production URL
The webhook URL must be publicly accessible. Do not use:
localhostor127.0.0.1- Vercel preview URLs (they require authentication)
- Private network addresses
Test accessibility by visiting the URL in an incognito browser window.
Webhook Configuration Reference
For reference, this is equivalent to the SQL trigger used in local development (from seed.sql):
create trigger "subscriptions_delete" after delete on "public"."subscriptions" for each rowexecute function "supabase_functions"."http_request"( 'https://yourdomain.com/api/db/webhook', 'POST', '{"Content-Type":"application/json", "X-Supabase-Event-Signature":"YOUR_SECRET"}', '{}', '5000');Webhooks for Older Versions
If you're using MakerKit version 2.17.1 or earlier, you need additional webhooks:
| Table | Event | Purpose |
|---|---|---|
public.accounts | DELETE | Clean up account data |
public.subscriptions | DELETE | Cancel billing subscription |
public.invitations | INSERT | Send invitation emails |
Version 2.17.2+ handles invitations through server actions, so only the subscriptions webhook is required.
Set Up Google Auth (Optional)
If you want Google login, configure it in both Google Cloud and Supabase.
In Google Cloud Console
- Create a project at console.cloud.google.com
- Navigate to APIs & Services > Credentials
- Click Create Credentials > OAuth client ID
- Select Web application
- Add authorized redirect URI from Supabase (found in Authentication > Providers > Google)
In Supabase Dashboard
- Go to Authentication > Providers
- Enable Google
- Enter your Client ID and Client Secret from Google Cloud
For detailed setup, see the Supabase Google Auth documentation.
MakerKit automatically shows Google login when you enable it in Supabase. No code changes needed.
Troubleshooting
"Invalid PKCE verifier" error
Users see this when clicking email links from a different browser. Update your email templates to use MakerKit's token hash approach. See Authentication Emails.
Webhooks not triggering
- Verify the URL is publicly accessible
- Check the
X-Supabase-Event-Signatureheader matches your environment variable - Review logs in Database > Webhooks for error messages
- Ensure your application is deployed and running
Authentication redirect fails
- Confirm Site URL matches your exact domain (including
wwwif used) - Verify Redirect URL includes the
**wildcard - Check browser console for specific error messages
Emails not delivered
- Verify SMTP settings in Supabase Dashboard
- Check your email provider's dashboard for delivery logs
- Confirm your sending domain has proper DNS records (SPF, DKIM, DMARC)
Database password lost
If you forgot your database password, reset it in Project Settings > Database > Database Password. You'll need to re-link your local project after resetting.
Frequently Asked Questions
Can I use Supabase's free tier for production?
How do I migrate from local development to production Supabase?
Do I need to manually create RLS policies?
Why do I need database webhooks?
Can I self-host Supabase instead of using their cloud?
Next Steps
- Environment Variables: Complete variable reference with Zod schemas
- Vercel Deployment: Deploy your Next.js application to Vercel
- Authentication Configuration: Configure OAuth providers and SMTP