Skip to content

Organizations Backend Implementation

Backend implementation for multi-tenant organization functionality using Better Auth.

Architecture

Organizations are managed by Better Auth's organization plugin, integrated with AdonisJS and PostgreSQL.

Client Request → Better Auth → PostgreSQL → Response

                   Redis (Session Cache)

Data Models

The organization feature uses the following models:

  • Organization - Multi-tenant workspaces with a stored user reference, slug for URL routing, and optional metadata
  • Member - Organization membership records with role-based access (owner, admin, member)
  • Team - Sub-groups within organizations for grouping members
  • Invitation - Pending organization invitations with expiry and status tracking

For complete schema details, field definitions, database structure, and relationships, see:

Better Auth Configuration

Organizations are configured in apps/server/app/lib/auth.ts:

typescript
import { organization } from 'better-auth/plugins'

export const auth = betterAuth({
  // ... other config
  plugins: [
    organization({
      allowUserToCreateOrganization: true,
      organizationLimit: 5,
      membershipLimit: 100,
      teams: { enabled: true },
    }),
  ],
})

Session Context

Active Organization

Sessions track the active organization for workspace context:

typescript
class Session {
  // ... other fields
  activeOrganizationId: string | null // Current workspace
}

This allows:

  • An explicit active workspace context for clients and organization-scoped routes
  • Quick workspace switching without re-authentication
  • Organization-specific permissions checking

Sessions also store activeTeamId. Organization membership lives in members; team membership lives in the separate team_members table.

API Endpoints

Better Auth handles organization, member, invitation, and team operations through /auth/organization/*. See the Authentication API reference for request, response, and status contracts.

Business Rules

  • An authenticated user may create organizations. Better Auth gives the creator the owner membership role, and Jubiloop initializes the organization's separate owner_id metadata field.
  • A user can create up to five organizations.
  • An organization can have up to 100 members.
  • Membership roles are owner, admin, and member; Better Auth enforces role permissions for organization-management operations.
  • The active organization and active team are session context, not membership records.
  • Better Auth membership roles authorize organization-management operations. The separate organizations.owner_id field is application metadata and does not define those permissions.
  • The Member model prevents deletion when the membership's user matches the organization's stored owner_id reference.
  • Team membership is independent of organization membership and uses team_members.
  • Invitation acceptance creates organization membership under Better Auth's organization flow.
  • Current events belong to an organization and are isolated by organization scope. Other organization-owned resource types are planned.

Best Practices

  1. Always check organization context in protected routes
  2. Validate permissions before sensitive operations
  3. Use Better Auth's built-in methods rather than custom implementation when possible
  4. Cache organization list on frontend for quick switching

Built with ❤️ by the Jubiloop team