Back to Blog

Multi-Tenant Architecture: 5-Level Isolation Model

TL;DR

Coomia DIPPublished on June 28, 202520 min read
Share this articleTwitter / X

Multi-Tenant Architecture: 5-Level Isolation Model

“

Series: S2 Architecture Overview · Article 5 | Level: Intermediate | Reading Time: 18 min

TL;DR

  • coomia-dip uses a Tenant → Org → Space → Project → World 5-level isolation model, where each level has clearly defined resource boundaries and permission scopes. Compared to a flat "tenant-user" two-level model, 5-level isolation better maps the real-world complexity of enterprise organizational structures.
  • Data isolation at the Project level is achieved through Doris Database-per-Project for physical isolation, while the World level uses Nessie Branch for logical isolation. The combination ensures absolute cross-tenant isolation and flexible version management within the same project.
  • Auto-Provisioning automatically initializes all necessary resources when a new level is created -- Doris databases, Nessie branches, Kafka topics, MinIO buckets -- transforming "submit a ticket and wait 3 days" into "make an API call and wait 3 seconds."

#1. Introduction: Why 5 Levels

Most SaaS platforms have a two-level multi-tenancy model: Tenant and User. This works for simple scenarios, but problems emerge when your customers are large enterprise groups.

Consider a real-world scenario:

Code
Huaneng Group (Tenant)
├── Huaneng International (subsidiary → Org)
│   ├── East China Branch (business unit → Space)
│   │   ├── Smart O&M Project (project → Project)
│   │   │   ├── Production Environment (world → World)
│   │   │   └── Test Environment (world → World)
│   │   └── Carbon Monitoring Project (project → Project)
│   └── South China Branch (business unit → Space)
├── Huaneng Renewables (subsidiary → Org)
│   └── Wind Power Division (business unit → Space)
│       └── Wind Turbine Health Monitoring (project → Project)
└── Huaneng Nuclear (subsidiary → Org)

If you force-fit a two-level model:

  • Can East China Branch O&M engineers see South China Branch data? They should not.
  • Can test environment data in the Smart O&M Project affect production? Absolutely not.
  • Can Huaneng International managers see Huaneng Renewables wind data? Depends on group policy.

A two-level model cannot express these requirements. You either write extensive custom permission logic or accept security gaps. coomia-dip's 5-level isolation model was designed to solve exactly this problem.

#2. The 5-Level Isolation Model in Detail

#2.1 Level Definitions

Code
Level 1: Tenant
  │  Highest isolation boundary. Different tenants are completely invisible to each other.
  │  Typical mapping: enterprise group, independent company
  │
  ├─ Level 2: Org (Organization)
  │  │  Legal entity or independent accounting unit. Different orgs under the same tenant
  │  │  are invisible by default and require explicit authorization.
  │  │  Typical mapping: subsidiary, business division
  │  │
  │  ├─ Level 3: Space
  │  │  │  Business collaboration unit. Different teams or departments within an org.
  │  │  │  Visible by default within the same org; permissions can be refined.
  │  │  │  Typical mapping: department, regional branch, business line
  │  │  │
  │  │  ├─ Level 4: Project
  │  │  │  │  Independent data domain. Owns its own Doris Database.
  │  │  │  │  Typical mapping: business project, application system
  │  │  │  │
  │  │  │  ├─ Level 5: World
  │  │  │  │  Versioned instance of a project. Nessie Branch isolation.
  │  │  │  │  Typical mapping: production env, test env, simulation sandbox

#2.2 Isolation Mechanisms at Each Level

LevelIsolation TypeTechnical ImplementationCross-Level Visibility
TenantAbsolute isolationIndependent identity domain + independent encryption keysNever cross-tenant
OrgStrong isolationIndependent permission tree + independent quotasRequires tenant admin explicit authorization
SpaceLogical isolationRBAC role domain + resource labelsDiscoverable within same org by default
ProjectData isolationDoris Database-per-ProjectRequires Space-level authorization
WorldVersion isolationNessie Branch-per-WorldSwitchable within same Project

