.do
Use Cases

B2B SaaS Platform

Build a complete multi-tenant B2B SaaS platform with Business-as-Code

Build a complete, autonomous multi-tenant B2B SaaS platform using Business-as-Code principles.

Overview

This use case demonstrates building a B2B SaaS platform that:

  • Manages multi-tenant organizations autonomously
  • Handles team hierarchies and permissions
  • Processes subscriptions and billing automatically
  • Tracks usage and enforces limits
  • Provides self-service provisioning
  • Delivers analytics and insights
  • Manages support workflows
  • Handles enterprise integrations

Architecture

graph TB subgraph Frontend["User Experience"] UI[Web Application] Admin[Admin Portal] API[REST API] end subgraph Core["Core Platform"] Orgs[Organizations] Teams[Teams & Users] Auth[Authentication] Permissions[Authorization] end subgraph Business["Business Logic"] Subscriptions[Subscription Management] Billing[Billing & Invoicing] Usage[Usage Tracking] Limits[Quota Enforcement] end subgraph AI["AI Services"] Analytics[Analytics Engine] Insights[Business Insights] Support[AI Support Agent] Recommendations[Recommendations] end subgraph Integration["Integrations"] Payment[Payment Provider] Email[Email Service] SSO[SSO/SAML] Webhooks[Webhooks] end UI --> Auth Admin --> Auth API --> Auth Auth --> Permissions Permissions --> Orgs Orgs --> Teams Teams --> Subscriptions Subscriptions --> Billing Subscriptions --> Usage Usage --> Limits Billing --> Payment Orgs --> Email Auth --> SSO Subscriptions --> Webhooks Analytics -.->|AI| Insights Support -.->|AI| Insights Recommendations -.->|AI| Analytics

Core Entities

Organizations

Organizations represent customer companies in a multi-tenant B2B platform.

import $, { db, on, send, ai } from 'sdk.do'

// Create organization
const organization = await $.Organization.create({
  $type: 'Organization',
  name: 'Acme Corporation',
  description: 'Enterprise software company',
  url: 'https://acme.com',
  email: '[email protected]',
  telephone: '+1-555-0100',

  // Organization details
  numberOfEmployees: 500,
  foundingDate: '2015-03-15',
  industry: 'Software',

  // Address
  address: {
    $type: 'PostalAddress',
    streetAddress: '123 Enterprise Blvd',
    addressLocality: 'San Francisco',
    addressRegion: 'CA',
    postalCode: '94105',
    addressCountry: 'US',
  },

  // Settings
  settings: {
    timezone: 'America/Los_Angeles',
    dateFormat: 'MM/DD/YYYY',
    currency: 'USD',
    language: 'en',
  },

  // Metadata
  status: 'active',
  createdAt: new Date(),
  onboardedAt: null,
})

Teams

Teams organize users within organizations with hierarchical structures.

// Create teams
const engineering = await $.Team.create({
  $type: 'PerformingGroup',
  name: 'Engineering',
  description: 'Product engineering team',
  parentOrganization: organization,
  numberOfMembers: 50,
  settings: {
    allowedRoles: ['admin', 'developer', 'viewer'],
    defaultRole: 'developer',
  },
})

const backend = await $.Team.create({
  $type: 'PerformingGroup',
  name: 'Backend',
  description: 'Backend engineering team',
  parentOrganization: organization,
  parentTeam: engineering,
  numberOfMembers: 20,
})

await db.relate(organization, $.hasSubOrganization, engineering)
await db.relate(engineering, $.hasSubOrganization, backend)

Users & Roles

// Create user
const user = await $.Person.create({
  $type: 'Person',
  givenName: 'Jane',
  familyName: 'Smith',
  email: '[email protected]',
  jobTitle: 'Senior Engineer',
  telephone: '+1-555-0123',

  // Authentication
  authProvider: 'email',
  emailVerified: true,

  // Metadata
  status: 'active',
  createdAt: new Date(),
  lastLoginAt: null,
})

// Assign to organization
await db.relate(organization, $.member, user)

// Assign to team with role
await $.Role.assign({
  user,
  team: backend,
  role: 'developer',
  permissions: ['resources.read', 'resources.write', 'deployments.create'],
  assignedBy: adminUser,
  assignedAt: new Date(),
})

Business Functions

1. Organization Onboarding

Complete self-service onboarding workflow with AI assistance.

