Skip to content

refactor(router): separate DB pool configs for master, accounts, and global tenant schemas#13335

Open
sai-harsha-vardhan wants to merge 8 commits into
mainfrom
refactor/split-accounts-global-db-pool-config
Open

refactor(router): separate DB pool configs for master, accounts, and global tenant schemas#13335
sai-harsha-vardhan wants to merge 8 commits into
mainfrom
refactor/split-accounts-global-db-pool-config

Conversation

@sai-harsha-vardhan

Copy link
Copy Markdown
Contributor

Summary

  • Previously the accounts schema (merchant accounts, profiles, MCAs, key stores) and the global tenant schema (users, roles) both reused master_database's pool config, coupling their connection-pool sizing to regular per-tenant payment traffic even though they have very different access patterns.
  • Adds dedicated accounts_database and global_database config blocks for the write/master side of those two pools, sized independently going forward.
  • replica_database stays shared across all three read paths (tenant schema, accounts schema, global schema), since reads don't need the same per-role isolation.
  • get_store() now picks global_database when building the global tenant's store, and master_database/accounts_database otherwise.
  • Updated all deployment config files (config.example.toml, development.toml, docker_compose.toml, config/deployments/env_specific.toml, loadtest/config/development.toml) with the new sections, defaulted to mirror master_database's values so existing deployments aren't broken until operators choose to tune them.

Test plan

  • cargo check -p router -p storage_impl — clean
  • cargo clippy -p router -p storage_impl --no-deps — clean, no new warnings
  • Deploy to a non-prod environment and confirm router/producer/consumer start up and connect using the new config sections
  • Confirm accounts/global schema queries still succeed end-to-end (merchant account CRUD, user/role login flows)

🤖 Generated with Claude Code

…and global tenant schemas

Previously master_database was reused to build the pools for the accounts
schema and the global tenant schema too, coupling their pool sizing
together even though they carry very different traffic patterns. Adds
dedicated accounts_database and global_database config blocks (write side)
while replica_database remains shared across all three read paths.
@sai-harsha-vardhan sai-harsha-vardhan requested a review from a team as a code owner July 15, 2026 13:00
@semanticdiff-com

semanticdiff-com Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  crates/storage_impl/src/database/store.rs  65% smaller
  crates/router/src/services.rs  52% smaller
  crates/router/src/configs/settings.rs  26% smaller
  crates/router/src/routes/app.rs  11% smaller
  crates/storage_impl/src/config.rs  4% smaller
  config/config.example.toml Unsupported file format
  config/deployments/env_specific.toml Unsupported file format
  config/development.toml Unsupported file format
  config/docker_compose.toml Unsupported file format
  crates/router/src/configs/secrets_transformers.rs  0% smaller
  loadtest/config/development.toml Unsupported file format

@sai-harsha-vardhan sai-harsha-vardhan self-assigned this Jul 15, 2026
sai-harsha-vardhan and others added 2 commits July 15, 2026 23:43
…l site instead of inside get_store

get_store previously re-derived "is this the global tenant" via a
tenant_id comparison against config.multitenancy.global_tenant, even
though every caller already knows statically which case it's in (the
global store is built from exactly one call site, separate from the
per-tenant maps). get_store and get_store_interface now just take the
already-resolved master/accounts Database configs as parameters.
@XyneSpaces

Copy link
Copy Markdown
Contributor

[blocking] Please make the new accounts_database and global_database settings backward-compatible, or gate rollout on all deployed config providers being migrated first. This PR makes those settings required and startup now validates/decrypts them, so an existing environment that still only provides master_database will fail during boot instead of falling back to the current single-pool behavior.

sai-harsha-vardhan and others added 2 commits July 16, 2026 11:46
get_store_interface now takes master_config/accounts_config as explicit
params, pushing it to 8 arguments and over clippy's default threshold.
Follows the same allow already used 280+ times elsewhere in this crate.
@sai-harsha-vardhan sai-harsha-vardhan added the S-test-ready Status: This PR is ready for cypress-tests label Jul 16, 2026
@github-actions github-actions Bot removed the S-test-ready Status: This PR is ready for cypress-tests label Jul 16, 2026
sai-harsha-vardhan and others added 2 commits July 16, 2026 12:18
…ical schema/config pools

AppState::with_storage built a full Store (4 bb8 pools each) twice per
tenant -- once via get_store_interface_map for the stores map, once
via get_accounts_store_interface_map for the accounts_store map --
even though both calls are for the same tenant and each only ever
reaches half of the pools it built. Merged into a single
get_store_interface_maps that builds the store once per tenant and
derives both StorageInterface and AccountsStorageInterface from that
one instance.

Also, ReplicaStore::new/Store::new always opened a separate pool for
the accounts schema even when it targets the exact same schema and
connection config as the main pool (always true for the global tenant,
and also true for any regular tenant configured with matching
schema/accounts_schema and matching database config). They now reuse
the existing bb8::Pool (Arc-backed, no new connections) in that case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants