Data Residency
Assign workspaces to geographic regions and route data to region-specific databases for compliance.
Atlas data residency controls let operators assign workspaces to geographic regions (e.g. eu-west, us-east). Each region maps to a dedicated database, ensuring tenant data stays in the correct jurisdiction.
SaaS Feature
Data residency is available on app.useatlas.dev Enterprise plans. Self-hosted deployments manage database routing directly.
Prerequisites
- Active Enterprise plan on app.useatlas.dev
- Internal database configured (
DATABASE_URL) - Platform admin role for dashboard access
- At least one region configured in
atlas.config.ts
How It Works
When a workspace is created or assigned a region, Atlas routes its analytics datasource queries to the region-specific datasource URL configured for that region. Internal data (conversations, audit logs) is stored in the default internal database (DATABASE_URL) regardless of region.
| Concept | Description |
|---|---|
| Region | A geographic identifier (e.g. us-east, eu-west) mapped to database URLs |
| Assignment | A workspace is assigned to a region at creation time |
| Migration | Region can be changed via a cross-region data migration (see below) |
| Default region | New workspaces get the configured default region if none is specified |
Configuration
atlas.config.ts
Add a residency section to your Atlas configuration:
import { defineConfig } from "@atlas/api/lib/config";
export default defineConfig({
datasources: {
default: { url: process.env.ATLAS_DATASOURCE_URL! },
},
enterprise: {
enabled: true,
licenseKey: process.env.ATLAS_ENTERPRISE_LICENSE_KEY,
},
residency: {
regions: {
"us-east": {
label: "US East (Virginia)",
databaseUrl: "postgresql://us-east-db.example.com/atlas",
datasourceUrl: "postgresql://us-east-analytics.example.com/warehouse",
},
"eu-west": {
label: "EU West (Ireland)",
databaseUrl: "postgresql://eu-west-db.example.com/atlas",
datasourceUrl: "postgresql://eu-west-analytics.example.com/warehouse",
},
"ap-southeast": {
label: "Asia Pacific (Singapore)",
databaseUrl: "postgresql://ap-southeast-db.example.com/atlas",
},
},
defaultRegion: "us-east",
},
});Each region requires:
| Field | Required | Description |
|---|---|---|
label | Yes | Human-readable name shown in the admin console |
databaseUrl | Yes | PostgreSQL URL for the region's internal database |
datasourceUrl | No | Override analytics datasource URL for this region |
The defaultRegion must be one of the configured region keys.
Admin UI
Navigate to Admin → Data Residency (platform admin only) to:
- View all configured regions with workspace counts and health status
- See which workspaces are assigned to which regions
- Identify the default region for new workspaces
Region assignment is also visible in the Platform Admin → Workspaces table as a region column.
API
List Configured Regions
curl http://localhost:3001/api/v1/platform/residency/regions \
-H "Authorization: Bearer $TOKEN"Response:
{
"regions": [
{ "region": "us-east", "label": "US East (Virginia)", "workspaceCount": 12, "healthy": true },
{ "region": "eu-west", "label": "EU West (Ireland)", "workspaceCount": 5, "healthy": true }
],
"defaultRegion": "us-east"
}Assign Region to Workspace
curl -X POST http://localhost:3001/api/v1/platform/residency/workspaces/$WORKSPACE_ID/region \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"region": "eu-west"}'Changing a workspace's region triggers a cross-region data migration. See Region Migration below.
Get Workspace Region
curl http://localhost:3001/api/v1/platform/residency/workspaces/$WORKSPACE_ID/region \
-H "Authorization: Bearer $TOKEN"List All Assignments
curl http://localhost:3001/api/v1/platform/residency/assignments \
-H "Authorization: Bearer $TOKEN"Connection Routing
When a workspace has a region assigned:
- Analytics queries — If the region has a
datasourceUrl, queries route to that region-specific datasource instead of the default - Internal writes — All internal data (conversations, audit logs, learned patterns) goes to the default internal database configured via
DATABASE_URL - No region — Workspaces without a region use the default datasource and internal database as before
The routing is transparent to the agent and end users — the same API endpoints work regardless of region.
Misrouting Detection
When running multiple regional API instances, each instance identifies itself via the ATLAS_API_REGION env var (or falls back to residency.defaultRegion from config). If a request arrives from a workspace assigned to a different region, Atlas logs a warning with the request ID, org ID, expected region, and actual region.
The /api/health endpoint includes a region field showing the instance's identity, plus a misroutedRequests counter when any misrouted requests have been detected.
Strict mode
Set ATLAS_STRICT_ROUTING=true (or residency.strictRouting: true in config) to reject misrouted requests with 421 Misdirected Request. The response includes a correctApiUrl hint (from the region's apiUrl config) so the client can redirect:
{
"error": "misdirected_request",
"correctApiUrl": "https://api-eu.useatlas.dev",
"expectedRegion": "eu-west",
"actualRegion": "us-west"
}Region Migration
When a workspace needs to move to a different region, Atlas performs a cross-region data migration. The migration moves conversations, semantic entities, learned patterns, and org-scoped settings from the source region to the target.
How it works
The migration runs in 4 phases:
- Export — workspace data is extracted from the source region's internal database into an export bundle
- Transfer — the bundle is sent to the target region's API via an internal service-to-service endpoint
- Cutover — the workspace's region assignment is updated and caches are flushed
- Cleanup — source data is marked for removal after a 7-day grace period
During migration, the workspace is read-only — write operations (new conversations, settings changes) return 409 Workspace Migrating until the migration completes.
Request a migration
curl -X POST http://localhost:3001/api/v1/admin/residency/migrate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"targetRegion": "eu-west"}'Rate limited to one migration per 30 days per workspace. The migration runs in the background — poll GET /api/v1/admin/residency/migration for status.
Check migration status
curl http://localhost:3001/api/v1/admin/residency/migration \
-H "Authorization: Bearer $TOKEN"What moves
| Data | Strategy |
|---|---|
| Conversations + messages | Exported and imported via bundle |
| Semantic entities (DB-backed) | Exported and imported via bundle |
| Learned patterns | Exported and imported via bundle |
| Org-scoped settings | Exported and imported via bundle |
| Analytics datasource | Customer-managed (not migrated) |
| Auth data (users, sessions) | Global — stays in place |
Configuration
Cross-region transfer requires:
ATLAS_INTERNAL_SECRET— shared secret across all regional API instances for service-to-service authapiUrlon each region config — the target region's public API endpoint
residency: {
regions: {
"us-east": {
label: "US East",
databaseUrl: "postgresql://...",
apiUrl: "https://api-us.useatlas.dev", // required for migration
},
"eu-west": {
label: "EU West",
databaseUrl: "postgresql://...",
apiUrl: "https://api-eu.useatlas.dev",
},
},
defaultRegion: "us-east",
}Retry and cancel
Failed migrations can be retried. Pending migrations can be cancelled:
# Retry a failed migration
curl -X POST http://localhost:3001/api/v1/admin/residency/migrate/$MIGRATION_ID/retry \
-H "Authorization: Bearer $TOKEN"
# Cancel a pending migration
curl -X POST http://localhost:3001/api/v1/admin/residency/migrate/$MIGRATION_ID/cancel \
-H "Authorization: Bearer $TOKEN"Limitations
- Region health checks report all configured regions as healthy (no active probing)
- Requires enterprise license
- Region configuration changes require server restart
- One migration per workspace per 30 days