// Onboarding workflow
on($.Organization.created, async (organization) => {
  // Create onboarding checklist
  const checklist = await $.ItemList.create({
    $type: 'ItemList',
    name: 'Onboarding Checklist',
    itemListElement: [
      {
        $type: 'ListItem',
        name: 'Verify email',
        position: 1,
        status: 'pending',
      },
      {
        $type: 'ListItem',
        name: 'Add team members',
        position: 2,
        status: 'pending',
      },
      {
        $type: 'ListItem',
        name: 'Configure settings',
        position: 3,
        status: 'pending',
      },
      {
        $type: 'ListItem',
        name: 'Create first project',
        position: 4,
        status: 'pending',
      },
      {
        $type: 'ListItem',
        name: 'Set up billing',
        position: 5,
        status: 'pending',
      },
    ],
  })

  await db.relate(organization, $.has, checklist)

  // Send welcome email
  await send($.Email.send, {
    to: organization.email,
    template: 'organization-welcome',
    data: {
      organization,
      checklist,
      setupUrl: `https://app.platform.do/onboarding/${organization.$id}`,
    },
  })

  // Create trial subscription
  await send($.Subscription.createTrial, {
    organization,
    plan: 'professional',
    trialDays: 14,
  })

  // Schedule check-in emails
  await send($.Email.schedule, {
    to: organization.email,
    template: 'onboarding-checkin-day3',
    sendAt: addDays(new Date(), 3),
    data: { organization },
  })

  await send($.Email.schedule, {
    to: organization.email,
    template: 'onboarding-checkin-day7',
    sendAt: addDays(new Date(), 7),
    data: { organization },
  })

  // Assign customer success rep
  const rep = await ai.decide('assign-success-rep', {
    organization,
    size: organization.numberOfEmployees,
    industry: organization.industry,
    plan: 'professional',
  })

  if (rep.shouldAssign) {
    await db.relate(organization, $.assignedTo, rep.representative)

    await send($.Notification.send, {
      to: rep.representative,
      message: `New organization assigned: ${organization.name}`,
      action: { view: organization.$id },
    })
  }
})

// Track onboarding progress
on($.Checklist.itemCompleted, async ({ checklist, item }) => {
  const organization = await db.related(checklist, $.belongsTo, $.Organization).then((orgs) => orgs[0])

  // Calculate completion percentage
  const items = checklist.itemListElement
  const completed = items.filter((i) => i.status === 'completed').length
  const progress = completed / items.length

  await db.update($.Organization, organization.$id, {
    onboardingProgress: progress,
  })

  // Mark as onboarded when complete
  if (progress === 1.0 && !organization.onboardedAt) {
    await db.update($.Organization, organization.$id, {
      onboardedAt: new Date(),
      status: 'onboarded',
    })

    await send($.Organization.onboarded, organization)

    // Send congratulations email
    await send($.Email.send, {
      to: organization.email,
      template: 'onboarding-complete',
      data: { organization },
    })
  }
})

2. Team Management

Hierarchical team structures with role-based access control.

// Add team member
async function addTeamMember(params: { team: Team; user: Person; role: string; permissions?: string[]; invitedBy: Person }) {
  const { team, user, role, permissions, invitedBy } = params

  // Check if user is already a member
  const existing = await db.related(team, $.member, user)
  if (existing.length > 0) {
    throw new Error('User is already a team member')
  }

  // Get organization
  const organization = await db.related(team, $.belongsTo, $.Organization).then((orgs) => orgs[0])

  // Check organization limits
  const subscription = await db.related(organization, $.has, $.Subscription).then((subs) => subs[0])
  const currentMembers = await db.count(organization, $.member)

  if (currentMembers >= subscription.plan.limits.users) {
    throw new Error('Organization has reached user limit')
  }

  // Add to organization if not already a member
  const orgMembers = await db.related(organization, $.member, user)
  if (orgMembers.length === 0) {
    await db.relate(organization, $.member, user)
  }

  // Add to team
  await db.relate(team, $.member, user)

  // Assign role
  const roleAssignment = await $.Role.create({
    $type: 'Role',
    roleName: role,
    member: user,
    memberOf: team,
    permissions: permissions || getDefaultPermissions(role),
    assignedBy: invitedBy,
    startDate: new Date(),
  })

  await db.relate(user, $.hasRole, roleAssignment)

  // Send welcome email
  await send($.Email.send, {
    to: user.email,
    template: 'team-invitation',
    data: {
      team,
      organization,
      role,
      invitedBy,
    },
  })

  await send($.Team.memberAdded, {
    team,
    user,
    role: roleAssignment,
  })

  return roleAssignment
}

// Permission checking
async function checkPermission(user: Person, resource: string, action: string): Promise<boolean> {
  // Get all roles for user
  const roles = await db.related(user, $.hasRole, $.Role)

  // Check if any role has the required permission
  for (const role of roles) {
    const permission = `${resource}.${action}`

    if (role.permissions.includes(permission) || role.permissions.includes(`${resource}.*`)) {
      return true
    }

    // Check wildcard permissions
    if (role.permissions.includes('*')) {
      return true
    }
  }

  return false
}

// Permission middleware
async function requirePermission(resource: string, action: string) {
  return async (context: Context) => {
    const user = context.user

    if (!user) {
      throw new Error('Unauthorized')
    }

    const hasPermission = await checkPermission(user, resource, action)

    if (!hasPermission) {
      throw new Error('Forbidden: Insufficient permissions')
    }

    return context.next()
  }
}

3. Subscription Management

Complete subscription lifecycle with plans, trials, and upgrades.

// Subscription plans
const plans = {
  starter: {
    name: 'Starter',
    price: 49,
    interval: 'month',
    limits: {
      users: 5,
      projects: 10,
      storage: 10, // GB
      apiCalls: 10000,
    },
    features: ['Basic support', 'Email notifications', 'API access'],
  },
  professional: {
    name: 'Professional',
    price: 199,
    interval: 'month',
    limits: {
      users: 25,
      projects: 50,
      storage: 100,
      apiCalls: 100000,
    },
    features: ['Priority support', 'Advanced analytics', 'Custom integrations', 'SSO/SAML'],
  },
  enterprise: {
    name: 'Enterprise',
    price: 999,
    interval: 'month',
    limits: {
      users: -1, // unlimited
      projects: -1,
      storage: 1000,
      apiCalls: 1000000,
    },
    features: ['Dedicated support', 'SLA guarantees', 'Custom contracts', 'On-premise deployment'],
  },
}

