Multi Tenant Databases


This is a farily age-old problem faced by most Spring-Boot applications. The default functionality associated with the spring-boot-starter-jdbc and associated RDBMS related spring-data modules auto configures a single datasource.

The Spring Framework provides the AbstractRoutingDataSource which allows configuration of one or more javax.sql.DataSourceinstances that are keyed on an identifier. The implementation of the method AbstractRoutingDataSource.determineCurrentLookupKey() will provide a result of the key to retrieve the tentant DataSourceinstance.

To provide a consistent schema, and upgrade path as the application evolves, the package Flyway can be used to consistently apply database migrations and track the changes within the database.

Exemplar implementations

This article Multitenancy Applications with Spring Boot and Flyway provides a rock solid foundation. There are, however, a few discrepancies in the article itself that make the described implementation unworkable. However, the provided GitHub repository has a proper implementation that does work.

What the exemplar implementation provides are the following:

  • A method for configuring multiple datasources
  • A method for applying Flyway migrations on each datasource
  • A method for resolving the tenant database to use based on HTTP header associated with the request

Thoughts on Migration Application

In a production environment, assuming this is a containerized application, it would be ideal to provide rolling updates to the application.

Adding a new Tenant

To add a new tentant, the database to contain the tenant would need to be established by an administrator. Subsequently, the configuration for the application would then be updated with the appropriate connection string and credentials, then the application containers could be restarted in a rolling fashion.

Security Considerations

The exemplar article assumes credentials of the database connection have permission to modify the database schema. In a production environment, this would not be recommended.

With this in mind, the code base could be extended to run the application in a fashion that would allow the database to be accessed and allow for Flyway to apply migrations but not remain resident. Then the application can be started normally utilizing a RW connection for data but not schema modification. A method of achieving this would be utilizing Spring Bean Definition Profiles.

Deployed in a framework like Kubernetes, an InitContainer could be declared that would run the application, as described above, in a mode where it will apply the Flyway migrations, then the regular operating application would be declared as a Container of the deployment. The semantics of a Kubernetes Deployment require that all declared InitContainer elements run to completion before any Container instances are started.

Configuration data could be externalized via a ConfigMap providing a much broader mechanism of providing configuration to the application.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store