Multi-Tenant Data Isolation

User Intent

"How do I isolate data for multiple tenants/users in my SaaS application?"

Operation

Concept: Per-user data isolation within a single Graphlit project SDK Method: createUser() + userId parameter in client initialization Use Case: SaaS applications with multiple users/tenants


Strategy: Per-User Scoping in Single Project

Graphlit supports multi-tenancy by creating users within your project and scoping SDK operations to each user.

import { Graphlit, Types } from 'graphlit-client';

// 1. Admin client (no user scoping) for user management
const adminClient = new Graphlit({
  organizationId: process.env.GRAPHLIT_ORGANIZATION_ID!,
  environmentId: process.env.GRAPHLIT_ENVIRONMENT_ID!,
  jwtSecret: process.env.GRAPHLIT_JWT_SECRET!,
});

// 2. When a user signs up (e.g., via Clerk, Supabase, Auth0)
async function onUserSignUp(authUser: { id: string; name: string; email: string }) {
  // Create user in Graphlit (maps to your auth provider's user)
  const user = await adminClient.createUser({
    name: authUser.name,
    identifier: authUser.id,  // Your auth provider's user ID (Clerk, Supabase, etc.)
    type: Types.UserTypes.Human,
  });
  
  // Store user.createUser.id in your database alongside auth user
  await db.users.update(authUser.id, {
    graphlitUserId: user.createUser.id
  });
}

// 3. On each user request, create scoped client
async function handleUserRequest(authUserId: string, request: any) {
  // Get Graphlit user ID from your database
  const graphlitUserId = await db.users.getGraphlitUserId(authUserId);
  
  // Create user-scoped client
  const userClient = new Graphlit({
    organizationId: process.env.GRAPHLIT_ORGANIZATION_ID!,
    environmentId: process.env.GRAPHLIT_ENVIRONMENT_ID!,
    jwtSecret: process.env.GRAPHLIT_JWT_SECRET!,
    userId: graphlitUserId,  // ← ALL operations now scoped to this user
  });
  
  // All content, conversations, and feeds are automatically isolated
  const results = await userClient.queryContents({
    filter: { search: request.query },
  });
  
  return results;  // Only returns this user's content
}

What Gets Scoped?

When you pass userId to the Graphlit client:

User-Scoped (Isolated per User):

  • Content - Documents, files, web pages ingested by this user

  • Conversations - Chat history and AI interactions

  • Feeds - Connected data sources (Slack, Gmail, etc.)

Project-Scoped (Shared Across Users):

  • 📋 Specifications - AI model configurations

  • 📋 Workflows - Content processing pipelines

This means you define AI models and workflows once at the project level, and each user gets isolated data automatically.


Complete Example: Multi-Tenant SaaS


Multi-Tenant Benefits

Complete Data Isolation: Each user's content/conversations/feeds are isolated Single Project Management: One project, shared specifications/workflows Scalable: Thousands of users per project Auth Integration: Works with Clerk, Supabase, Auth0, custom auth Usage Tracking: Per-user usage tracking available


Implementation Checklist


Alternative: Legacy ownerId (Deprecated)

The legacy ownerId parameter is still supported but deprecated. Use userId for new applications.


Last updated

Was this helpful?