#2.3 WorldContext: The Object That Spans All 5 Levels

In coomia-dip, every gRPC call must carry a WorldContext, which is the runtime representation of the 5-level isolation model:

PROTOBUF
message WorldContext {
  string tenant_id = 1;    // Level 1: Tenant
  string org_id = 2;       // Level 2: Organization
  string space_id = 3;     // Level 3: Space
  string project_id = 4;   // Level 4: Project
  string world_id = 5;     // Level 5: World

  // Authentication info
  string principal_id = 6;        // Current user
  repeated string roles = 7;      // User role list
  map<string, string> claims = 8; // Additional claims (for ABAC)
}

This object is constructed starting from the API Gateway and propagated throughout the entire request chain, ensuring every component knows which isolation level the current operation executes within.

#3. Technical Implementation of Data Isolation

#3.1 Level 4 Isolation: Doris Database-per-Project

Each Project owns an independent Doris Database. This is not using a project_id column to distinguish data within the same database -- that would be logical isolation; this is true physical isolation.

Code
Doris Instance (shared)
├── database: proj_huaneng_ops_001
│   ├── entity_common    (object instances)
│   ├── entity_edge      (relation instances)
│   ├── entity_event     (event records)
│   └── entity_metric    (metric data)
│
├── database: proj_huaneng_carbon_002
│   ├── entity_common
│   ├── entity_edge
│   ├── entity_event
│   └── entity_metric
│
├── database: proj_wind_health_003
│   ├── entity_common
│   ├── entity_edge
│   ├── entity_event
│   └── entity_metric

Why Database-per-Project instead of Database-per-Tenant?

Code
Comparison:

Database-per-Tenant:
  ├── Pros: Simpler management, fewer databases
  ├── Cons: Different projects under same tenant share a Database
  │         → One project's heavy query affects other projects
  │         → DDL changes need coordination across all projects in the tenant
  │         → Cannot configure independent resource quotas per project
  └── Verdict: ❌ Isolation granularity too coarse

Database-per-Project:
  ├── Pros: Independent resource quotas and performance isolation per project
  │         → Heavy queries don't affect other projects
  │         → DDL changes only affect the current project
  │         → Can scale independently
  ├── Cons: More databases (but Doris supports thousands of databases)
  └── Verdict: ✅ Optimal balance

Database-per-World:
  ├── Pros: Maximum isolation
  ├── Cons: Database count explodes (each project may have 10+ Worlds)
  │         → Severe resource waste
  │         → Cross-World queries become nearly impossible
  └── Verdict: ❌ Over-isolation

#3.2 Level 5 Isolation: Nessie Branch-per-World

World-level isolation is achieved through Nessie branches. Nessie is a Git-like data lakehouse catalog manager that works with the Iceberg table format.

Code
Nessie Repository (per Project)
├── Branch: world_production     ← Production environment
│   └── Iceberg Tables:
│       ├── entity_common        (pointing to Iceberg snapshot S-2024-001)
│       ├── entity_edge          (pointing to Iceberg snapshot S-2024-002)
│       └── entity_event         (pointing to Iceberg snapshot S-2024-003)
│
├── Branch: world_staging        ← Staging environment
│   └── Iceberg Tables:
│       ├── entity_common        (pointing to Iceberg snapshot S-2024-004)
│       ├── entity_edge          (inherited from production)
│       └── entity_event         (inherited from production)
│
├── Branch: world_sandbox_alice  ← Alice's sandbox
│   └── Iceberg Tables:          (forked from production)
│       └── ...
│
└── Branch: world_whatif_q3      ← Q3 planning simulation
    └── Iceberg Tables:          (forked from production)
        └── ...

Key Properties of Nessie Branches:

  • O(1) Creation: Creating a new World only requires creating a Nessie branch, which is a metadata operation taking < 100ms. No data copying required.
  • Copy-on-Write: A new World shares all Iceberg data files with its parent World. New data files are only created when writes occur in the new World.
  • Mergeable: Modifications in a sandbox can be merged back into production via Nessie Merge, similar to Git merge.
  • Time Travel: Each World retains a complete version history, allowing rollback to any point in time.

