Multi-tenancy

Aether has been designed with a multi-tenant (a.k.a Team) architecture in mind. For this boilerplate, this means each user is expected to belong to one (and only one) organization.

Current Organization

From within your application's services you will have access to the id of the organization belonging to the current user via the currentUser.organizationId property, found on the API context. As expected, this property will only be available from within services which require authentication.

Model Patterns

Prisma patterns which help to facilitate a multi-tenant architecture.

Uniqueness

When retrieving records from your database, you'll likely only want to find unique models based on some provided information — as well as the organization which the currentUser belongs to. To facilitate this, it's recommended you define a compound unique constraint which includes the provided information as well as the field used to store the organization's id.

Cascading Deletion

When an organization is deleted, it'll likely be desirable to delete all of the organization's related-records. This can be achieved by configuring a cascading delete when defining the foreign key relationship between the organization model and others.

Putting It Together

When combined, the uniqueness and cascading deletion topics described above should result in an implementation which resembles the following.

model Organization {
  id        String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  somethings Something[]
}

model Something {
  id        String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  organization   Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  organizationId String

  @@unique([id, organizationId], name: "tenant")
}