Does Supabase Work With Clerk?

Partially CompatibleLast verified: 2026-02-26

You can use Clerk and Supabase together, but they duplicate authentication responsibilities and require careful architecture to avoid conflicts.

Quick Facts

Compatibility
partial
Setup Difficulty
Moderate
Official Integration
No — community maintained
Confidence
high
Minimum Versions

How Supabase Works With Clerk

Clerk and Supabase both handle authentication, which creates architectural overlap. The typical pattern is to use Clerk for user management and UI, then use Clerk's JWT tokens to authenticate requests to Supabase. You disable Supabase's built-in auth or use it only for row-level security (RLS) policies. Clerk provides the session management and pre-built components, while Supabase handles the database and realtime features. The developer experience is smooth once configured: Clerk handles signup/login, and you pass Clerk's JWT to Supabase client initialization. However, you're maintaining two authentication systems, which adds complexity around token refresh, user metadata sync, and logout flows. This combo works best when you want Clerk's superior UX and user management but need Supabase's PostgreSQL database and realtime capabilities. If you only need simple auth, using Supabase alone is simpler.

Best Use Cases

SaaS applications needing polished auth UI (Clerk) with complex relational data (Supabase PostgreSQL)
Real-time collaborative apps where Clerk handles identity and Supabase manages shared state
Multi-tenant platforms using Clerk for org management and Supabase for tenant-isolated data with RLS
Apps requiring advanced user analytics and session management (Clerk) with custom business logic in database (Supabase)

Quick Setup

bash
npm install @clerk/nextjs @supabase/supabase-js
typescript
// pages/api/auth.ts - Setup Supabase client with Clerk JWT
import { createClient } from '@supabase/supabase-js';
import { getAuth } = from '@clerk/nextjs/server';

export async function getSupabaseClient(req, res) {
  const { getToken } = getAuth(req);
  const token = await getToken({ template: 'supabase' });
  
  const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      global: {
        headers: { Authorization: `Bearer ${token}` },
      },
    }
  );
  return supabase;
}

// pages/dashboard.tsx - Usage example
import { useAuth } from '@clerk/nextjs';
import { createClient } from '@supabase/supabase-js';

export default function Dashboard() {
  const { getToken } = useAuth();
  const [data, setData] = React.useState(null);

  React.useEffect(() => {
    (async () => {
      const token = await getToken({ template: 'supabase' });
      const supabase = createClient(
        process.env.NEXT_PUBLIC_SUPABASE_URL!,
        process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
        { global: { headers: { Authorization: `Bearer ${token}` } } }
      );
      const { data } = await supabase.from('posts').select('*');
      setData(data);
    })();
  }, [getToken]);

  return <div>{JSON.stringify(data)}</div>;
}

Known Issues & Gotchas

critical

Token mismatch: Supabase JWT validation fails if Clerk tokens aren't configured as valid JWTs for Supabase

Fix: Configure Supabase to accept Clerk's JWT_TEMPLATE. Set the JWKS URL to Clerk's public key endpoint in your Supabase project settings, or manually verify tokens in your API layer.

warning

User metadata synchronization: Supabase auth_users table won't auto-sync with Clerk's user directory

Fix: Use Clerk webhooks to sync user data to a custom Supabase table (users_profiles). Clerk fires events on user creation/update; catch these and upsert into your Supabase table.

warning

Session logout timing: Logging out from Clerk doesn't invalidate Supabase sessions if you cache tokens client-side

Fix: Always listen to Clerk's onClerkLoaded and session change events to clear Supabase client state and remove cached tokens.

warning

RLS policies expect a user ID in auth.uid(), but Clerk's sub claim might not match your Supabase user table ID

Fix: Map Clerk user IDs to Supabase row IDs explicitly, or use custom claims in Clerk's JWT to include both identifiers.

Alternatives

  • Supabase Auth + Supabase UI: Simpler but less polished authentication UI; all features in one platform
  • Firebase + Clerk: Similar pattern but with Firestore instead of PostgreSQL; better for real-time document-based apps
  • Auth0 + Supabase: More enterprise-focused than Clerk, with deeper customization options

Resources

Related Compatibility Guides

Explore more compatibility guides