#3.3 Doris + Nessie Working Together

Code
Read operation routing:

Request arrives → Extract WorldContext
               → project_id → Determine Doris Database
               → world_id → Determine Nessie Branch

Case 1: Real-time data query (hot data)
  → Query Doris Database (project_id)
  → Inject world_id filter in SQL
  → Return results

Case 2: Historical data query / time travel
  → Query Nessie Branch (world_id)
  → Get Iceberg snapshot at specified time
  → Query through Doris Iceberg Catalog
  → Return results

Case 3: Cross-World comparison
  → Query two Nessie Branches simultaneously
  → Compare differences between two Iceberg snapshots
  → Return diff results

#4. Compute Isolation

#4.1 Resource Quota Model

Compute isolation ensures one tenant's/project's workload does not affect others. coomia-dip enforces resource quotas at multiple levels:

Code
Tenant Level Quota:
  ├── max_orgs: 50
  ├── max_total_storage: 10TB
  ├── max_concurrent_queries: 1000
  └── max_api_calls_per_minute: 10000

Org Level Quota:
  ├── max_spaces: 20
  ├── max_storage: 2TB (cannot exceed Tenant limit)
  └── max_concurrent_queries: 200

Space Level Quota:
  ├── max_projects: 10
  └── max_storage: 500GB

Project Level Quota:
  ├── max_worlds: 20
  ├── doris_database_size_limit: 100GB
  ├── max_concurrent_queries: 50
  ├── max_object_count: 10,000,000
  └── max_derived_property_computations_per_minute: 1000

World Level Quota:
  ├── max_nessie_branch_size: 50GB (Iceberg data)
  ├── max_concurrent_users: 100
  └── max_event_rate: 500/second

#4.2 Query Resource Isolation

Doris's Workload Group feature is used to implement query-level resource isolation:

SQL
-- Create Workload Group per Project
CREATE WORKLOAD GROUP proj_huaneng_ops_001
PROPERTIES (
  'cpu_share' = '10',
  'memory_limit' = '30%',
  'max_concurrency' = '50',
  'max_queue_size' = '100',
  'queue_timeout' = '5000'
);

-- Queries automatically bind to the Workload Group
SET workload_group = 'proj_huaneng_ops_001';
SELECT ... FROM entity_common WHERE ...;

This ensures that even if a project user executes an extremely resource-intensive query, other projects' query performance is unaffected.

#4.3 Reasoning Compute Isolation

Reasoning & Decision Layer (Reasoning & Decision) compute tasks -- rule engine, derived property computation, AI reasoning -- are isolated through Kubernetes namespaces and resource limits:

YAML
# One Kubernetes Namespace per Tenant
apiVersion: v1
kind: Namespace
metadata:
  name: tenant-huaneng
  labels:
    coomia-dip/tenant-id: "huaneng"

---
# ResourceQuota limits tenant compute resources
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: tenant-huaneng
spec:
  hard:
    requests.cpu: "32"
    requests.memory: "64Gi"
    limits.cpu: "64"
    limits.memory: "128Gi"
    pods: "100"

#5. Permission Inheritance Model

#5.1 Inheritance Direction: Top-Down

Permissions inherit top-down through the 5-level model. Higher-level permissions automatically propagate to lower levels:

Code
Tenant Admin
  │  Has full management permissions for all resources under the tenant
  │
  ├── Org Admin
  │   │  Has management permissions for all Spaces, Projects, Worlds under the org
  │   │  Inherited from Tenant Admin's authorization
  │   │
  │   ├── Space Admin
  │   │   │  Has management permissions for all Projects, Worlds under the space
  │   │   │
  │   │   ├── Project Member
  │   │   │   │  Has operational permissions for all Worlds under the project
  │   │   │   │
  │   │   │   └── World Viewer
  │   │   │       Can only view data in a specific World

#5.2 Permission Override Rules

Code
Rule 1: Higher-level authorization → Lower-level automatic inheritance
  Org Admin authorized for OrgA → Automatically has permissions for all Spaces under OrgA

