Skip to content

Architecture

Tenants is a Layer 3 host on the Base Template layering (template layering and reuse). Layer suffixes are described in solution structure.

Service contracts

Code-first contracts in ConnectSoft.Saas.Tenants.ServiceModel (namespace ConnectSoft.Saas.Tenants.servicemodel/2025/tenants/):

Contract gRPC adapter
ITenantManagementService GrpcTenantManagementService
ITenantQueryService GrpcTenantQueryService

Tenants-specific gRPC interceptor: TenantGrpcServerInterceptor.

REST surface (TenantsController, api/tenants)

HTTP Route Operation
POST /draft CreateDraftAsync
PUT /activate ActivateAsync
PUT /suspend SuspendAsync
PUT /decommission DecommissionAsync
PUT /residency ChangeResidencyAsync
POST /queries/by-partition GetTenantForTenantAsync
POST /queries/by-id GetTenantByIdAsync
POST /queries/by-tenant-key GetTenantByTenantKeyAsync

DTOs: TenantDto, TenantResponse, request types (CreateTenantDraftRequest, etc.).

Messaging

Publishes the five tenants.domain.v1.* lifecycle events; consumes only its own TenantCreatedEvent via TenantLifecycleSaga. No IConsumer<T> classes - the saga is the only handler.

Persistence

NHibernate + Fluent mapping TenantEntityMap -> table Tenants in schema ConnectSoft.Saas.Tenants. Single-table aggregate with unique constraints UQ_Tenants_TenantId and UQ_Tenants_TenantKey (globally unique tenant id and key - distinct from other contexts where uniqueness is only filter-scoped). FluentMigrator MicroserviceMigration + SampleTenantSeed. Shipped dialect: SQL Server.

Multitenancy uses the shared SaasTenantFilter row filter on TenantId; appsettings Multitenancy defaults to SharedDb.

Concurrency

TenantLifecycleGrain (keyed by tenant partition id) serializes writes per partition.

See also