// Create subscription
async function createSubscription(params: { organization: Organization; plan: string; paymentMethod?: string; trial?: boolean; trialDays?: number }) {
  const { organization, plan, paymentMethod, trial, trialDays } = params

  const planConfig = plans[plan]
  if (!planConfig) {
    throw new Error('Invalid plan')
  }

  const subscription = await $.Subscription.create({
    $type: 'Subscription',
    name: `${planConfig.name} Plan`,
    provider: organization,

    // Pricing
    price: planConfig.price,
    priceCurrency: 'USD',
    billingPeriod: planConfig.interval,

    // Dates
    startDate: new Date(),
    endDate: null,

    // Trial
    isTrial: trial || false,
    trialEndDate: trial ? addDays(new Date(), trialDays || 14) : null,

    // Plan details
    plan: planConfig,

    // Payment
    paymentMethod: paymentMethod || null,

    // Status
    status: 'active',
    autoRenew: true,
  })

  await db.relate(organization, $.has, subscription)

  // Schedule trial end reminder
  if (trial) {
    await send($.Email.schedule, {
      to: organization.email,
      template: 'trial-ending-soon',
      sendAt: subDays(subscription.trialEndDate, 3),
      data: { organization, subscription },
    })
  }

  await send($.Subscription.created, subscription)

  return subscription
}

// Handle subscription changes
on($.Subscription.created, async (subscription) => {
  const organization = await db.related(subscription, $.belongsTo, $.Organization).then((orgs) => orgs[0])

  // Initialize usage tracking
  await $.UsageRecord.create({
    $type: 'UsageRecord',
    subscription: subscription.$id,
    organization: organization.$id,
    period: {
      start: subscription.startDate,
      end: addMonths(subscription.startDate, 1),
    },
    metrics: {
      users: 0,
      projects: 0,
      storage: 0,
      apiCalls: 0,
    },
  })

  // Log event
  await db.create($.AuditLog, {
    action: 'subscription.created',
    actor: organization.$id,
    target: subscription.$id,
    timestamp: new Date(),
  })
})

// Upgrade subscription
async function upgradeSubscription(params: { subscription: Subscription; newPlan: string; immediate?: boolean }) {
  const { subscription, newPlan, immediate } = params

  const planConfig = plans[newPlan]
  if (!planConfig) {
    throw new Error('Invalid plan')
  }

  // Calculate proration if immediate
  let prorationAmount = 0
  if (immediate) {
    const daysRemaining = differenceInDays(subscription.endDate, new Date())
    const daysInPeriod = differenceInDays(subscription.endDate, subscription.startDate)
    const unusedAmount = (subscription.price * daysRemaining) / daysInPeriod
    const newAmount = (planConfig.price * daysRemaining) / daysInPeriod
    prorationAmount = newAmount - unusedAmount
  }

  // Update subscription
  await db.update($.Subscription, subscription.$id, {
    plan: planConfig,
    price: planConfig.price,
    upgradeScheduled: !immediate,
    upgradeDate: immediate ? new Date() : subscription.endDate,
  })

  // Create invoice if immediate and prorated
  if (immediate && prorationAmount > 0) {
    await send($.Invoice.create, {
      subscription,
      amount: prorationAmount,
      description: `Prorated upgrade to ${planConfig.name}`,
      dueDate: new Date(),
    })
  }

  await send($.Subscription.upgraded, {
    subscription,
    oldPlan: subscription.plan.name,
    newPlan: planConfig.name,
    immediate,
  })
}

4. Usage Tracking & Quota Enforcement

Real-time usage tracking with automatic quota enforcement.

// Track usage
async function trackUsage(params: { organization: Organization; metric: string; amount: number; metadata?: any }) {
  const { organization, metric, amount, metadata } = params

  // Get current subscription
  const subscription = await db.related(organization, $.has, $.Subscription).then((subs) => subs[0])

  if (!subscription) {
    throw new Error('No active subscription')
  }

  // Get current usage record
  const usageRecord = await db
    .list($.UsageRecord, {
      where: {
        subscription: subscription.$id,
        'period.start': { $lte: new Date() },
        'period.end': { $gte: new Date() },
      },
    })
    .then((records) => records[0])

  if (!usageRecord) {
    throw new Error('No usage record found')
  }

  // Update usage
  const newUsage = (usageRecord.metrics[metric] || 0) + amount

  await db.update($.UsageRecord, usageRecord.$id, {
    [`metrics.${metric}`]: newUsage,
    updatedAt: new Date(),
  })

  // Check if approaching limit
  const limit = subscription.plan.limits[metric]
  if (limit > 0) {
    const percentage = newUsage / limit

    // Alert at 80%
    if (percentage >= 0.8 && percentage < 0.9) {
      await send($.Usage.approaching, {
        organization,
        metric,
        current: newUsage,
        limit,
        percentage,
      })
    }

    // Alert at 90%
    if (percentage >= 0.9 && percentage < 1.0) {
      await send($.Usage.warning, {
        organization,
        metric,
        current: newUsage,
        limit,
        percentage,
      })
    }

    // Exceeded
    if (percentage >= 1.0) {
      await send($.Usage.exceeded, {
        organization,
        metric,
        current: newUsage,
        limit,
        percentage,
      })
    }
  }

  // Create usage event
  await db.create($.UsageEvent, {
    organization: organization.$id,
    subscription: subscription.$id,
    metric,
    amount,
    timestamp: new Date(),
    metadata,
  })

  return { current: newUsage, limit }
}

