Documentation/Core Concepts/B2B Multi-Tenancy & Metadata

B2B Multi-Tenancy & Customer Metadata

In modern SaaS applications, usage is attributed not just to a single email, but across multi-tenant organizations, team workspaces, user roles, and subscription tiers.

---

Structured Customer Object

You can pass a rich structured customer object directly into vibezcheck():

typescript
const result = streamText({
model: vibezcheck('openai/gpt-', {
customer: {
id: 'cus_stripe_888', // Stripe Customer ID or internal userId
userId: 'usr_founder_01', // Explicit internal user ID
email: 'alex@acme.corp', // Customer email
name: 'Alex Developer', // Customer display name
phone: '+15551234567', // Customer phone
orgId: 'org_acme_enterprise', // Multi-tenant Org ID
orgName: 'Acme Corp', // Company name
teamId: 'team_ai_agents', // Team / Workspace ID
role: 'admin', // User role (admin, member, owner)
plan: 'scale', // Subscription plan (starter, scale, enterprise)
tier: 'unlimited', // Billing tier
metadata: { // Custom arbitrary key-values
region: 'eu-central-1',
cost_center: 90210,
department: 'R&D',
feature_flag_beta: true,
},
},
database: supabase,
pricing: { margin: 1.4 },
}),
messages,
});

---

How Metadata Flows

1. `UsageEvent` Snapshot: event.customer retains the full customer profile snapshot.

2. Database Sink: Automatically mapped to columns and merged into the JSONB metadata column in Supabase / PostgreSQL.

3. Stripe Sync: Automatically populated in Stripe Customer metadata (vibez_user_id, org_id, team_id, plan, tier, role).

---

Stripe Customer Metadata Sync

typescript
import { createCustomerManager } from 'vibezcheck';
const manager = createCustomerManager();
// Automatically provisions Stripe customer with all metadata
const { customer } = await manager.getOrCreate({
userId: 'usr_777',
email: 'cto@acme.ai',
name: 'John Doe',
orgId: 'org_acme',
plan: 'growth',
metadata: { seats: 25 },
});
// Update customer metadata when user changes plans
await manager.updateCustomer(customer.id, {
plan: 'enterprise',
metadata: { seats: 100 },
});
Page 6 of 18