Skip to content

Multi-Region

Regions represent geographic or logical deployment zones. Each region can have its own database URL, control plane URL, and lifecycle status. Tenants can be migrated between regions to satisfy compliance requirements or optimize latency.

Region Model

interface Region {
id: string;
display_name: string; // "EU West (Frankfurt)"
slug: string; // "eu_west"
control_plane_url: string; // "https://eu.stratum.example.com"
database_url: string; // stored but never exposed in API responses
is_primary: boolean;
status: "active" | "draining" | "inactive";
metadata: Record<string, unknown>;
}

Region Lifecycle

active ──> draining ──> inactive
StatusDescription
activeAccepting new tenants, serving traffic
drainingNo new tenants, existing tenants being migrated out
inactiveEmpty, can be safely deleted

Creating Regions

const eu = await stratum.createRegion({
display_name: "EU West (Frankfurt)",
slug: "eu_west",
control_plane_url: "https://eu.stratum.example.com",
is_primary: false,
metadata: { provider: "aws", az: "eu-west-1" },
});
const us = await stratum.createRegion({
display_name: "US East (Virginia)",
slug: "us_east",
is_primary: true,
});

Via the API:

Terminal window
curl -X POST http://localhost:3001/api/v1/regions \
-H "X-API-Key: YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "EU West (Frankfurt)",
"slug": "eu_west",
"control_plane_url": "https://eu.stratum.example.com",
"is_primary": false,
"metadata": {"provider": "aws", "az": "eu-west-1"}
}'

Migrating Tenants

Move a tenant to a different region:

await stratum.migrateRegion("tenant-uuid", eu.id);

Via the API:

Terminal window
curl -X POST http://localhost:3001/api/v1/tenants/TENANT_UUID/migrate-region \
-H "X-API-Key: YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"region_id": "EU_REGION_UUID"}'

Migration Validations

The migration checks:

  • Tenant exists and is not archived
  • Target region exists
  • Target region status is active (not draining or inactive)

Managing Regions

List

Terminal window
curl http://localhost:3001/api/v1/regions \
-H "X-API-Key: YOUR_KEY"

Update Status

Drain a region before decommissioning:

Terminal window
curl -X PATCH http://localhost:3001/api/v1/regions/REGION_UUID \
-H "X-API-Key: YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "draining"}'

Delete

Deletion fails if any active tenants are assigned to the region:

Terminal window
curl -X DELETE http://localhost:3001/api/v1/regions/REGION_UUID \
-H "X-API-Key: YOUR_ADMIN_KEY"

Data Residency Example

For GDPR data residency compliance, create regions per jurisdiction and assign tenants accordingly:

// Create jurisdiction-specific regions
const eu = await stratum.createRegion({
display_name: "EU (Frankfurt)",
slug: "eu_frankfurt",
});
const us = await stratum.createRegion({
display_name: "US East (Virginia)",
slug: "us_east",
is_primary: true,
});
// EU customer data stays in EU
await stratum.migrateRegion("eu-tenant-uuid", eu.id);
// US customer data stays in US
await stratum.migrateRegion("us-tenant-uuid", us.id);

Region Slug Rules

Region slugs follow the same rules as tenant slugs:

  • Lowercase letters, digits, and underscores only
  • Must start with a letter
  • Maximum 63 characters
  • Pattern: ^[a-z][a-z0-9_]{0,62}$

Authorization

RouteRequired Scope
GET /api/v1/regionsread
POST /api/v1/regionswrite
PATCH /api/v1/regions/:idwrite
DELETE /api/v1/regions/:idwrite
POST /api/v1/tenants/:id/migrate-regionadmin

Security

The database_url field is stored internally but never exposed in API responses. This prevents accidental leakage of database credentials through the API.