Rule 2: Lower levels can tighten but not expand
  Space Admin cannot grant permissions beyond what Org Admin provided

Rule 3: Explicit DENY takes precedence over inherited ALLOW
  Even if Org Admin allows access, a Space-level explicit DENY still takes effect

Rule 4: Cross-level authorization requires admin
  Adding an Org A user to Org B's Space requires Tenant Admin

Priority chain:
  Explicit DENY > Explicit ALLOW > Inherited DENY > Inherited ALLOW > Default DENY

#5.3 RBAC + ABAC Hybrid Model

RBAC handles "what a role can do"; ABAC handles "under what conditions it can do it":

Code
RBAC Role Definitions (customizable per Space):

Role: DataEngineer
  Permissions:
    - ObjectType.* : READ
    - ObjectType.create : ALLOW (limited to data-source types)
    - Pipeline.* : READ, WRITE, EXECUTE
    - World.switch : ALLOW

Role: DataAnalyst
  Permissions:
    - ObjectType.* : READ
    - DerivedProperty.* : READ, CREATE
    - Search.* : READ
    - Export.* : ALLOW (limit 1000 rows)

Role: BusinessUser
  Permissions:
    - Dashboard.* : READ
    - Action.execute : ALLOW (limited to approved types)
    - World.switch : DENY (can only see production World)
Code
ABAC Policy Examples:

Policy: "sensitive-data-time-restriction"
  Condition:
    resource.classification == "CONFIDENTIAL"
    AND time.hour < 8 OR time.hour > 20
  Effect: DENY
  Reason: "Confidential data accessible only during business hours"

Policy: "geo-restriction"
  Condition:
    resource.region != principal.department_region
  Effect: DENY
  Reason: "Can only access data from your own region"

Policy: "data-volume-limit"
  Condition:
    request.type == "EXPORT"
    AND request.row_count > 10000
    AND principal.role != "DataEngineer"
  Effect: DENY
  Reason: "Non-engineer roles cannot export more than 10,000 rows"

#6. Auto-Provisioning

#6.1 Pain Points of Traditional Processes

The traditional process for creating a new project environment in enterprise platforms typically looks like this:

Code
Day 1: Submit ticket → "Please create a new database instance"
Day 2: DBA approves → Queued waiting
Day 3: DBA creates database → Configures user permissions
Day 4: Submit ticket → "Please create new Kafka Topics"
Day 5: Messaging admin approves → Creates Topics
Day 6: Submit ticket → "Please create MinIO Bucket"
Day 7: Storage admin approves → Creates Bucket
Day 8: Start development → Discover missing Nessie config
Day 9: ...

Total time: 1-2 weeks
People involved: 3-5 different teams
Failure probability: ~30% (some step missed or misconfigured)

#6.2 Auto-Provisioning Architecture

coomia-dip automates this entire process through the Auto-Provisioning mechanism:

Code
Creating a new Project:

API: POST /api/v1/admin/projects

ProjectProvisioner automatically executes:
  ├── Step 1: Validate quotas (1ms)
  │   ├── Check if Project count under Space exceeds limit
  │   ├── Check if storage quota is sufficient
  │   └── Check if compute resources are allocatable
  │
  ├── Step 2: Create Doris Database (200ms)
  │   ├── CREATE DATABASE proj_{tenant}_{name}_{id}
  │   ├── CREATE TABLE entity_common (...)
  │   ├── CREATE TABLE entity_edge (...)
  │   ├── CREATE TABLE entity_event (...)
  │   ├── CREATE WORKLOAD GROUP proj_{id} (...)
  │   └── GRANT SELECT, INSERT, UPDATE ON proj_{id}.* TO svc_account
  │
  ├── Step 3: Create Nessie Repository (100ms)
  │   ├── Create Nessie Namespace
  │   ├── Create main Branch (default World)
  │   └── Initialize Iceberg table metadata
  │
  ├── Step 4: Create Kafka Topics (300ms)
  │   ├── proj_{id}.data-change (data change events, 12 partitions)
  │   ├── proj_{id}.audit.access (audit logs, 6 partitions)
  │   ├── proj_{id}.audit.mutation (audit logs, 6 partitions)
  │   ├── proj_{id}.subscription (subscription routing, 6 partitions)
  │   └── proj_{id}.derived-property (derived property cascade, 6 partitions)
  │
  ├── Step 5: Create MinIO Bucket (50ms)
  │   ├── Create bucket: proj-{id}
  │   ├── Set lifecycle policy
  │   └── Configure access policy
  │
  ├── Step 6: Create Redis Namespace (10ms)
  │   ├── Configure key prefix: proj:{id}:
  │   └── Set memory quota
  │
  ├── Step 7: Initialize metadata (50ms)
  │   ├── Register Project metadata in PostgreSQL
  │   ├── Create default roles and permissions
  │   └── Record provisioning audit log
  │
  └── Done! Total time: ~800ms

