Multi-Tenancy, Tenant Isolation, and Deployment Topology Model
Model multi-tenancy, tenant isolation, customer boundary, environment boundary, deployment topology, cloud/on-prem separation, data residency, tenant-scoped identifiers, tenant-aware indexing, tenant-aware events, and production correctness untuk enterprise CPQ/Quote/Order/Billing systems.
Multi-Tenancy, Tenant Isolation, and Deployment Topology Model
1. Core Idea
Enterprise data model harus menjawab pertanyaan:
Data ini milik tenant/customer/deployment/environment mana, dan boundary apa yang tidak boleh dilanggar?
Dalam enterprise SaaS, telco BSS/OSS, CPQ, quote/order/billing, satu platform bisa melayani banyak customer, region, deployment model, dan environment.
Deployment bisa berupa:
- shared SaaS,
- dedicated SaaS,
- private cloud,
- on-prem,
- hybrid,
- region-specific deployment,
- customer-specific instance,
- multi-environment setup: dev, test, staging, prod, DR.
Mental model:
Multi-tenancy is not only infrastructure. It must be encoded in identity, keys, indexes, events, caches, search, read models, audit, and access control.
2. Why Tenant Isolation Matters
Jika tenant isolation tidak jelas:
- customer A bisa melihat quote customer B,
- cache key menampilkan pricing tenant lain,
- search index leak data antar tenant,
- event consumer memproses event tenant yang salah,
- batch job update data semua tenant,
- report mencampur revenue tenant,
- purge/anonymization tenant A menghapus data tenant B,
- on-prem customer menerima config SaaS,
- data residency dilanggar,
- support user mengakses environment salah,
- integration endpoint salah tenant.
Tenant isolation adalah salah satu boundary paling kritikal dalam enterprise production system.
3. Tenant vs Customer vs Account vs Organization
Jangan menyamakan tenant dengan customer.
| Concept | Meaning |
|---|---|
| Tenant | Runtime/data isolation boundary. |
| Customer | Business party buying/using service. |
| Account | Commercial/operational relationship container. |
| Organization | Enterprise hierarchy/legal entity. |
| Deployment | Physical/logical runtime installation. |
| Environment | Prod/staging/dev/test/DR boundary. |
| Region | Geographic/legal/latency boundary. |
Example:
Tenant:
csg-customer-prod-001
Customer inside tenant:
GlobalCorp
Accounts inside customer:
GlobalCorp APAC
GlobalCorp Indonesia
Deployment:
dedicated cloud deployment in APAC region
A tenant may contain many business customers in B2B2X scenarios. Or one customer may have a dedicated tenant.
Verify internal semantics.
4. Tenancy Models
Common models:
| Model | Description |
|---|---|
| Single tenant | One customer/deployment per application/database. |
| Shared database, shared schema | Rows separated by tenant_id. |
| Shared database, separate schema | One schema per tenant. |
| Database per tenant | Strong isolation, higher operational complexity. |
| Deployment per tenant | Dedicated app/runtime/database. |
| Hybrid | Large customers dedicated, smaller shared. |
Each model affects:
- data model,
- key strategy,
- query filters,
- migrations,
- backup/restore,
- reporting,
- event routing,
- tenant provisioning,
- incident blast radius,
- data residency.
5. Tenant Entity
Tenant entity represents isolation boundary.
Fields:
tenant
- id
- tenant_code
- display_name
- tenant_type
- status
- deployment_id
- region_code
- data_residency_region
- isolation_model
- provisioned_at
- suspended_at
- decommissioned_at
Tenant lifecycle:
PROVISIONING
ACTIVE
SUSPENDED
MIGRATING
DECOMMISSIONING
DECOMMISSIONED
Tenant status should affect:
- login/access,
- quote/order creation,
- integrations,
- billing,
- background jobs,
- data exports.
6. Deployment Topology Model
Deployment describes runtime placement.
Fields:
deployment
- id
- deployment_code
- deployment_type
- cloud_provider
- region
- environment
- cluster_id
- database_cluster_id
- message_broker_cluster_id
- search_cluster_id
- status
Deployment type examples:
- shared-saas,
- dedicated-saas,
- private-cloud,
- on-prem,
- disaster-recovery,
- migration-shadow.
Data model may need to know deployment topology for:
- integration endpoint routing,
- data residency,
- support access,
- tenant provisioning,
- backup/restore,
- operational reporting,
- incident blast radius.
7. Environment Boundary
Environment must be explicit.
Examples:
DEV
TEST
SIT
UAT
STAGING
PRODUCTION
DR
SANDBOX
CUSTOMER_TEST
Data should not cross environment boundary casually.
Fields:
environment
- environment_code
- environment_type
- production_like
- data_policy
- integration_policy
Common failure:
Production integration event consumed by staging service.
Include environment in:
- event metadata,
- integration endpoint,
- tenant registry,
- cache namespace,
- search index name,
- logs,
- monitoring,
- data export.
8. Tenant-Scoped Tables
If shared schema, every tenant-owned row needs tenant boundary.
Example:
create table quote (
tenant_id uuid not null,
id uuid not null,
quote_number text not null,
customer_id uuid not null,
status text not null,
created_at timestamptz not null,
primary key (tenant_id, id)
);
Or:
id uuid primary key,
tenant_id uuid not null
with every query filtering tenant_id.
Important:
- primary key strategy,
- foreign key includes tenant_id where possible,
- unique constraints are tenant-scoped,
- indexes include tenant_id,
- API authorization verifies tenant scope,
- cache key includes tenant_id.
9. Tenant-Scoped Unique Constraints
Business numbers may be unique per tenant, not globally.
Example:
create unique index uq_quote_number_per_tenant
on quote (tenant_id, quote_number);
For shared DB:
create unique index uq_order_source_quote_per_tenant
on product_order (tenant_id, source_quote_id, source_quote_version)
where source_quote_id is not null;
If tenant_id is missing from unique key, one tenant can block another tenant's valid business number or source reference.
10. Tenant-Aware Indexing
Common query:
select *
from product_order
where tenant_id = :tenant_id
and customer_id = :customer_id
and status = :status
order by updated_at desc
limit 50;
Index:
create index idx_order_tenant_customer_status_updated
on product_order (tenant_id, customer_id, status, updated_at desc);
Tenant_id should usually be first for tenant-scoped queries in shared schema.
But verify actual query patterns and cardinality.
11. Tenant-Aware Events
Every event should carry tenant/environment where applicable.
Example:
{
"eventId": "uuid",
"eventType": "QuoteAccepted",
"tenantId": "tenant-id",
"environment": "PRODUCTION",
"aggregateType": "QUOTE",
"aggregateId": "quote-id",
"correlationId": "corr-123"
}
Consumers should reject/ignore events outside their tenant/environment scope.
Topic/queue strategy may include:
- shared topic with tenant_id in payload,
- tenant-specific topic,
- deployment-specific broker,
- environment-specific broker.
Do not mix prod and non-prod event streams.
12. Tenant-Aware Cache
Cache key must include tenant and environment.
Bad:
quote:{quoteId}
catalog:offering:{offeringId}
permission:{userId}
Better:
prod:{tenantId}:quote:{quoteId}:v:{version}
prod:{tenantId}:catalog:offering:{offeringId}:v:{version}
prod:{tenantId}:permission:{userId}:v:{permissionVersion}
If catalog is globally shared, key should still reflect version and deployment scope if variations exist.
Failure mode:
Tenant A sees tenant B pricing because cache key lacks tenant_id.
13. Tenant-Aware Search Index
Search index must isolate tenant data.
Options:
| Strategy | Notes |
|---|---|
| Index per tenant | Strong separation, many indexes. |
| Shared index with tenant filter | Simpler, requires strict query filter. |
| Index per deployment/region | Useful for residency. |
| Hybrid | Dedicated index for large tenants. |
Search document should include:
tenant_id
environment
access_scope
data_classification
source_version
indexed_at
Search query must filter tenant/scope server-side.
Do not rely on frontend to filter search results.
14. Tenant-Aware Reporting
Reporting questions:
- report per tenant,
- cross-tenant platform ops,
- customer-specific analytics,
- regional reporting,
- deployment-level performance,
- SaaS aggregate KPI.
Controls:
- row-level security,
- tenant-scoped datasets,
- anonymized aggregate cross-tenant reporting,
- access audit,
- tenant-aware data lineage.
Cross-tenant analytics must be governed because it can expose customer confidential information.
15. Data Residency
Data residency constrains where data can be stored/processed.
Fields:
data_residency_region
allowed_processing_regions
allowed_backup_regions
allowed_support_regions
restricted_export
Data residency affects:
- database location,
- backup location,
- search index,
- logs,
- analytics,
- object storage,
- support access,
- integration endpoint,
- DR region.
Do not assume only main database matters. Derived data stores also count.
16. Regionalization
Region may affect:
- tax,
- currency,
- latency,
- legal entity,
- data residency,
- serviceability,
- product availability,
- deployment,
- integration endpoint,
- support team.
Model:
tenant_region_assignment
- tenant_id
- region_code
- role = PRIMARY / DR / REPORTING / SUPPORT
- effective_from
- effective_to
If customer operates globally, business region and data residency region may differ.
17. Tenant Provisioning
Provisioning creates tenant runtime/data.
Provisioning steps:
- create tenant record,
- assign deployment/region,
- configure identity provider,
- create database/schema/namespace if needed,
- configure integrations,
- seed reference data,
- publish catalog/price baseline,
- create admin users,
- configure backup/monitoring,
- run smoke tests.
Model:
tenant_provisioning_request
- tenant_id
- status
- requested_by
- started_at
- completed_at
- failure_code
Tenant provisioning is a workflow, not manual checklist only.
18. Tenant Configuration
Tenant-specific config may include:
- enabled modules,
- product catalog scope,
- pricing model,
- currency defaults,
- locale/timezone,
- billing integration endpoint,
- OSS endpoint,
- workflow variant,
- feature flags,
- data retention policy,
- custom field enablement,
- API limits.
Model:
tenant_configuration
- tenant_id
- config_key
- config_value
- value_type
- effective_from
- effective_to
- source
Govern tenant config carefully. It can create hidden behavior differences.
19. Tenant Feature Flags
Feature flags can be tenant-scoped.
Fields:
tenant_feature_flag
- tenant_id
- feature_key
- status
- rollout_group
- effective_from
- effective_to
- reason_code
Failure modes:
- feature enabled for wrong tenant,
- old code path and new data model mismatch,
- flag removed before migration complete,
- reporting does not know feature state.
Feature flags should be included in migration/cutover governance.
20. On-Prem and Hybrid Considerations
On-prem deployments may differ:
- customer controls infrastructure,
- upgrade cadence slower,
- integration endpoints local,
- data export restricted,
- telemetry limited,
- support access constrained,
- database version differs,
- event broker differs,
- backup/restore owned by customer,
- schema migration window narrower.
Data model should avoid assuming central SaaS control if on-prem is supported.
Need store:
deployment_type = ON_PREM
upgrade_channel
supported_version
customer_operated
telemetry_policy
21. Tenant Migration
Tenant may migrate:
- shared to dedicated,
- one region to another,
- on-prem to cloud,
- old version to new version,
- tenant split/merge,
- database/schema move.
Model:
tenant_migration
- id
- tenant_id
- from_deployment_id
- to_deployment_id
- migration_type
- status
- started_at
- completed_at
- cutover_at
- rollback_strategy
Migration requires:
- data export/import,
- ID preservation,
- event replay/bridge,
- integration endpoint switch,
- search/read model rebuild,
- cache invalidation,
- reporting continuity,
- data residency validation.
22. Tenant Decommissioning
Decommissioning must follow retention/legal hold.
Steps:
- suspend access,
- stop integrations,
- export/hand over data if contract requires,
- archive required records,
- purge/anonymize allowed data,
- revoke users/secrets,
- delete cache/search/read models,
- stop scheduled jobs,
- remove tenant from routing,
- keep tombstone/audit.
Model:
tenant_decommission_request
- tenant_id
- status
- retention_policy_checked
- legal_hold_checked
- completed_at
23. Tenant-Aware Background Jobs
Batch jobs must be tenant-aware.
Examples:
- quote expiry,
- order reconciliation,
- billing trigger,
- data quality scan,
- retention purge,
- projection rebuild,
- cache warmup.
Fields:
job_run
- tenant_id nullable
- deployment_id
- environment
- job_type
- status
- started_at
- completed_at
Avoid background job accidentally scanning/updating all tenants without explicit scope.
24. PostgreSQL Physical Design
Tenant table:
create table tenant (
id uuid primary key,
tenant_code text not null unique,
display_name text not null,
tenant_type text not null,
status text not null,
deployment_id uuid,
region_code text,
data_residency_region text,
isolation_model text,
provisioned_at timestamptz,
suspended_at timestamptz,
decommissioned_at timestamptz,
created_at timestamptz not null,
updated_at timestamptz not null
);
Deployment table:
create table deployment_topology (
id uuid primary key,
deployment_code text not null unique,
deployment_type text not null,
environment text not null,
cloud_provider text,
region text,
cluster_id text,
database_cluster_id text,
message_broker_cluster_id text,
search_cluster_id text,
status text not null,
created_at timestamptz not null,
updated_at timestamptz not null
);
Tenant config:
create table tenant_configuration (
id uuid primary key,
tenant_id uuid not null references tenant(id),
config_key text not null,
config_value text,
value_type text,
effective_from timestamptz not null,
effective_to timestamptz,
source text,
created_at timestamptz not null,
unique (tenant_id, config_key, effective_from)
);
Useful indexes:
create index idx_tenant_status_region
on tenant (status, region_code);
create index idx_tenant_config_current
on tenant_configuration (tenant_id, config_key)
where effective_to is null;
create index idx_deployment_env_region
on deployment_topology (environment, region, status);
25. Java/JAX-RS Backend Implications
Tenant context should be resolved at request boundary.
Sources:
- authenticated token claim,
- hostname/subdomain,
- path/header,
- API client registration,
- internal service context,
- message/event metadata.
Request handling:
TenantResolver
-> validates tenant status
-> attaches TenantContext
-> all repositories/services require tenant context
Avoid optional tenant filters.
Repository methods should require tenant_id for tenant-owned data:
Quote findById(TenantId tenantId, QuoteId quoteId);
Do not expose findById(quoteId) if shared tenant DB.
26. API Impact
API should define tenant scoping.
Options:
GET /quotes/{id}
X-Tenant-Id: tenant-id
or tenant resolved by auth/subdomain.
For public APIs, do not let clients arbitrarily pass tenant ID unless authorized.
Error cases:
- tenant not found,
- tenant suspended,
- tenant mismatch with token,
- tenant not configured,
- feature disabled for tenant,
- wrong environment.
Use stable error codes.
27. Security and Privacy
Tenant isolation controls:
- tenant-aware auth claims,
- tenant-aware row filtering,
- tenant-aware cache keys,
- tenant-aware events,
- tenant-aware search filters,
- tenant-aware exports,
- tenant-aware admin support access,
- audit cross-tenant access,
- tenant-specific encryption keys if required,
- tenant-specific retention policy if required.
Support/admin cross-tenant access must be controlled and audited.
28. Data Quality Checks
Examples:
-- Tenant-owned rows missing tenant_id
-- Conceptual; run per table where applicable.
select id
from quote
where tenant_id is null;
-- Active tenant without deployment
select id, tenant_code
from tenant
where status = 'ACTIVE'
and deployment_id is null;
-- Current config duplicate
select tenant_id, config_key, count(*)
from tenant_configuration
where effective_to is null
group by tenant_id, config_key
having count(*) > 1;
More advanced checks:
- cross-tenant reference,
- event tenant mismatch,
- cache/search tenant leakage,
- tenant suspended but jobs still running,
- data residency mismatch.
29. Failure Modes
| Failure mode | Symptom | Likely cause | Prevention |
|---|---|---|---|
| Cross-tenant data leak | Customer sees other customer | Missing tenant filter | Tenant context required everywhere |
| Cache tenant leak | Wrong pricing/status shown | Cache key lacks tenant | Tenant-aware cache key |
| Search leak | Search returns other tenant docs | Missing tenant filter/index isolation | Tenant-filtered search |
| Wrong event processed | Consumer updates wrong tenant | Event lacks tenant/environment | Tenant-aware event envelope |
| Data residency breach | Data stored in wrong region | Deployment topology not modelled | Residency metadata/validation |
| Background job overreach | Batch updates all tenants | No tenant scope | Tenant-aware job model |
| Tenant config drift | Behavior inconsistent | Config not versioned/audited | Effective-dated config |
| On-prem upgrade fails | Migration assumes SaaS | Deployment differences hidden | Deployment model |
| Tenant decommission incomplete | Data remains in cache/search | Derived copy registry missing | Decommission workflow |
| Reporting mixes tenants | KPI leak/wrong aggregate | Dataset lacks tenant scope | Tenant-aware analytics |
30. PR Review Checklist
When reviewing tenant/deployment changes, ask:
- Is this data tenant-owned?
- Is tenant_id required and indexed?
- Are unique constraints tenant-scoped?
- Are APIs resolving tenant securely?
- Are cache keys tenant-aware?
- Are events tenant/environment-aware?
- Are search/read models tenant-filtered?
- Are background jobs scoped by tenant?
- Does data residency apply?
- Does deployment topology affect integration endpoint?
- Is tenant config versioned/effective-dated?
- Does this support SaaS, dedicated, on-prem, or hybrid?
- Does purge/decommission cover derived stores?
- Is cross-tenant admin access audited?
31. Internal Verification Checklist
Verify these in the internal CSG/team context:
- Whether product is single-tenant, multi-tenant, dedicated, on-prem, or hybrid.
- Actual meaning of tenant vs customer/account.
- Whether tenant_id exists on operational tables.
- Whether tenant isolation is DB-per-tenant, schema-per-tenant, or row-level.
- Tenant-aware cache/search/event conventions.
- Tenant-aware unique constraint strategy.
- Tenant provisioning/decommissioning process.
- Data residency requirements by customer/region.
- On-prem deployment differences.
- Tenant-specific feature flags/config.
- Support/admin cross-tenant access process.
- Incidents involving cross-tenant leak, tenant config drift, wrong environment, or tenant migration issues.
32. Summary
Multi-tenancy is a data modelling boundary.
A strong model must define:
- tenant,
- customer/account distinction,
- deployment topology,
- environment,
- region/data residency,
- tenant-scoped IDs,
- tenant-aware indexes,
- tenant-aware events,
- tenant-aware cache/search/read models,
- tenant configuration,
- feature flags,
- provisioning,
- migration,
- decommissioning,
- background job scope,
- support/admin access audit.
The key principle:
If tenant boundary is not explicit in your data model and every derived copy, it will eventually be violated by a query, cache, event, search index, batch job, export, or support tool.
You just completed lesson 61 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.