Build a Schema-Based Multi-Tenant Spring Boot Application with PostgreSQL & JWT
In today's SaaS-driven world, multi-tenancy is a key architectural pattern that enables multiple customers (tenants) to share a single application while keeping their data isolated. In this guide, we’ll explore how to implement schema-based multi-tenancy in Spring Boot using PostgreSQL and JWT authentication.
🔍 What is Multi-Tenancy?
Multi-tenancy allows a single application to serve multiple customers (tenants), with each tenant’s data stored separately. Common approaches include:
- Database-per-tenant
- Schema-per-tenant ✅ (used in this project)
- Table-per-tenant
We use schema-based multi-tenancy, meaning each tenant gets a dedicated schema in the same database — balancing efficiency and data isolation.
⚙️ Key Features
- ✅ Schema-based tenant isolation in PostgreSQL
- 🔐 JWT authentication & authorization
- 🔄 RESTful APIs with clean endpoints
- 💡 Dynamic tenant schema provisioning
- 🛑 Centralized error handling with structured responses
🚀 Technologies Used
- Spring Boot (Java 17+)
- PostgreSQL (12+)
- JWT for secure login
- Maven/Gradle for build management
📦 Setup Guide
✅ Prerequisites
- Java 17+
- PostgreSQL installed
- Maven or Gradle
🛠️ Database Configuration
CREATE DATABASE user_db;
Update application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/user_db
spring.datasource.username=postgres
spring.datasource.password=postgres
🔐 JWT Configuration
security.jwt.secret-key=your-secret-key
security.jwt.expiration-time=9000000
▶️ Running the Application
With Maven:
mvn clean install
mvn spring-boot:run
With Gradle:
./gradlew clean build
./gradlew bootRun
📬 Using the REST API
🔐 Authentication
1. Register User
POST /api/v1/auth/signup
Headers: X-Tenant-ID
Body:
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"role": "USER"
}
2. Login
POST /api/v1/auth/login
{
"email": "john@example.com",
"password": "password123"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiJ9..."
}
🏢 Tenant Management
Create Tenant
POST /api/tenants
Headers: Authorization: Bearer <token>
{
"tenantId": "tenant1"
}
✅ Automatically creates a schema for the tenant.
💬 Message Management
Get Messages by Thread
GET /api/messages/thread/{threadId}
Headers: JWT + X-Tenant-ID
❌ Error Handling
{
"status": 401,
"error": "Unauthorized",
"message": "Invalid credentials",
"timestamp": "2023-06-15T10:15:30Z"
}
Other errors: 400, 403, 404, 500.
💡 Why Schema-Based Multi-Tenancy?
- 🧩 Data Isolation: tenants cannot access each other’s data
- ⚡ Performance: shared resources with logical separation
- 📈 Scalability: easy onboarding by adding a schema
🧪 Use Cases
- SaaS platforms managing multiple clients
- CRM systems with organizational hierarchies
- B2B platforms with workspace segregation