Return to site

🍃🗄️ DATABASE MULTITENANCY with Spring Boot & ARCONIA

One SaaS. Many customers. How far should data isolation go?

September 26, 2026

🔸 TL;DR

A multitenant SaaS can store every customer's data in the same tables, separate schemas, or separate databases. Arconia brings the tenant context + database routing needed to implement the database-per-tenant model cleanly with Spring Boot.

🔸 1️⃣ WHAT IS ARCONIA?

Arconia is an open-source add-on framework for Spring Boot focused on modern enterprise applications.

It provides modules for:

▪️ Multitenancy

▪️ Dev Services

▪️ OpenTelemetry

▪️ AI observability

▪️ Cloud-native tooling

It complements Spring Boot rather than replacing it.

For database multitenancy, two pieces are particularly interesting:

Arconia resolves the current tenant, propagates it through the request, then its Data JDBC module can route JDBC connections to the corresponding database.

🔸 2️⃣ WHAT IS MULTITENANCY?

A tenant is usually a customer organization, not an individual user.

Imagine a CRM SaaS:

Everyone runs on the same SaaS product, but:

ACME must never see GLOBEX's CRM data.

The architectural question becomes:

Where do we create that isolation boundary?

🔸 3️⃣ THE 3️⃣ DATABASE MULTITENANCY STRATEGIES

There are three classic approaches.

1️⃣ SHARED DATABASE + SHARED TABLES

Every tenant shares the same tables.

Isolation comes from something like:

✅ Cheapest and easiest to operate

⚠️ A missing tenant filter can expose another customer's data

-

2️⃣ SHARED DATABASE + SEPARATE SCHEMAS

Same database server, but each tenant gets its own schema.

✅ Stronger logical isolation

✅ Tables don't require tenant_id everywhere

⚠️ More schemas and migrations to manage

-

3️⃣ DATABASE PER TENANT

Each customer gets its own database.

✅ Strongest of these three data-isolation boundaries

⚠️ More databases, pools, migrations and operations to manage

Hibernate also describes these as discriminator-, schema-, and database-based multitenancy.

🔸 4️⃣ WHY DATABASE-PER-TENANT?

Why not simply add tenant_id everywhere?

Because sometimes strong isolation is worth the operational cost.

▪️ Data isolation A query against ACME's DB cannot accidentally return GLOBEX rows.

▪️ Smaller blast radius A bad query such as:

damages one tenant database rather than every tenant stored in the same tables.

▪️ Independent backup & restore Restore ACME without restoring the complete SaaS dataset.

▪️ Independent scaling A huge customer can move to stronger infrastructure.

▪️ Data residency European and Asian customers can potentially live in different infrastructure locations.

▪️ Lifecycle management Onboarding, migration or deletion can happen database by database.

But database-per-tenant isn't free: Arconia notes that dynamically created tenant data sources each hold a connection pool, so the number of tenant data sources must be controlled.

And separate databases don't automatically mean separate physical infrastructure: if several databases share the same DB server, a server-level failure can still affect them all.

🔸 5️⃣ USE CASE: A MULTITENANT CRM SaaS

Imagine:

Alice authenticates as an ACME user.

Her request carries:

The application determines the tenant once:

Your business code can still simply ask:

It doesn't need:

The database connection itself is already pointing at ACME's database.

That's the interesting part.

🔸 6️⃣ SET IT UP WITH ARCONIA IN 5️⃣ STEPS

Arconia Multitenancy currently requires Java 25+, because its tenant context uses Java ScopedValue.

1️⃣ ADD ARCONIA MULTITENANCY

https://docs.arconia.io/arconia/latest/multitenancy/

https://docs.arconia.io/arconia/latest/multitenancy/data-jdbc/

The Web starter resolves and propagates the tenant. arconia-multitenancy-data-jdbc provides TenantDataSource, which implements database-per-tenant JDBC routing. The Data JDBC module intentionally has no auto-configuration.

-

2️⃣ DECLARE YOUR CRM TENANTS

https://docs.arconia.io/arconia/latest/multitenancy/tenant-details/

Arconia can maintain a known set of tenants and reject unknown or disabled identifiers. For dynamic SaaS onboarding, tenant details can instead come from JDBC or your own TenantDetailsService.

-

3️⃣ CONFIGURE THE CUSTOMER DATABASES

https://docs.spring.io/spring-boot/how-to/data-access.html

Each CRM tenant maps to connection details controlled by the application. Don't construct JDBC URLs directly from an untrusted tenant identifier: use it as a validated lookup key.

-

4️⃣ ROUTE CONNECTIONS WITH TenantDataSource

https://docs.arconia.io/arconia/latest/multitenancy/data-jdbc/

TenantDataSource checks the current tenant and delegates JDBC connections to its database. It works with plain JDBC, JdbcClient, JdbcTemplate, and Spring Data JDBC.

-

5️⃣ LET ARCONIA RESOLVE THE TENANT

By default, the Web starter resolves X-TenantId, validates it and binds it to TenantContext. JDBC access then reaches ACME's datasource rather than requiring tenant_id in each repository query.

The resulting architecture is:

🔸 TAKEAWAYS

▪️ Multitenancy does not automatically mean one DB per customer.

▪️ Shared tables + tenant_id are often the simplest and cheapest model.

▪️ Separate schemas provide an intermediate isolation level.

▪️ Database-per-tenant increases isolation and reduces the potential blast radius of tenant-specific data failures.

▪️ The price is operational complexity: more databases, migrations and connection pools.

▪️ Arconia makes the database-per-tenant model interesting because tenant resolution and JDBC routing become infrastructure concerns instead of business-code concerns. (findAll() and not findAllById("Acme"))

Your repository can remain:

while the architecture decides whether that means:

or:

Same Spring Boot application. Different tenant. Different database. 🗄️

#Java #Spring #SpringBoot #Arconia #Multitenancy #SaaS #PostgreSQL #JDBC #SoftwareArchitecture #CloudNative

https://youtu.be/uZepsaaASO4?si=_VzzOeYH6JYvvwzY

Go further with Java certification:

Java👇

Spring👇

SpringBook👇

JavaFullstackBook👇