Most AI applications eventually need multi-tenancy — workspaces, teams, or organisations where users share data and resources. Clerk's Organizations feature handles the membership model, role assignment, and permission checks so you don't build this infrastructure yourself.

Enabling Organizations

In the Clerk Dashboard, go to Organizations and enable the feature. Choose whether users can create their own organizations or only be invited. Set the roles you need (Clerk provides admin and member by default; you can add custom roles).

Creating and Joining Organizations

// Client component — create an organization
'use client';
import { useOrganizationList } from '@clerk/nextjs';
 
export function CreateOrgButton() {
  const { createOrganization } = useOrganizationList();
 
  const handleCreate = async () => {
    await createOrganization({ name: 'Acme Corp' });
  };
 
  return <button onClick={handleCreate}>Create Organisation</button>;
}
// Show the organization switcher UI
import { OrganizationSwitcher } from '@clerk/nextjs';
 
export function OrgSwitcher() {
  return (
    <OrganizationSwitcher
      afterCreateOrganizationUrl="/org/:id/dashboard"
      afterSelectOrganizationUrl="/org/:id/dashboard"
    />
  );
}

Reading the Active Organization Server-Side

// app/api/org-documents/route.ts
import { auth } from '@clerk/nextjs/server';
 
export async function GET() {
  const { userId, orgId, orgRole } = auth();
 
  if (!userId || !orgId) {
    return Response.json({ error: 'No active organization' }, { status: 401 });
  }
 
  // orgId scopes the data query to the active org
  const docs = await getDocumentsForOrg(orgId);
  return Response.json(docs);
}

Permission Checks

// Check role in server component
import { auth } from '@clerk/nextjs/server';
 
export default async function AdminPage() {
  const { orgRole } = auth();
 
  if (orgRole !== 'org:admin') {
    return <p>Admin access required.</p>;
  }
 
  return <AdminDashboard />;
}
 
// Check fine-grained permission
import { auth } from '@clerk/nextjs/server';
 
export async function DELETE(req: Request) {
  const { has } = auth();
 
  if (!has({ permission: 'org:documents:delete' })) {
    return Response.json({ error: 'Forbidden' }, { status: 403 });
  }
 
  // proceed with deletion
}
Clerk custom permissions follow the format org:resource:action. Define them in the Clerk Dashboard under Organizations > Roles & Permissions. Assign permissions to roles, then check them with has({ permission: '...' }).

Syncing Organization Data to Your Database

When a user joins or leaves an organization, or their role changes, you need to update your database. Use Clerk webhooks to sync these events.

// app/api/webhooks/clerk/route.ts
import { Webhook } from 'svix';
import { headers } from 'next/headers';
 
export async function POST(req: Request) {
  const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET!);
  const headerPayload = headers();
  const svixId = headerPayload.get('svix-id')!;
  const svixTimestamp = headerPayload.get('svix-timestamp')!;
  const svixSignature = headerPayload.get('svix-signature')!;
 
  const payload = await req.text();
  const event = wh.verify(payload, {
    'svix-id': svixId,
    'svix-timestamp': svixTimestamp,
    'svix-signature': svixSignature,
  }) as { type: string; data: any };
 
  if (event.type === 'organizationMembership.created') {
    await db.insert(orgMembers).values({
      orgId: event.data.organization.id,
      userId: event.data.public_user_data.user_id,
      role: event.data.role,
    });
  }
 
  if (event.type === 'organizationMembership.deleted') {
    await db.delete(orgMembers)
      .where(and(
        eq(orgMembers.orgId, event.data.organization.id),
        eq(orgMembers.userId, event.data.public_user_data.user_id),
      ));
  }
 
  return Response.json({ received: true });
}
Metadata Value
Title Clerk Multi-Tenant Organizations: Roles, Permissions, and Member Management
Tool Clerk
Primary SEO keyword clerk organizations multi-tenant
Secondary keywords clerk roles permissions, clerk organization membership, clerk webhook sync, clerk orgId
Estimated read time 8 minutes
Research date 2026-04-14