ops: data residency configuration for multi-region deployments#390
Merged
0xVida merged 2 commits intoStellar-Fluid:mainfrom Mar 30, 2026
Merged
Conversation
|
@daveades Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
90e944f to
cfafa82
Compare
Add DATABASE_REGION, DATABASE_URL_EU, and DATABASE_URL_US support so each Fluid instance connects to the correct regional database. - regionRouter service maintains a lazy Prisma client pool keyed by region; getDbForRegion() returns the right client for a given region - findApiKeyAcrossRegions() searches all configured regional DBs in parallel at bootstrap so a key is always found regardless of which regional DB it lives in - apiKeyMiddleware attaches res.locals.db (the tenant's regional client) and stores the tenant's region in ApiKeyConfig for downstream use - Tenant model gains a region field (default "US") with an index - Every response carries an X-Fluid-Region header for observability - Tenant and ApiKeyConfig interfaces updated to carry region - 18 unit tests covering URL resolution, client pooling, region detection, and cross-region key lookup resilience closes Stellar-Fluid#211
cfafa82 to
816e856
Compare
Contributor
|
🎉 This PR is included in version 1.21.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Support deploying Fluid with separate databases per region to comply with data residency requirements (GDPR EU isolation).
How it works
Region selection per instance
Set
DATABASE_REGION=EU(orUS) on each server instance. Every response carries anX-Fluid-Regionheader so load balancers and operators can verify routing.Per-region connection strings
If a regional URL is not set,
DATABASE_URLis used as fallback, so single-region deployments require no changes.Regional DB pool (
regionRouterservice)Lazily creates one Prisma client per configured region and caches it for the process lifetime.
getDbForRegion(region)always returns the correct client.Cross-region key bootstrap
findApiKeyAcrossRegions()searches all configured regional DBs in parallel. This solves the bootstrap problem: on the very first request we find the API key regardless of which regional DB it lives in. The resolved region is then cached in Redis so subsequent requests route directly.Request-level DB routing (
apiKeyMiddleware)After resolving an API key, the middleware attaches
res.locals.db(the tenant's regional Prisma client) so all downstream handlers write data to the correct region without any changes to handler code.Schema
Tenantgains aregionfield (default"US") with an index. The migration is a non-destructiveALTER TABLE … ADD COLUMNsafe to run per-region independently.Per-region migration
Files changed
server/src/services/regionRouter.ts— regional DB pool, URL resolution, cross-region key lookupserver/prisma/schema.prisma—regionfield onTenantserver/prisma/migrations/20260329180000_add_tenant_region/— migration SQLserver/src/middleware/apiKeys.ts— attachesres.locals.dbandregiontoApiKeyConfigserver/src/models/tenantStore.ts—regionfield onTenantinterfaceserver/src/index.ts— callsinitializeRegionalDbs()on startup; stampsX-Fluid-Regionheaderserver/.env.example— documentsDATABASE_REGION,DATABASE_URL_EU,DATABASE_URL_USTests
18 unit tests covering:
resolveDbUrl: regional URL priority, DATABASE_URL fallback, dev.db fallbackDEFAULT_REGION: env var reading and uppercase normalisationgetDbForRegion: client pool caching (same instance per region, distinct across regions)isRegionIsolated/getConfiguredRegions: correct region set based on envfindApiKeyAcrossRegions: null for missing key, resilience when one regional DB errors, multi-region parallel searchcloses #211