// Check quota before operation
async function checkQuota(organization: Organization, metric: string, required: number = 1): Promise<boolean> {
  const subscription = await db.related(organization, $.has, $.Subscription).then((subs) => subs[0])

  if (!subscription) {
    return false
  }

  const limit = subscription.plan.limits[metric]

  // Unlimited
  if (limit === -1) {
    return true
  }

  // Get current usage
  const usageRecord = await db
    .list($.UsageRecord, {
      where: {
        subscription: subscription.$id,
        'period.start': { $lte: new Date() },
        'period.end': { $gte: new Date() },
      },
    })
    .then((records) => records[0])

  if (!usageRecord) {
    return false
  }

  const current = usageRecord.metrics[metric] || 0
  return current + required <= limit
}

// Quota enforcement middleware
async function enforceQuota(metric: string, required: number = 1) {
  return async (context: Context) => {
    const organization = context.organization

    if (!organization) {
      throw new Error('No organization context')
    }

    const allowed = await checkQuota(organization, metric, required)

    if (!allowed) {
      const subscription = await db.related(organization, $.has, $.Subscription).then((subs) => subs[0])
      const limit = subscription.plan.limits[metric]

      throw new Error(`Quota exceeded: ${metric} limit is ${limit}`)
    }

    // Track usage after successful operation
    context.onSuccess(async () => {
      await trackUsage({
        organization,
        metric,
        amount: required,
      })
    })

    return context.next()
  }
}

// Handle quota exceeded
on($.Usage.exceeded, async (event) => {
  const { organization, metric, current, limit } = event

  // Notify admins
  const admins = await db.list($.Person, {
    where: {
      organization: organization.$id,
      role: 'admin',
    },
  })

  for (const admin of admins) {
    await send($.Email.send, {
      to: admin.email,
      template: 'quota-exceeded',
      priority: 'high',
      data: {
        organization,
        metric,
        current,
        limit,
        upgradeUrl: `https://app.platform.do/billing/upgrade`,
      },
    })
  }

  // AI suggests upgrade
  const recommendation = await ai.decide('suggest-upgrade', {
    organization,
    subscription: await db.related(organization, $.has, $.Subscription).then((subs) => subs[0]),
    usage: event,
  })

  if (recommendation.shouldSuggest) {
    await send($.Notification.send, {
      to: admins,
      template: 'upgrade-suggestion',
      data: {
        recommendation,
        organization,
      },
    })
  }
})

5. Billing & Invoicing

Automated billing with invoice generation and payment processing.

// Generate invoice
async function generateInvoice(subscription: Subscription) {
  const organization = await db.related(subscription, $.belongsTo, $.Organization).then((orgs) => orgs[0])

  // Get usage for billing period
  const usageRecord = await db
    .list($.UsageRecord, {
      where: {
        subscription: subscription.$id,
        'period.end': { $lte: new Date() },
      },
      sort: { 'period.end': -1 },
      limit: 1,
    })
    .then((records) => records[0])

  // Calculate base amount
  let totalAmount = subscription.price

  // Add usage-based charges
  const overages = calculateOverages(usageRecord, subscription.plan.limits)
  totalAmount += overages.total

  // Apply discounts
  const discounts = await db.related(organization, $.has, $.Discount, {
    where: {
      validFrom: { $lte: new Date() },
      validThrough: { $gte: new Date() },
      status: 'active',
    },
  })

  let discountAmount = 0
  for (const discount of discounts) {
    if (discount.type === 'percentage') {
      discountAmount += totalAmount * (discount.value / 100)
    } else {
      discountAmount += discount.value
    }
  }

  totalAmount -= discountAmount

  // Create invoice
  const invoice = await $.Invoice.create({
    $type: 'Invoice',
    identifier: `INV-${Date.now()}`,

    // Parties
    provider: organization,
    customer: organization,

    // Amounts
    totalPaymentDue: {
      $type: 'PriceSpecification',
      price: totalAmount,
      priceCurrency: 'USD',
    },

    // Line items
    referencesOrder: [
      {
        $type: 'OrderItem',
        orderItem: subscription,
        orderQuantity: 1,
        price: subscription.price,
        description: `${subscription.plan.name} Plan`,
      },
      ...overages.items.map((item) => ({
        $type: 'OrderItem',
        orderItem: item.metric,
        orderQuantity: item.amount,
        price: item.rate,
        description: item.description,
      })),
    ],

    // Discounts
    discount: discounts.map((d) => ({
      name: d.name,
      amount: d.type === 'percentage' ? `${d.value}%` : d.value,
    })),

    // Dates
    dateIssued: new Date(),
    paymentDueDate: addDays(new Date(), 30),
    billingPeriod: {
      startDate: usageRecord.period.start,
      endDate: usageRecord.period.end,
    },

    // Status
    paymentStatus: 'due',
  })

  await db.relate(organization, $.receivesInvoice, invoice)

  await send($.Invoice.created, invoice)

  return invoice
}

