Backend Development 14 min read

Implementing Multi‑Tenant Architecture with Spring Boot and Spring Cloud

This article explains the concept, advantages, design considerations, and step‑by‑step implementation of a multi‑tenant architecture using Spring Boot and Spring Cloud, covering database strategies, tenant isolation, dynamic routing, and deployment scenarios for SaaS applications.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing Multi‑Tenant Architecture with Spring Boot and Spring Cloud

Overview

Multi‑tenant architecture allows multiple tenants to access a single application while keeping each tenant's resources and data isolated. It enables personalized solutions, reduces operational costs, saves development effort, and improves scalability.

Advantages

Better meet diverse tenant requirements.

Lower infrastructure and maintenance costs.

Reuse code to accelerate onboarding of new tenants.

Enhanced scalability through horizontal expansion.

Technical Choices

The most important factor is a correct architectural approach; however, choosing appropriate technologies speeds up implementation.

Design Approach

Framework Selection

For Java‑based multi‑tenant applications, Spring Boot and Spring Cloud are recommended. Spring Boot simplifies project setup, while Spring Cloud provides tools for micro‑service architecture.

Spring Boot

Spring Boot auto‑configures common libraries, reducing developer effort.

@RestController
public class TenantController {

    @GetMapping("/hello")
    public String hello(@RequestHeader("tenant-id") String tenantId) {
        return "Hello, " + tenantId;
    }
}

Spring Cloud

Spring Cloud offers solutions such as Eureka, Zookeeper, and Consul for service discovery and load balancing, which are useful in multi‑tenant systems.

Database Design

Two common strategies ensure data isolation:

Shared database with a tenant_id column in each table.

Separate database per tenant with identical schemas.

Application Deployment

Application Isolation

Isolate tenants using containers, virtual machines, or namespaces; Docker is a popular choice.

Tenant‑Specific Configuration

Store configuration per tenant (e.g., ports, SSL certificates) in a database or cloud configuration center.

Tenant Management

Tenant Information Maintenance

Provide CRUD operations for tenant metadata.

CREATE TABLE tenant (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL UNIQUE,
    description VARCHAR(255),
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

Tenant Permission Control

Enforce access control so tenants cannot access each other's data.

@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/api/tenant/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
            .passwordEncoder(new BCryptPasswordEncoder())
            .and()
            .inMemoryAuthentication()
            .withUser("admin")
            .password(new BCryptPasswordEncoder().encode("123456"))
            .roles("ADMIN");
    }
}

Technical Implementation

1. Multi‑Tenant in Spring Boot

1.1 Multiple DataSources

Configure a separate DataSource for each tenant.

@Configuration
public class DataSourceConfig {
    @Bean(name = "dataSourceA")
    @ConfigurationProperties(prefix = "spring.datasource.a")
    public DataSource dataSourceA() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSourceB")
    @ConfigurationProperties(prefix = "spring.datasource.b")
    public DataSource dataSourceB() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSourceC")
    @ConfigurationProperties(prefix = "spring.datasource.c")
    public DataSource dataSourceC() {
        return DataSourceBuilder.create().build();
    }
}

Inject the required DataSource using @Qualifier :

@Service
public class ProductService {
    @Autowired
    @Qualifier("dataSourceA")
    private DataSource dataSource;
    // ...
}

1.2 Dynamic Routing

Switch DataSources at runtime based on the tenant identifier.

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return TenantContextHolder.getTenantId();
    }
}

@Configuration
public class DataSourceConfig {
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().type(DynamicDataSource.class).build();
    }
}

2. Multi‑Tenant in Spring Cloud

Leverage service registration, configuration center, and load balancing to isolate tenants.

Use Eureka for service discovery; register each tenant's services under distinct names.

Store tenant‑specific configuration in Spring Cloud Config.

Employ Ribbon for tenant‑aware load balancing.

Implement tenant routing at the API gateway level.

Application Scenarios

Private Cloud

Deploy within an enterprise‑controlled environment for higher data security and control.

Public Cloud

Benefit from lower costs, elastic scaling, and global deployment.

Enterprise‑Level SaaS

Support ERP, CRM, OA, and other large‑scale applications requiring high reliability and security.

Implementation Steps

1. Set Up Spring Boot & Spring Cloud

Add Maven dependencies for Spring Boot and Spring Cloud.

org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-dependencies
2020.0.3
pom
import

Configure properties in application.yml (datasource URL, credentials, Eureka server, etc.).

2. Modify Database Schema

Add a tenant identifier column to relevant tables or create separate databases per tenant.

3. Implement Multi‑Tenant Deployment

Instantiate tenant‑specific beans and route requests based on tenant ID.

@Configuration
public class MultiTenantConfig {

    // Provide tenant‑aware DataSource
    @Bean
    public DataSource dataSource(TenantRegistry tenantRegistry) {
        return new TenantAwareDataSource(tenantRegistry);
    }

    // Multi‑tenant SqlSessionFactory
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        return sessionFactory.getObject();
    }

    // Interceptor for tenant switching
    @Bean
    public MultiTenantInterceptor multiTenantInterceptor(TenantResolver tenantResolver) {
        MultiTenantInterceptor interceptor = new MultiTenantInterceptor();
        interceptor.setTenantResolver(tenantResolver);
        return interceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(multiTenantInterceptor());
    }

    @Bean
    public TenantRegistry tenantRegistry() {
        return new TenantRegistryImpl();
    }

    @Bean
    public TenantResolver tenantResolver() {
        return new HeaderTenantResolver();
    }
}

4. Tenant Management

Use Eureka to register each tenant's service instances and provide isolated databases for data separation.

Conclusion

The article detailed how to build a multi‑tenant application with Spring Boot and Spring Cloud, covering environment setup, database design, deployment, and management. Such architecture improves scalability and maintainability for SaaS solutions, though it adds operational complexity that can be mitigated with further automation.

backendMicroservicesSpring Bootmulti-tenantSpring CloudDatabase Isolation
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.