Skip to main content

ADR-008: Separate Databases Per Product

Date: 2026-07-07
Status: Accepted
Deciders: Pete Carroll


Context​

As Traxs Group expands from RoundTrip to Waypoint and Relay, a fundamental architectural decision must be made: do all three products share a single database, or does each product get its own database?

This decision affects schema evolution, deployment independence, team scalability, data isolation, and the integration story between products.


Decision​

Each Traxs product gets its own dedicated Azure SQL database. Products share data through the Command Center API, not through direct database access.

RoundTrip → sqldb-roundtrip-production
Waypoint → sqldb-waypoint-production
Relay → sqldb-relay-production

Cross-product data sharing uses the Command Center API as the integration layer:

Waypoint needs RoundTrip revenue data:
Waypoint API → Command Center API → RoundTrip API → returns DTO
(never direct database access)

Alternatives Considered​

Option A — Shared Database, Shared Schema​

All three products read and write to the same Azure SQL database. Tables are prefixed or namespaced by product.

Rejected because:

  • A migration in RoundTrip can break Waypoint and Relay — no deployment independence
  • Schema changes require coordination across all product teams
  • A single database becomes a scaling bottleneck as all three products grow
  • Cannot sell, spin off, or deprecate a single product independently
  • A bug that corrupts RoundTrip data could affect Waypoint and Relay data

Option B — Shared Database, Separate Schemas​

One database server, separate schemas per product (roundtrip.*, waypoint.*, relay.*).

Rejected because:

  • Still a single point of failure — if the database goes down, all three products go down
  • Schema separation is a convention, not enforced isolation
  • Migrations still risk cross-schema interference
  • Harder to give each product independent backup/restore policies

Option C — Separate Databases (selected)​

Each product has its own database. Cross-product data sharing via API.

Selected because:

  • True deployment independence — RoundTrip migrations never affect Waypoint
  • Products can scale their databases independently
  • Clean product boundaries support future team structure (one team per product)
  • Products can have independent backup, restore, and retention policies
  • Integration through API is explicit, versioned, and auditable

Consequences​

What becomes easier:

  • Deploying RoundTrip schema changes without affecting other products
  • Scaling each database independently based on actual product usage
  • Onboarding developers to a single product without understanding the others
  • Future team structure — dedicated developers per product work in independent codebases
  • Selling or licensing individual products independently

What becomes harder:

  • Cross-product queries require API calls rather than SQL joins
  • Reporting that spans products (e.g. "total Traxs Group revenue across all products") must aggregate from multiple APIs
  • Client record sync is eventual consistency, not immediate
  • More Azure resources to manage and pay for

The integration pattern:

// Waypoint Executive Dashboard — Revenue Widget
// Does NOT query RoundTrip database directly
// Calls Command Center API which calls RoundTrip API

public async Task<RevenueSnapshot> GetRoundTripRevenueAsync(
Guid tenantId, CancellationToken ct)
{
var response = await _commandCenterClient
.GetAsync($"/v1/roundtrip/revenue-summary?tenantId={tenantId}", ct);

return await response.Content
.ReadFromJsonAsync<RevenueSnapshot>(ct);
}