// Process invoice payment
on($.Invoice.created, async (invoice) => {
  const organization = await db.related(invoice, $.belongsTo, $.Organization).then((orgs) => orgs[0])
  const subscription = await db.related(organization, $.has, $.Subscription).then((subs) => subs[0])

  // Get payment method
  if (!subscription.paymentMethod) {
    // Send payment request email
    await send($.Email.send, {
      to: organization.email,
      template: 'invoice-payment-required',
      data: {
        invoice,
        paymentUrl: `https://app.platform.do/billing/pay/${invoice.$id}`,
      },
    })
    return
  }

  // Attempt automatic payment
  try {
    const payment = await send($.Payment.process, {
      invoice,
      amount: invoice.totalPaymentDue.price,
      currency: invoice.totalPaymentDue.priceCurrency,
      paymentMethod: subscription.paymentMethod,
      customer: organization,
    })

    if (payment.status === 'succeeded') {
      await db.update($.Invoice, invoice.$id, {
        paymentStatus: 'paid',
        paidAt: new Date(),
      })

      // Send receipt
      await send($.Email.send, {
        to: organization.email,
        template: 'payment-receipt',
        data: { invoice, payment },
      })

      await send($.Invoice.paid, { invoice, payment })
    } else {
      throw new Error(payment.error || 'Payment failed')
    }
  } catch (error) {
    // Payment failed
    await send($.Email.send, {
      to: organization.email,
      template: 'payment-failed',
      priority: 'high',
      data: {
        invoice,
        error: error.message,
        updatePaymentUrl: `https://app.platform.do/billing/payment-method`,
      },
    })

    await send($.Invoice.paymentFailed, { invoice, error })
  }
})

// Handle failed payments
on($.Invoice.paymentFailed, async ({ invoice, error }) => {
  const organization = await db.related(invoice, $.belongsTo, $.Organization).then((orgs) => orgs[0])

  // Retry after 3 days
  await send($.Invoice.retryPayment, {
    invoice,
    retryAt: addDays(new Date(), 3),
  })

  // If overdue by 7 days, suspend service
  const daysSinceIssue = differenceInDays(new Date(), invoice.dateIssued)

  if (daysSinceIssue >= 7) {
    const subscription = await db.related(organization, $.has, $.Subscription).then((subs) => subs[0])

    await db.update($.Subscription, subscription.$id, {
      status: 'suspended',
      suspendedAt: new Date(),
      suspensionReason: 'payment-overdue',
    })

    await send($.Subscription.suspended, { subscription, reason: 'payment-overdue' })
  }
})

6. User Provisioning

Automated user provisioning with SSO and SCIM support.

// SCIM user provisioning
async function scimProvisionUser(params: {
  organization: Organization
  userName: string
  name: { givenName: string; familyName: string }
  emails: Array<{ value: string; primary: boolean }>
  active: boolean
  groups?: string[]
}) {
  const { organization, userName, name, emails, active, groups } = params

  // Check if user already exists
  const primaryEmail = emails.find((e) => e.primary)?.value || emails[0].value
  let user = await db
    .list($.Person, {
      where: { email: primaryEmail },
    })
    .then((users) => users[0])

  if (!user) {
    // Create new user
    user = await $.Person.create({
      $type: 'Person',
      givenName: name.givenName,
      familyName: name.familyName,
      email: primaryEmail,
      additionalName: userName,

      // SCIM attributes
      active,
      authProvider: 'scim',

      // Metadata
      status: active ? 'active' : 'inactive',
      createdAt: new Date(),
    })

    // Add to organization
    await db.relate(organization, $.member, user)

    await send($.User.provisioned, { user, organization, source: 'scim' })
  } else {
    // Update existing user
    await db.update($.Person, user.$id, {
      givenName: name.givenName,
      familyName: name.familyName,
      active,
      status: active ? 'active' : 'inactive',
      updatedAt: new Date(),
    })

    await send($.User.updated, { user, source: 'scim' })
  }

  // Assign to groups/teams
  if (groups && groups.length > 0) {
    for (const groupName of groups) {
      const team = await db
        .list($.Team, {
          where: {
            organization: organization.$id,
            name: groupName,
          },
        })
        .then((teams) => teams[0])

      if (team) {
        await db.relate(team, $.member, user)
      }
    }
  }

  return user
}