From "submit a ticket, wait 1 week" to "API call, wait 1 second"

#6.3 Rapid World Creation

Creating a new World is even faster than creating a Project because Worlds share the Project's Doris Database:

Code
Creating a new World:

WorldProvisioner automatically executes:
  ├── Step 1: Validate quotas (1ms)
  │   └── Check if World count under Project exceeds limit
  │
  ├── Step 2: Create Nessie Branch (50ms)
  │   ├── Fork from source Branch (usually production)
  │   └── Pure metadata operation, no data copying
  │
  ├── Step 3: Initialize World context (20ms)
  │   ├── Register World metadata
  │   └── Create permission records for world_id
  │
  └── Done! Total time: ~80ms

Creating a new simulation sandbox: 80ms
The sandbox has exactly the same data as production (Copy-on-Write)
Modifications in the sandbox do not affect production

#6.4 Auto-Deprovisioning

When deleting a Project or World, Auto-Deprovisioning automatically cleans up all associated resources:

Code
Deleting a Project:

ProjectDeprovisioner automatically executes:
  ├── Step 1: Verify no active connections (10ms)
  ├── Step 2: Create final snapshot to MinIO (async, non-blocking)
  ├── Step 3: Delete Kafka Topics (200ms)
  ├── Step 4: Delete Nessie Repository (100ms)
  ├── Step 5: DROP DATABASE proj_{id} (500ms)
  ├── Step 6: Clean Redis namespace (10ms)
  ├── Step 7: Mark MinIO Bucket for expiration (not immediate; auto-cleanup in 30 days)
  ├── Step 8: Update PostgreSQL metadata (10ms)
  └── Step 9: Record cleanup audit log (5ms)

Data retention policy:
  - Doris data: Deleted immediately
  - MinIO data: Retained 30 days (recoverable)
  - Audit logs: Retained per topic retention period
  - PostgreSQL metadata: Soft delete, retained 90 days

#7. Cross-Level Queries and Data Sharing

#7.1 Cross-World Queries

Different Worlds within the same Project can be compared, forming the foundation of the "simulation sandbox" feature:

Code
Scenario: Compare data differences between production and sandbox

API: POST /api/v1/ontology/worlds/compare
{
  "source_world": "world_production",
  "target_world": "world_sandbox_q3",
  "object_type": "InventoryItem",
  "compare_properties": ["quantity", "reorder_point"]
}

Internal implementation:
  1. Get production Nessie Branch → Iceberg snapshot A
  2. Get sandbox_q3 Nessie Branch → Iceberg snapshot B
  3. Iceberg provides snapshot-level diff:
     - Added data files
     - Deleted data files
     - Modified rows (via position-delete files)
  4. Return diff results

#7.2 Cross-Project Data Sharing

Different Projects cannot query each other by default, but specific ObjectTypes can be shared through the DataLink mechanism:

Code
DataLink Definition:

{
  "link_name": "shared_equipment_catalog",
  "source_project": "proj_asset_management",
  "source_object_type": "Equipment",
  "target_project": "proj_maintenance",
  "exposed_properties": ["name", "location", "model", "install_date"],
  "hidden_properties": ["purchase_price", "depreciation"],
  "access_mode": "READ_ONLY",
  "sync_mode": "REAL_TIME"   // Real-time sync via Kafka CDC
}

