{"id":34017056,"url":"https://github.com/mathias82/quarkus-multitenancy","last_synced_at":"2026-04-19T00:02:01.719Z","repository":{"id":326149550,"uuid":"1104202990","full_name":"mathias82/quarkus-multitenancy","owner":"mathias82","description":"Lightweight Quarkus extension that resolves the current tenant per request using configurable strategies (headers, JWT claims, cookies, or paths) and exposes it through a request-scoped TenantContext. Designed for REST microservices that need multi-tenant tenant awareness without OIDC or multiple datasources.","archived":false,"fork":false,"pushed_at":"2025-12-06T22:56:03.000Z","size":56,"stargazers_count":3,"open_issues_count":4,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-12-10T01:23:14.530Z","etag":null,"topics":["cloud","extension","java","microservices","multi-tenancy","quarkus","saas","tenant-resolution"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mathias82.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-25T22:34:07.000Z","updated_at":"2025-12-06T22:57:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mathias82/quarkus-multitenancy","commit_stats":null,"previous_names":["mathias82/quarkus-multitenancy-helper","mathias82/quarkus-multitenancy"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/mathias82/quarkus-multitenancy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathias82%2Fquarkus-multitenancy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathias82%2Fquarkus-multitenancy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathias82%2Fquarkus-multitenancy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathias82%2Fquarkus-multitenancy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mathias82","download_url":"https://codeload.github.com/mathias82/quarkus-multitenancy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathias82%2Fquarkus-multitenancy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27706936,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-13T02:00:09.769Z","response_time":147,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloud","extension","java","microservices","multi-tenancy","quarkus","saas","tenant-resolution"],"created_at":"2025-12-13T14:23:37.946Z","updated_at":"2026-04-19T00:02:01.474Z","avatar_url":"https://github.com/mathias82.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🧩 Quarkus Multi-Tenancy Extension\r\n\r\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.mathias82/quarkus-multitenancy-core-runtime.svg)](https://central.sonatype.com/artifact/io.github.mathias82/quarkus-multitenancy-core-runtime)\r\n[![Website](https://img.shields.io/badge/Website-GitHub%20Pages-black)](https://mathias82.github.io/quarkus-multitenancy/)\r\n[![Build](https://github.com/mathias82/quarkus-multitenancy/actions/workflows/build.yml/badge.svg)](https://github.com/mathias82/quarkus-multitenancy/actions/workflows/build.yml)\r\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\r\n![Java](https://img.shields.io/badge/Java-17%2B-blue)\r\n![Quarkus](https://img.shields.io/badge/Quarkus-3.x-red)\r\n![Status](https://img.shields.io/badge/status-stable-brightgreen)\r\n\r\n\u003e A modular, decoupled multi-tenancy framework for Quarkus \r\n\u003e supporting HTTP, ORM, and future extensions.\r\n\r\n\r\nQuarkus Multi-Tenancy provides a generic tenant resolution API and reusable building blocks that can be integrated with HTTP (headers, cookies, JWT), Hibernate ORM, and custom extensions.\r\nIt abstracts tenant identification logic away from any specific technology\r\nand exposes a consistent TenantContext you can inject anywhere.\r\n\r\nWhy this exists\r\n- No standard tenant resolution abstraction exists in Quarkus.\r\n- This library defines a generic runtime API usable across REST, ORM, OIDC, or messaging.\r\n- It can evolve into a Quarkiverse extension.\r\n\r\n---\r\n\r\n💡 Designed for REST microservices or backend modules\r\nit can run independently of HTTP, allowing tenant resolution in database, cache, or messaging layers.\r\n\r\n\r\n## 📌 About This Project\r\n\r\n**Quarkus Multi-Tenancy** is an extension designed to standardize and simplify tenant resolution for Quarkus services, provides a decoupled multi-layer architecture.\r\n\r\n- A core runtime module that defines TenantResolver, TenantContext, and composition logic.\r\n- Independent HTTP, database, and deployment layers built on top of the core.\r\n\r\nThis makes the extension modular, lightweight, and framework-agnostic,\r\nso you can plug tenant resolution into HTTP requests, JPA datasources, or background jobs seamlessly.\r\n\r\n- Consistent tenant identification per request\r\n- Pluggable resolvers (header now, JWT/cookie/path soon)\r\n- Minimal boilerplate code\r\n- Future integration with datasources, caches, identity providers\r\n- Published on **Maven Central**\r\n\r\nNext step: *Quarkiverse compatibility* ✔️\r\n\r\n---\r\n\r\n## 📚 Modules\r\n\r\n| Module | Description | Docs |\r\n|--------|--------------|------|\r\n| 🧠 **Core Runtime** | Defines `TenantContext`, `TenantResolver` | [Read more →](quarkus-multitenancy-core-runtime/README.md) |\r\n| ⚙️ **Core Deployment** | Build-time Quarkus integration for core | [Read more →](quarkus-multitenancy-core-deployment/README.md) |\r\n| 🌐 **HTTP Runtime** | Resolves tenants from header/JWT/cookie | [Read more →](quarkus-multitenancy-http-runtime/README.md) |\r\n| 🧩 **HTTP Deployment** | Registers HTTP resolvers | [Read more →](quarkus-multitenancy-http-deployment/README.md) |\r\n| 🧱 **ORM Runtime** | Integrates Hibernate ORM multi-tenancy | [Read more →](quarkus-multitenancy-orm-runtime/README.md) |\r\n| ⚙️ **ORM Deployment** | Quarkus feature registration for ORM | [Read more →](quarkus-multitenancy-orm-deployment/README.md) |\r\n| 🧪 **Demo App** | PostgreSQL multi-tenant REST demo | [Read more →](quarkus-multitenancy-demo/README.md) |\r\n\r\n---\r\n\r\n# 🧠 Quarkus Multi-Tenancy Core Runtime\r\n\r\nThe **core foundation** of the Quarkus Multi-Tenancy extension.  \r\nIt defines the base APIs used to resolve and isolate tenants across layers \r\nfrom HTTP requests to ORM and background jobs.\r\n\r\n---\r\n\r\n## 🚀 What It Does\r\n\r\nThis module provides:\r\n- The **`TenantContext`** – a request-scoped CDI bean storing the active tenant.\r\n- The **`TenantResolver`** – an interface for resolving tenant IDs dynamically.\r\n- The **`CompositeTenantResolver`** – allows multiple resolvers (header, JWT, cookie) to cooperate.\r\n\r\n---\r\n\r\n## 🧩 Multi-Tenant Isolation Achieved\r\n\r\nUsing this module (along with the HTTP and ORM runtimes),  \r\neach incoming request is **isolated per tenant**, both logically and physically:\r\n\r\n✅ Each request carries a tenant identifier (e.g., `X-Tenant: tenant1`).  \r\n✅ The active tenant is injected into `TenantContext`.  \r\n✅ The ORM runtime automatically routes persistence operations to the correct datasource.  \r\n✅ This ensures **complete data isolation** — each tenant’s data lives in its own database.\r\n\r\nFor example:\r\n\r\n| Request | Header | Database Used |\r\n|----------|---------|---------------|\r\n| `GET /api/users` | `X-Tenant: tenant1` | `tenant1` PostgreSQL DB |\r\n| `GET /api/users` | `X-Tenant: tenant2` | `tenant2` PostgreSQL DB |\r\n\r\nThis means:  \r\n→ Users from tenant1 will **never see or modify** data from tenant2.  \r\n→ The system scales horizontally with full **per-tenant isolation**.  \r\n\r\n---\r\n\r\n## ⚙️ Required Dependencies\r\n\r\nThese two modules together provide:\r\n- Tenant resolution from HTTP requests\r\n- Runtime context propagation\r\n- ORM-level datasource routing per tenant\r\n- \r\nTo enable full multi-tenant operation, your application should include:\r\n\r\n```xml\r\n\u003cdependencies\u003e\r\n    \u003c!-- HTTP Runtime (for header/jwt/cookie resolution) --\u003e\r\n    \u003cdependency\u003e\r\n        \u003cgroupId\u003eio.github.mathias82\u003c/groupId\u003e\r\n        \u003cartifactId\u003equarkus-multitenancy-http-runtime\u003c/artifactId\u003e\r\n        \u003cversion\u003e0.1.15\u003c/version\u003e\r\n    \u003c/dependency\u003e\r\n\r\n    \u003c!-- ORM Runtime (for Hibernate datasource switching) --\u003e\r\n    \u003cdependency\u003e\r\n        \u003cgroupId\u003eio.github.mathias82\u003c/groupId\u003e\r\n        \u003cartifactId\u003equarkus-multitenancy-orm-runtime\u003c/artifactId\u003e\r\n        \u003cversion\u003e0.1.15\u003c/version\u003e\r\n    \u003c/dependency\u003e\r\n\u003c/dependencies\u003e\r\n```\r\n---\r\n## 💡 Example Usage\r\n\r\n```java\r\nimport io.github.mathias82.quarkus.multitenancy.core.runtime.context.TenantContext;\r\nimport jakarta.inject.Inject;\r\nimport jakarta.ws.rs.GET;\r\nimport jakarta.ws.rs.Path;\r\n\r\n@Path(\"/tenant\")\r\npublic class TenantResource {\r\n\r\n    @Inject\r\n    TenantContext tenantContext;\r\n\r\n    @GET\r\n    public String getTenant() {\r\n        return tenantContext.getTenantId().orElse(\"NO TENANT FOUND\");\r\n    }\r\n}\r\n```\r\n\r\nWhen you send:\r\ncurl -H \"X-Tenant: tenant1\" http://localhost:8080/tenant\r\n\r\nOutput: tenant1\r\n\r\nAnd Hibernate ORM automatically connects to the datasource configured for tenant1.\r\n\r\n| Layer            | Module                              | Responsibility                       |\r\n| ---------------- | ----------------------------------- | ------------------------------------ |\r\n| **HTTP Runtime** | `quarkus-multitenancy-http-runtime` | Resolves tenant per HTTP request     |\r\n| **ORM Runtime**  | `quarkus-multitenancy-orm-runtime`  | Connects ORM layer to tenant context |\r\n\r\nTogether, they achieve full tenant-based isolation in Quarkus.\r\n\r\n---\r\n\r\n## 🚀 Quick Start\r\n\r\n```bash\r\nmvn clean install\r\ncd quarkus-multitenancy-demo\r\nmvn quarkus:dev\r\n```\r\n\r\nIn order to test it import the demo.postman_collection.json into Postman Curl\r\n\r\n---\r\n\r\n## 🧭 Architecture Overview\r\n\r\n```\r\n[HTTP Request]\r\n     ↓\r\n[HTTP TenantResolver] (header/JWT/cookie)\r\n     ↓\r\n[TenantContext] (request-scoped)\r\n     ↓\r\n[ORM Resolver] → selects datasource (tenant1, tenant2)\r\n```\r\n\r\n👉 See the quarkus-multitenancy-demo README.md\r\n for full setup (Docker, Postman, tenants).\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathias82%2Fquarkus-multitenancy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathias82%2Fquarkus-multitenancy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathias82%2Fquarkus-multitenancy/lists"}