// SSO authentication
async function ssoAuthenticate(params: { samlResponse: string; organization: Organization }) {
  const { samlResponse, organization } = params

  // Validate SAML response
  const samlData = await validateSAMLResponse(samlResponse, organization)

  if (!samlData.valid) {
    throw new Error('Invalid SAML response')
  }

  // Get or create user
  let user = await db
    .list($.Person, {
      where: {
        email: samlData.email,
        organization: organization.$id,
      },
    })
    .then((users) => users[0])

  if (!user) {
    // Auto-provision user from SAML attributes
    user = await $.Person.create({
      $type: 'Person',
      givenName: samlData.firstName,
      familyName: samlData.lastName,
      email: samlData.email,
      authProvider: 'saml',

      // SAML attributes
      externalId: samlData.nameId,

      status: 'active',
      createdAt: new Date(),
    })

    await db.relate(organization, $.member, user)

    await send($.User.provisioned, { user, organization, source: 'saml' })
  }

  // Update last login
  await db.update($.Person, user.$id, {
    lastLoginAt: new Date(),
  })

  // Create session
  const session = await $.Session.create({
    user: user.$id,
    organization: organization.$id,
    authMethod: 'saml',
    createdAt: new Date(),
    expiresAt: addHours(new Date(), 24),
  })

  await send($.Session.created, session)

  return { user, session }
}

7. Analytics & Reporting

Real-time analytics with AI-powered insights.

// Organization analytics
async function getOrganizationAnalytics(organization: Organization, timeRange: string = '30d') {
  const startDate = subtractTimeRange(new Date(), timeRange)

  // User metrics
  const userMetrics = await db.aggregate($.Person, {
    where: {
      organization: organization.$id,
      createdAt: { $gte: startDate },
    },
    aggregations: {
      total: { $count: '*' },
      active: { $count: '*', where: { lastLoginAt: { $gte: subDays(new Date(), 7) } } },
      newUsers: { $count: '*', where: { createdAt: { $gte: startDate } } },
    },
  })

  // Usage metrics
  const usageMetrics = await db.aggregate($.UsageEvent, {
    where: {
      organization: organization.$id,
      timestamp: { $gte: startDate },
    },
    groupBy: ['metric'],
    aggregations: {
      total: { $sum: 'amount' },
      average: { $avg: 'amount' },
      peak: { $max: 'amount' },
    },
  })

  // Financial metrics
  const financialMetrics = await db.aggregate($.Invoice, {
    where: {
      customer: organization.$id,
      dateIssued: { $gte: startDate },
    },
    aggregations: {
      revenue: { $sum: 'totalPaymentDue.price' },
      paid: { $sum: 'totalPaymentDue.price', where: { paymentStatus: 'paid' } },
      outstanding: { $sum: 'totalPaymentDue.price', where: { paymentStatus: 'due' } },
    },
  })

  // Support metrics
  const supportMetrics = await db.aggregate($.Ticket, {
    where: {
      organization: organization.$id,
      createdAt: { $gte: startDate },
    },
    aggregations: {
      total: { $count: '*' },
      open: { $count: '*', where: { status: 'open' } },
      resolved: { $count: '*', where: { status: 'resolved' } },
      avgResponseTime: { $avg: 'firstResponseTime' },
      avgResolutionTime: { $avg: 'resolutionTime' },
    },
  })

  return {
    users: userMetrics,
    usage: usageMetrics,
    financial: financialMetrics,
    support: supportMetrics,
    timeRange,
    generatedAt: new Date(),
  }
}

// AI-powered insights
async function generateInsights(organization: Organization) {
  const analytics = await getOrganizationAnalytics(organization, '90d')

  // AI analyzes patterns
  const insights = await ai.analyze('organization-health', {
    organization,
    analytics,
    subscription: await db.related(organization, $.has, $.Subscription).then((subs) => subs[0]),
  })

  return {
    health: insights.overallHealth, // 0-100
    trends: insights.trends,
    risks: insights.risks,
    opportunities: insights.opportunities,
    recommendations: insights.recommendations,
  }
}

// Scheduled reporting
setInterval(
  async () => {
    // Get all organizations
    const organizations = await db.list($.Organization, {
      where: { status: 'active' },
    })

    for (const org of organizations) {
      try {
        // Generate weekly report
        const analytics = await getOrganizationAnalytics(org, '7d')
        const insights = await generateInsights(org)

        // Get admins
        const admins = await db.list($.Person, {
          where: {
            organization: org.$id,
            role: 'admin',
          },
        })

        // Send report
        for (const admin of admins) {
          await send($.Email.send, {
            to: admin.email,
            template: 'weekly-analytics-report',
            data: {
              organization: org,
              analytics,
              insights,
            },
          })
        }
      } catch (error) {
        console.error(`Failed to generate report for ${org.name}:`, error)
      }
    }
  },
  7 * 24 * 60 * 60 * 1000
) // Weekly

8. Support Workflows

AI-powered support with ticketing and automation.