DataLink ensures:

  • The target Project can only see explicitly exposed properties
  • Data is provided in read-only mode
  • Access still goes through OntologyRuntimeService, subject to permission checks and auditing
  • Data lineage automatically records cross-Project dependencies

#7.3 Absolute Cross-Tenant Isolation

Cross-tenant data sharing is absolutely prohibited. No DataLinks, no admin backdoors, no mechanism exists to let Tenant A see Tenant B's data.

Code
Isolation guarantees:

1. Identity isolation: tenant_id in Tenant A's user Token
   will never match Tenant B's resource tenant_id

2. Network isolation: gRPC requests from different Tenants carry different TLS certificates

3. Storage isolation: Doris Database names include tenant_id
   SQL injection cannot cross Database boundaries (Doris permission control)

4. Cache isolation: Redis key prefixes include tenant_id
   Even cache penetration cannot return other tenants' data

5. Audit isolation: tenant_id in audit logs cannot be forged
   Extracted from auth Token by API Gateway and injected

#8. Deployment Topologies

#8.1 Small-Scale Deployment (< 10 tenants)

Code
┌─────────────────────────────────────────┐
│          Shared Infrastructure           │
│                                          │
│  ┌─────────┐  ┌──────┐  ┌──────────┐   │
│  │  Doris   │  │Kafka │  │PostgreSQL│   │
│  │ (shared) │  │(shared)│ │ (shared) │   │
│  │          │  │      │  │          │   │
│  │ DB: t1p1 │  │      │  │          │   │
│  │ DB: t1p2 │  │      │  │          │   │
│  │ DB: t2p1 │  │      │  │          │   │
│  └─────────┘  └──────┘  └──────────┘   │
│                                          │
│  ┌──────┐  ┌──────┐  ┌──────────────┐  │
│  │Redis │  │MinIO │  │Nessie+Iceberg│  │
│  │(shared)│ │(shared)│ │  (shared)    │  │
│  └──────┘  └──────┘  └──────────────┘  │
│                                          │
│  Isolation: Database / Branch / Namespace│
└─────────────────────────────────────────┘

#8.2 Large-Scale Deployment (100+ tenants)

Code
┌──────────────────────────────────────────────┐
│          Tenant Group A (Financial Clients)    │
│                                               │
│  ┌─────────┐  ┌──────┐  ┌──────────────┐    │
│  │ Doris   │  │Kafka │  │Nessie+Iceberg│    │
│  │ Cluster │  │Cluster│  │   Cluster    │    │
│  │(dedicated)│ │(dedicated)│ │(dedicated)  │    │
│  └─────────┘  └──────┘  └──────────────┘    │
│                                               │
│  Features: Independent clusters, physical     │
│  isolation, compliance certified              │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│       Tenant Group B (Manufacturing, shared)  │
│                                               │
│  ┌─────────┐  ┌──────┐  ┌──────────────┐    │
│  │ Doris   │  │Kafka │  │Nessie+Iceberg│    │
│  │ Cluster │  │Cluster│  │   Cluster    │    │
│  │ (shared) │  │(shared)│  │  (shared)    │    │
│  └─────────┘  └──────┘  └──────────────┘    │
│                                               │
│  Features: Shared clusters, logical           │
│  isolation, cost optimized                    │
└──────────────────────────────────────────────┘

#8.3 Hybrid Deployment Strategy

Code
Decision Matrix:

┌─────────────────┬──────────────┬───────────────┐
│ Client Type      │ Isolation    │ Deployment    │
├─────────────────┼──────────────┼───────────────┤
│ Finance/Health  │ Physical     │ Dedicated     │
│ Government      │ Physical     │ Dedicated     │
│ Large Mfg       │ Hybrid       │ Shared+Ded DB │
│ SMB             │ Logical      │ Shared        │
│ Trial/POC       │ Logical      │ Shared        │
└─────────────────┴──────────────┴───────────────┘

#9. Monitoring and Alerting

#9.1 Multi-Tenant Monitoring Dimensions

