---
name: Multi-Tenancy
slug: multi-tenancy
category: DevOps
description: Multi-Tenancy covers tenant resolution, database or schema isolation, tenant-aware JPA, reactive tenant context, and tenant-safe jobs and caching in Spring Boot 3. Use it when building or reviewing tenant-bound application flows.
github: "https://github.com/rrezartprebreza/spring-boot-skills/tree/main/skills/spring-boot-3/multi-tenancy"
language: Java
stars: 247
forks: 39
install: "npx degit https://github.com/rrezartprebreza/spring-boot-skills/tree/main/skills/spring-boot-3/multi-tenancy ~/.claude/skills/multi-tenancy"
installs_to: ~/.claude/skills/multi-tenancy
source_path: skills/spring-boot-3/multi-tenancy/SKILL.md
collection_size: 24
category_size: 828
collection_url: "https://dirskills.com/collections/rrezartprebreza/spring-boot-skills"
added: 2026-09-02T05:21:22.826Z
last_synced: 2026-09-02T05:21:22.826Z
canonical_url: "https://dirskills.com/skills/multi-tenancy"
---

# Multi-Tenancy

Multi-Tenancy covers tenant resolution, database or schema isolation, tenant-aware JPA, reactive tenant context, and tenant-safe jobs and caching in Spring Boot 3. Use it when building or reviewing tenant-bound application flows.

**Install:**

```bash
npx degit https://github.com/rrezartprebreza/spring-boot-skills/tree/main/skills/spring-boot-3/multi-tenancy ~/.claude/skills/multi-tenancy
```

## README

# Multi-Tenancy

Treat tenant identity as an authorization boundary, not a query convenience.

## Choose an isolation model

- Database per tenant: strongest isolation and highest operational cost.
- Schema per tenant: strong logical isolation with shared infrastructure.
- Shared schema with `tenant_id`: simplest operations, but every access path must enforce scope.
- Document the selected model and prohibit repositories from bypassing it.

## Resolve tenant identity

- Derive the tenant from a verified token claim, trusted host mapping, or authenticated API key.
- Reject missing, unknown, disabled, or conflicting tenant identifiers.
- Never trust a public `X-Tenant-Id` header by itself.
- Clear servlet thread-local context in `finally`; use Reactor `Context` for reactive flows.

## Enforce isolation

- Apply tenant selection before opening the persistence session or transaction.
- Include tenant identity in unique constraints, cache keys, idempotency keys, and object storage paths.
- Prevent cross-tenant joins and unrestricted administrative repositories.
- Authorize support impersonation explicitly and audit every use.

## Operations

- Run migrations per database/schema with resumable progress and version reporting.
- Propagate tenant identity into scheduled jobs, messages, and async tasks explicitly.
- Limit noisy tenants with quotas and per-tenant observability using bounded identifiers.
- Test negative cross-tenant access, not only successful tenant queries.

## Examples

- See `examples/good-tenant-filter.java` and `examples/bad-tenant-filter.java`.

## Gotchas

- Agent trusts a tenant header supplied by the caller - derive tenant from authenticated context.
- Agent forgets to clear a servlet `ThreadLocal` - pooled threads can leak one tenant into another request.
- Agent scopes database queries but not cache keys - cached data can cross tenants.
- Agent starts a transaction before selecting the tenant - routing may choose the wrong database.
- Agent runs background jobs without tenant context - make tenant an explicit job parameter.