// Create support ticket
async function createTicket(params: { organization: Organization; user: Person; subject: string; description: string; priority?: string; category?: string }) {
  const { organization, user, subject, description, priority, category } = params

  // AI analyzes ticket
  const analysis = await ai.analyze('ticket-triage', {
    subject,
    description,
    user,
    organization,
  })

  // Create ticket
  const ticket = await $.Ticket.create({
    $type: 'Ticket',
    identifier: `TICK-${Date.now()}`,

    // Content
    name: subject,
    description,

    // Parties
    customer: user,
    organization,

    // Classification
    category: category || analysis.suggestedCategory,
    priority: priority || analysis.suggestedPriority,

    // AI insights
    sentiment: analysis.sentiment,
    urgency: analysis.urgency,
    suggestedResponse: analysis.suggestedResponse,

    // Status
    status: 'open',
    createdAt: new Date(),
  })

  // Auto-assign based on category
  const agent = await ai.decide('assign-support-agent', {
    ticket,
    category: ticket.category,
    priority: ticket.priority,
    availability: await getSupportAgentAvailability(),
  })

  if (agent.assignTo) {
    await db.relate(ticket, $.assignedTo, agent.assignTo)

    await send($.Notification.send, {
      to: agent.assignTo,
      message: `New ticket assigned: ${subject}`,
      priority: ticket.priority,
      action: { view: ticket.$id },
    })
  }

  // Send acknowledgment
  await send($.Email.send, {
    to: user.email,
    template: 'ticket-created',
    data: {
      ticket,
      estimatedResponse: agent.estimatedResponseTime,
    },
  })

  await send($.Ticket.created, ticket)

  return ticket
}

// AI support agent
on($.Ticket.created, async (ticket) => {
  // Check if AI can auto-resolve
  const resolution = await ai.decide('auto-resolve-ticket', {
    ticket,
    knowledgeBase: await searchKnowledgeBase(ticket.description),
    similarTickets: await findSimilarTickets(ticket),
  })

  if (resolution.canAutoResolve && resolution.confidence > 0.9) {
    // Send resolution
    await send($.Email.send, {
      to: ticket.customer.email,
      template: 'ticket-auto-resolution',
      data: {
        ticket,
        resolution: resolution.solution,
        helpfulArticles: resolution.articles,
        feedbackUrl: `https://app.platform.do/support/feedback/${ticket.$id}`,
      },
    })

    // Mark as resolved
    await db.update($.Ticket, ticket.$id, {
      status: 'resolved',
      resolution: resolution.solution,
      resolvedAt: new Date(),
      resolvedBy: 'ai-agent',
      autoResolved: true,
    })

    await send($.Ticket.resolved, { ticket, resolution })
  } else if (resolution.suggestedResponse) {
    // Suggest response to agent
    const agent = await db.related(ticket, $.assignedTo, $.Person).then((agents) => agents[0])

    if (agent) {
      await send($.Notification.send, {
        to: agent,
        template: 'suggested-response',
        data: {
          ticket,
          suggestion: resolution.suggestedResponse,
        },
      })
    }
  }
})

// SLA monitoring
on($.Ticket.created, async (ticket) => {
  // Define SLA based on priority
  const sla = {
    critical: { firstResponse: 1, resolution: 4 }, // hours
    high: { firstResponse: 4, resolution: 24 },
    medium: { firstResponse: 8, resolution: 48 },
    low: { firstResponse: 24, resolution: 120 },
  }

  const timeLimits = sla[ticket.priority] || sla.medium

  // Schedule SLA breach alerts
  await send($.Alert.schedule, {
    alertAt: addHours(ticket.createdAt, timeLimits.firstResponse * 0.8),
    type: 'sla-warning',
    ticket: ticket.$id,
    metric: 'firstResponse',
  })

  await send($.Alert.schedule, {
    alertAt: addHours(ticket.createdAt, timeLimits.resolution * 0.8),
    type: 'sla-warning',
    ticket: ticket.$id,
    metric: 'resolution',
  })
})

Workflows

Organization Lifecycle

// Complete organization lifecycle
const organizationWorkflow = {
  // 1. Signup
  signup: async (params: SignupParams) => {
    const org = await $.Organization.create(params)
    await send($.Organization.created, org)
    return org
  },

  // 2. Onboarding
  onboard: on($.Organization.created, async (org) => {
    await createOnboardingChecklist(org)
    await createTrialSubscription(org)
    await assignSuccessRep(org)
    await sendWelcomeEmail(org)
  }),

  // 3. Activation
  activate: on($.Organization.onboarded, async (org) => {
    await db.update($.Organization, org.$id, { status: 'active' })
    await scheduleHealthChecks(org)
    await enableFeatures(org)
  }),

  // 4. Growth
  monitor: setInterval(async () => {
    const orgs = await db.list($.Organization, { where: { status: 'active' } })

    for (const org of orgs) {
      const health = await calculateHealthScore(org)

      if (health.score < 50) {
        await send($.Organization.needsAttention, { org, health })
      }
    }
  }, 86400000), // Daily

  // 5. Renewal
  renew: on($.Subscription.expiring, async ({ subscription }) => {
    const org = await db.related(subscription, $.belongsTo, $.Organization).then((orgs) => orgs[0])

    if (subscription.autoRenew) {
      await renewSubscription(subscription)
    } else {
      await sendRenewalReminder(org, subscription)
    }
  }),

  // 6. Churn Prevention
  preventChurn: on($.Organization.needsAttention, async ({ org, health }) => {
    const intervention = await ai.decide('churn-prevention', {
      organization: org,
      health,
    })

    if (intervention.shouldIntervene) {
      await executeChurnPrevention(org, intervention)
    }
  }),
}

Events

// Organization events
on($.Organization.created, async (org) => {
  console.log('New organization:', org.name)
})

on($.Organization.onboarded, async (org) => {
  console.log('Organization onboarded:', org.name)
})

on($.Organization.suspended, async ({ org, reason }) => {
  console.log('Organization suspended:', org.name, reason)
})