Code
Level 1 Monitoring (Tenant):
  - API calls / minute
  - Total storage usage
  - Active user count
  - Error rate

Level 4 Monitoring (Project):
  - Doris Database size
  - Query QPS and P99 latency
  - Workload Group resource utilization
  - Kafka Topic consumption lag

Level 5 Monitoring (World):
  - Nessie Branch size
  - Active connections
  - Event publishing frequency
  - Derived property computation queue length

#9.2 Noisy Neighbor Detection

Code
Noisy Neighbor Detection:

Trigger conditions:
  1. A Project's Doris query latency > 2x P95
  2. A Project's Kafka production rate > 80% of quota
  3. A Project's CPU usage > 90% of Workload Group limit

Automatic response:
  1. Alert notification → Project owner + platform ops
  2. Auto-throttle → Reduce the Project's concurrency limit
  3. Query logging → Record queries causing high load
  4. Optimization suggestions → Auto-analyze slow queries and suggest indexes

#10. Comparison with Palantir Foundry Multi-Tenancy

DimensionPalantir Foundrycoomia-dip
Isolation levels3 (Enrollment → Org → Project)5 (+Space +World)
VersioningDataset-level TransactionWorld-level Nessie Branch
Data isolationShared HDFS + ACLDatabase-per-Project
Compute isolationSpark resource poolsDoris Workload Group + K8s Namespace
Simulation sandboxBranch (AIP feature)World (native support)
Auto-provisioningEnrollment process (manual approval)API-driven (< 1 second)

coomia-dip's 5-level model has two more levels than Foundry -- Space and World. Space better maps enterprise internal department structures, while World provides native "simulation sandbox" capability -- something that requires Foundry's AIP (AI Platform) advanced features.

#11. Common Questions and Best Practices

#11.1 When to Create a New Org vs Space

Code
Create a new Org:
  - Independent legal entity (subsidiary)
  - Needs independent billing
  - Requires fully independent admin
  - Data not shared by default

Create a new Space:
  - Department within the same legal entity
  - Shared billing
  - May need cross-department collaboration
  - Data discoverable within org by default

#11.2 When to Create a New World

Code
Must create a new World:
  - Test/staging environment → Avoid affecting production data
  - What-if simulation → Modify data without affecting real environment
  - Data migration validation → Test Schema changes in sandbox
  - Training environment → Provide safe practice space for new users

No need for a new World:
  - Simple permission isolation → RBAC/ABAC is sufficient
  - Different views/dashboards → Dashboard configuration is sufficient
  - Historical data viewing → Time travel (Nessie snapshots) is sufficient

#Key Takeaways

  1. The 5-level isolation model maps the real complexity of enterprise organizations. The Tenant → Org → Space → Project → World hierarchy adds 3 critical dimensions beyond a flat "tenant-user" model: Org maps legal entities, Space maps business units, World maps versioned environments. Each additional isolation level provides finer-grained permission management and resource control.

  2. The "dual insurance" design for data isolation is key. Doris Database-per-Project provides physical-level data isolation; Nessie Branch-per-World provides logical-level version isolation. The former ensures zero possibility of data leakage between projects; the latter makes multi-version management within a project lightweight and zero-cost (O(1) branch creation, Copy-on-Write data sharing).

  3. Auto-Provisioning reduces environment creation from weeks to seconds. Traditional enterprises need 1-2 weeks and coordination among 3-5 teams to create a new project environment. coomia-dip completes creation of Doris Database, Nessie Repository, Kafka Topics, and MinIO Bucket in < 1 second through automated provisioning. This is not just an efficiency improvement -- it changes how teams use environments: from "carefully using scarce environments" to "creating disposable sandboxes on demand."

“

Next Article Preview: [S2-06] Event-Driven Architecture: Kafka's 7 Roles -- a deep dive into how Kafka serves 7 distinct roles: CDC, audit, subscription routing, pipeline triggers, derived property cascade, reasoning triggers, and cross-Layer coordination.

Tags: #multi-tenant #isolation #world #nessie #doris #auto-provisioning #rbac #abac #coomia-dip