// Subscription events
on($.Subscription.created, async (sub) => {
  console.log('New subscription:', sub.plan.name)
})

on($.Subscription.upgraded, async ({ subscription, oldPlan, newPlan }) => {
  console.log('Subscription upgraded:', oldPlan, '->', newPlan)
})

on($.Subscription.cancelled, async (sub) => {
  console.log('Subscription cancelled:', sub.plan.name)
})

// Usage events
on($.Usage.exceeded, async (event) => {
  console.log('Quota exceeded:', event.metric, event.organization.name)
})

// Invoice events
on($.Invoice.created, async (invoice) => {
  console.log('Invoice created:', invoice.identifier)
})

on($.Invoice.paid, async ({ invoice }) => {
  console.log('Invoice paid:', invoice.identifier)
})

// Support events
on($.Ticket.created, async (ticket) => {
  console.log('Ticket created:', ticket.identifier)
})

on($.Ticket.resolved, async ({ ticket }) => {
  console.log('Ticket resolved:', ticket.identifier)
})

Metrics

Track key B2B SaaS metrics:

// Calculate MRR
async function calculateMRR() {
  const subscriptions = await db.list($.Subscription, {
    where: {
      status: 'active',
      isTrial: false,
    },
  })

  const mrr = subscriptions.reduce((total, sub) => {
    if (sub.billingPeriod === 'month') {
      return total + sub.price
    } else if (sub.billingPeriod === 'year') {
      return total + sub.price / 12
    }
    return total
  }, 0)

  return mrr
}

// Calculate churn rate
async function calculateChurnRate(timeRange: string = '30d') {
  const startDate = subtractTimeRange(new Date(), timeRange)

  const activeAtStart = await db.count($.Subscription, {
    where: {
      createdAt: { $lt: startDate },
      status: 'active',
    },
  })

  const cancelled = await db.count($.Subscription, {
    where: {
      cancelledAt: { $gte: startDate },
    },
  })

  return (cancelled / activeAtStart) * 100
}

// Calculate NPS
async function calculateNPS(timeRange: string = '90d') {
  const startDate = subtractTimeRange(new Date(), timeRange)

  const surveys = await db.list($.Survey, {
    where: {
      type: 'nps',
      completedAt: { $gte: startDate },
    },
  })

  const promoters = surveys.filter((s) => s.score >= 9).length
  const detractors = surveys.filter((s) => s.score <= 6).length
  const total = surveys.length

  return ((promoters - detractors) / total) * 100
}

// Calculate LTV
async function calculateLTV(organization: Organization) {
  const orders = await db.list($.Invoice, {
    where: {
      customer: organization.$id,
      paymentStatus: 'paid',
    },
  })

  const totalRevenue = orders.reduce((sum, inv) => sum + inv.totalPaymentDue.price, 0)
  const months = differenceInMonths(new Date(), organization.createdAt)
  const avgMonthlyRevenue = totalRevenue / months

  // Estimate LTV based on churn
  const churnRate = await calculateChurnRate()
  const avgLifetimeMonths = 1 / (churnRate / 100)

  return avgMonthlyRevenue * avgLifetimeMonths
}

Best Practices

1. Multi-Tenancy

  • Strict Isolation: Never query across organizations without explicit relationships
  • Tenant Context: Always include organization/tenant context in queries
  • Database Isolation: Use row-level security or tenant-scoped connections
  • Resource Limits: Enforce per-tenant quotas to prevent abuse

2. Security

  • Role-Based Access Control: Implement fine-grained permissions
  • Audit Logging: Log all administrative actions
  • Data Encryption: Encrypt sensitive data at rest and in transit
  • SSO/SAML: Support enterprise authentication requirements
  • API Security: Use API keys, OAuth2, or JWT for API access

3. Scalability

  • Async Processing: Use event-driven architecture for heavy operations
  • Caching: Cache frequently accessed data per tenant
  • Rate Limiting: Implement per-tenant rate limits
  • Database Optimization: Use proper indexes and query optimization

4. Billing

  • Accurate Tracking: Track usage in real-time with idempotency
  • Flexible Plans: Support multiple pricing models
  • Prorations: Handle plan changes with fair prorations
  • Failed Payments: Implement retry logic with grace periods

5. Customer Success

  • Proactive Monitoring: Track health scores and intervene early
  • Onboarding: Guide customers to activation with clear milestones
  • Support: Provide self-service resources and AI assistance
  • Feedback Loops: Regularly collect and act on customer feedback

6. Analytics

  • Real-Time Metrics: Provide dashboards with live data
  • Cohort Analysis: Track behavior by signup cohort
  • Feature Usage: Monitor which features drive engagement
  • Predictive Analytics: Use AI to predict churn and expansion

Complete Implementation

See the full working example at:

Key Takeaways

  1. Multi-Tenancy First: Design for tenant isolation from day one
  2. Subscription Lifecycle: Automate the entire subscription journey
  3. Usage-Based Billing: Track usage accurately and enforce quotas
  4. Enterprise Features: SSO, SCIM, audit logs are table stakes
  5. Customer Success: Proactive monitoring prevents churn
  6. AI Integration: Use AI for support, insights, and automation

Next Steps


Questions? Check the patterns or join our Discord