<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Matthaios Stavrou</title>
    <description>The latest articles on Forem by Matthaios Stavrou (@mathias82).</description>
    <link>https://forem.com/mathias82</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3686077%2Fb42023c8-c84f-436f-9066-8ac535e873d8.jpeg</url>
      <title>Forem: Matthaios Stavrou</title>
      <link>https://forem.com/mathias82</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mathias82"/>
    <language>en</language>
    <item>
      <title>Building a Kafka Event-Driven Spring Boot Application with Avro, Schema Registry and PostgreSQL</title>
      <dc:creator>Matthaios Stavrou</dc:creator>
      <pubDate>Sun, 04 Jan 2026 21:28:07 +0000</pubDate>
      <link>https://forem.com/mathias82/building-a-kafka-event-driven-spring-boot-application-with-avro-schema-registry-and-postgresql-3i0</link>
      <guid>https://forem.com/mathias82/building-a-kafka-event-driven-spring-boot-application-with-avro-schema-registry-and-postgresql-3i0</guid>
      <description>&lt;p&gt;If you’re building event-driven systems with Apache Kafka, you must think about data contracts early.&lt;/p&gt;

&lt;p&gt;This post shows a practical, end-to-end Spring Boot example using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apache Kafka&lt;/li&gt;
&lt;li&gt;Confluent Schema Registry&lt;/li&gt;
&lt;li&gt;Avro serialization&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Full source code:&lt;br&gt;
🔗 &lt;a href="https://github.com/mathias82/kafka-schema-registry-spring-demo" rel="noopener noreferrer"&gt;https://github.com/mathias82/kafka-schema-registry-spring-demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧠 Why Schema Registry + Avro?&lt;/p&gt;

&lt;p&gt;JSON works… until it doesn’t.&lt;/p&gt;

&lt;p&gt;Common problems in Kafka-based systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;breaking consumers when producers change payloads&lt;/li&gt;
&lt;li&gt;no schema versioning&lt;/li&gt;
&lt;li&gt;unclear data contracts between teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avro + Schema Registry solves this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enforcing schema compatibility&lt;/li&gt;
&lt;li&gt;allowing safe schema evolution&lt;/li&gt;
&lt;li&gt;decoupling producers from consumers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This demo shows how to do it the right way with Spring Boot.&lt;/p&gt;

&lt;p&gt;🏗️ Architecture Overview&lt;br&gt;
Client (Postman)&lt;br&gt;
      |&lt;br&gt;
      v&lt;br&gt;
Spring Boot Producer (REST)&lt;br&gt;
      |&lt;br&gt;
      v&lt;br&gt;
Kafka Topic (users.v1)&lt;br&gt;
      |&lt;br&gt;
      v&lt;br&gt;
Spring Boot Consumer&lt;br&gt;
      |&lt;br&gt;
      v&lt;br&gt;
PostgreSQL&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Producer exposes POST /users&lt;/li&gt;
&lt;li&gt;Payload is converted to an Avro record&lt;/li&gt;
&lt;li&gt;Message is published to Kafka&lt;/li&gt;
&lt;li&gt;Consumer deserializes Avro and persists data to PostgreSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✨ What This Demo Includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spring Boot Kafka Producer (Avro)&lt;/li&gt;
&lt;li&gt;Spring Boot Kafka Consumer (Avro)&lt;/li&gt;
&lt;li&gt;Confluent Schema Registry&lt;/li&gt;
&lt;li&gt;PostgreSQL persistence using Spring Data JPA&lt;/li&gt;
&lt;li&gt;Schema evolution with backward compatibility&lt;/li&gt;
&lt;li&gt;Docker Compose for local development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🐳 Local Setup (Kafka + Schema Registry + PostgreSQL)&lt;br&gt;
Prerequisites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21&lt;/li&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Docker &amp;amp; Docker Compose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start infrastructure&lt;/p&gt;

&lt;p&gt;docker compose up -d&lt;/p&gt;

&lt;p&gt;Services started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka → localhost:29092&lt;/li&gt;
&lt;li&gt;Schema Registry → &lt;a href="http://localhost:8081" rel="noopener noreferrer"&gt;http://localhost:8081&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PostgreSQL → localhost:5432&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;▶️ Run the Applications&lt;br&gt;
Consumer&lt;br&gt;
cd consumer-app&lt;br&gt;
mvn spring-boot:run&lt;/p&gt;

&lt;p&gt;Listens to users.v1 and persists messages to PostgreSQL.&lt;/p&gt;

&lt;p&gt;Producer&lt;br&gt;
cd producer-app&lt;br&gt;
mvn spring-boot:run&lt;/p&gt;

&lt;p&gt;Exposes REST endpoint.&lt;/p&gt;

&lt;p&gt;📬 Produce an Event&lt;br&gt;
curl -X POST &lt;a href="http://localhost:8080/users" rel="noopener noreferrer"&gt;http://localhost:8080/users&lt;/a&gt; \&lt;br&gt;
  -H "Content-Type: application/json" \&lt;br&gt;
  -d '{&lt;br&gt;
    "id": "u-1",&lt;br&gt;
    "email": "&lt;a href="mailto:user@test.com"&gt;user@test.com&lt;/a&gt;",&lt;br&gt;
    "firstName": "John",&lt;br&gt;
    "lastName": "Doe",&lt;br&gt;
    "isActive": true,&lt;br&gt;
    "age": 30&lt;br&gt;
  }'&lt;/p&gt;

&lt;p&gt;You’ll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avro schema registered (or validated)&lt;/li&gt;
&lt;li&gt;Message published to Kafka&lt;/li&gt;
&lt;li&gt;Consumer saving the record to PostgreSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔄 Schema Evolution (The Important Part)&lt;/p&gt;

&lt;p&gt;Avro allows safe evolution when rules are respected.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a new optional field&lt;/li&gt;
&lt;li&gt;Provide a default value&lt;/li&gt;
&lt;li&gt;Keep compatibility set to BACKWARD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Schema Registry ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;old consumers keep working&lt;/li&gt;
&lt;li&gt;new producers don’t break the system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This demo is designed to show real-world schema evolution, not toy examples.&lt;/p&gt;

&lt;p&gt;☁️ Confluent Cloud Ready&lt;/p&gt;

&lt;p&gt;The project also supports Confluent Cloud via Spring profiles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SASL/SSL&lt;/li&gt;
&lt;li&gt;Schema Registry API keys&lt;/li&gt;
&lt;li&gt;use.latest.version=true&lt;/li&gt;
&lt;li&gt;auto.register.schemas=false&lt;/li&gt;
&lt;li&gt;Perfect for CI/CD pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 Source Code&lt;/p&gt;

&lt;p&gt;👉 GitHub repository:&lt;br&gt;
&lt;a href="https://github.com/mathias82/kafka-schema-registry-spring-demo" rel="noopener noreferrer"&gt;https://github.com/mathias82/kafka-schema-registry-spring-demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;Avro schemas&lt;/li&gt;
&lt;li&gt;Producer &amp;amp; Consumer apps&lt;/li&gt;
&lt;li&gt;PostgreSQL setup&lt;/li&gt;
&lt;li&gt;Postman collection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧩 Who Is This For?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java &amp;amp; Spring Boot developers&lt;/li&gt;
&lt;li&gt;Kafka users moving beyond JSON&lt;/li&gt;
&lt;li&gt;Teams building event-driven microservices&lt;/li&gt;
&lt;li&gt;Anyone learning Schema Registry + Avro&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⭐ Final Thoughts&lt;/p&gt;

&lt;p&gt;This is a production-style Kafka example, not a hello-world.&lt;/p&gt;

&lt;p&gt;If you’re serious about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schema contracts&lt;/li&gt;
&lt;li&gt;backward compatibility&lt;/li&gt;
&lt;li&gt;safe evolution&lt;/li&gt;
&lt;li&gt;real persistence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then this demo will save you a lot of trial and error.&lt;/p&gt;

&lt;p&gt;👉 Star the repo if it helped you&lt;br&gt;
👉 Fork it and adapt it to your own system&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>confluent</category>
      <category>avro</category>
      <category>springboot</category>
    </item>
    <item>
      <title>🚦 How to Fail Fast on Kafka Schema Registry in Spring Boot (Avoid Production Breaks)</title>
      <dc:creator>Matthaios Stavrou</dc:creator>
      <pubDate>Sat, 03 Jan 2026 12:33:10 +0000</pubDate>
      <link>https://forem.com/mathias82/how-to-fail-fast-on-kafka-schema-registry-in-spring-boot-avoid-production-breaks-4loc</link>
      <guid>https://forem.com/mathias82/how-to-fail-fast-on-kafka-schema-registry-in-spring-boot-avoid-production-breaks-4loc</guid>
      <description>&lt;p&gt;If you are using Kafka Schema Registry with Spring Boot and want to avoid runtime failures in production, this guide shows how to implement fail-fast schema validation the right way.&lt;br&gt;
Apache Kafka is the backbone of many modern event-driven architectures. When combined with Spring Boot, it enables scalable, decoupled microservices that communicate through events instead of tight REST dependencies.&lt;/p&gt;

&lt;p&gt;However, as Kafka systems grow, one problem appears again and again:&lt;/p&gt;

&lt;h2&gt;
  
  
  Schema incompatibility reaching production.
&lt;/h2&gt;

&lt;p&gt;A single incompatible change in an Avro or Protobuf schema can silently break consumers, cause deserialization failures, or — even worse — lead to corrupted data flows that are detected days later.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore why Kafka Schema Registry validation must fail fast, how Spring Boot applications often get this wrong, and how to catch schema contract issues before production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Kafka Schema Issues Are So Dangerous
&lt;/h2&gt;

&lt;p&gt;Kafka is schema-agnostic by default. This flexibility is powerful — but also dangerous.&lt;/p&gt;

&lt;p&gt;Common real-world problems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Producers sending incompatible schemas&lt;/li&gt;
&lt;li&gt;Consumers crashing due to deserialization errors&lt;/li&gt;
&lt;li&gt;Schema Registry compatibility set correctly, but violations detected only at runtime&lt;/li&gt;
&lt;li&gt;CI/CD pipelines that deploy code without validating schema contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the time the issue is detected, production data is already affected.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Myth: “Schema Registry Will Protect Me”
&lt;/h2&gt;

&lt;p&gt;Many teams believe that using Confluent Schema Registry automatically guarantees safety.&lt;/p&gt;

&lt;p&gt;Reality check ❌&lt;br&gt;
Schema Registry enforces compatibility only when schemas are registered — not when your Spring Boot application starts.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;p&gt;Your app can deploy successfully&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka topics can exist&lt;/li&gt;
&lt;li&gt;CI pipelines pass&lt;/li&gt;
&lt;li&gt;And yet… the first produced message fails at runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the opposite of what we want.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fail-Fast Principle for Kafka Schema Contracts
&lt;/h2&gt;

&lt;p&gt;A fail-fast Kafka application must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate schema compatibility on startup&lt;/li&gt;
&lt;li&gt;Fail immediately if schema registration is rejected&lt;/li&gt;
&lt;li&gt;Block deployment before traffic reaches production&lt;/li&gt;
&lt;li&gt;Shift schema validation left into CI/CD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Spring Boot makes this possible — but not out of the box.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Common Anti-Patterns in Spring Boot Kafka&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
Here are patterns that look fine but hide serious risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relying on auto-registration without validation&lt;/li&gt;
&lt;li&gt;Allowing producers to lazily register schemas&lt;/li&gt;
&lt;li&gt;Catching and ignoring serialization exceptions&lt;/li&gt;
&lt;li&gt;Letting consumers discover incompatibility at runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These patterns lead to late failures, operational firefighting, and broken SLAs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Correct Approach: Validate Schemas at Startup
&lt;/h2&gt;

&lt;p&gt;The right solution is simple in concept:&lt;/p&gt;

&lt;p&gt;If schema registration fails, the application must not start.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicit schema registration&lt;/li&gt;
&lt;li&gt;Compatibility checks during application bootstrap&lt;/li&gt;
&lt;li&gt;No lazy runtime surprises&lt;/li&gt;
&lt;li&gt;Full alignment with DevOps and CI/CD best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When implemented correctly, your Spring Boot Kafka service becomes self-defensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters in Real Production Systems
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In real enterprise environments:&lt;/li&gt;
&lt;li&gt;Multiple teams evolve schemas independently&lt;/li&gt;
&lt;li&gt;Kafka topics are shared across domains&lt;/li&gt;
&lt;li&gt;Rolling deployments happen continuously&lt;/li&gt;
&lt;li&gt;Backward compatibility mistakes are inevitable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fail-fast schema validation turns these risks into early, actionable errors instead of production incidents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive: Practical Implementation
&lt;/h2&gt;

&lt;p&gt;The full technical breakdown — including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spring Boot startup hooks&lt;/li&gt;
&lt;li&gt;Schema Registry compatibility validation&lt;/li&gt;
&lt;li&gt;Producer configuration pitfalls&lt;/li&gt;
&lt;li&gt;CI/CD integration patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;is covered step-by-step in the following article 👇&lt;/p&gt;

&lt;p&gt;👉 Read the full implementation guide on Medium:&lt;br&gt;
Fail-Fast Kafka Schema Contracts in Spring Boot — Before Production Breaks&lt;br&gt;
&lt;a href="https://medium.com/@mstauroy/fail-fast-kafka-schema-contracts-in-spring-boot-before-production-breaks-1b080204b49e" rel="noopener noreferrer"&gt;https://medium.com/@mstauroy/fail-fast-kafka-schema-contracts-in-spring-boot-before-production-breaks-1b080204b49e&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;Does Kafka Schema Registry validate schemas at application startup?&lt;br&gt;
No. By default, schema compatibility is checked only when schemas are registered at runtime, which can lead to late production failures.&lt;/p&gt;

&lt;p&gt;How do you fail fast with Kafka Schema Registry in Spring Boot?&lt;br&gt;
By validating schema registration and compatibility during application startup and failing the application if registration is rejected.&lt;/p&gt;

&lt;p&gt;Why do Kafka schema incompatibility issues reach production?&lt;br&gt;
Because most Spring Boot applications rely on lazy schema registration and do not enforce compatibility checks during deployment.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;Kafka is reliable. Schema Registry is powerful.&lt;br&gt;
But without fail-fast validation, your system is still fragile.&lt;/p&gt;

&lt;p&gt;If you are serious about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Production safety&lt;/li&gt;
&lt;li&gt;Contract-driven development&lt;/li&gt;
&lt;li&gt;Kafka best practices&lt;/li&gt;
&lt;li&gt;Spring Boot reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then schema validation must happen before your app ever starts.&lt;/p&gt;

&lt;p&gt;Fail fast and sleep better.&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>schemaregistry</category>
      <category>springboot</category>
      <category>eventdriven</category>
    </item>
    <item>
      <title>Quarkus Multitenant Plugin (Java): Tenant Resolution in 5 Minutes (Header/JWT/Cookie)</title>
      <dc:creator>Matthaios Stavrou</dc:creator>
      <pubDate>Tue, 30 Dec 2025 12:57:36 +0000</pubDate>
      <link>https://forem.com/mathias82/building-a-generic-multitenancy-extension-for-quarkus-from-idea-to-maven-central-3a9b</link>
      <guid>https://forem.com/mathias82/building-a-generic-multitenancy-extension-for-quarkus-from-idea-to-maven-central-3a9b</guid>
      <description>&lt;p&gt;If you build multi-tenant Quarkus services, you’ve probably repeated the same logic in multiple codebases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read &lt;code&gt;tenantId&lt;/code&gt; from a &lt;strong&gt;header&lt;/strong&gt; (API gateways / service-to-service)&lt;/li&gt;
&lt;li&gt;or from a &lt;strong&gt;JWT claim&lt;/strong&gt; (auth-centric flows)&lt;/li&gt;
&lt;li&gt;or from a &lt;strong&gt;cookie&lt;/strong&gt; (browser apps)&lt;/li&gt;
&lt;li&gt;and then wire it into your persistence strategy (Hibernate ORM multitenancy, datasource routing, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built a small &lt;strong&gt;Quarkus multitenant plugin/extension&lt;/strong&gt; that standardizes &lt;em&gt;tenant resolution&lt;/em&gt; so every service follows the same contract and you don’t keep re-implementing edge cases.&lt;/p&gt;

&lt;p&gt;👉 Full deep-dive (architecture + implementation + publishing to Maven Central):&lt;br&gt;&lt;br&gt;
&lt;a href="https://medium.com/@mstauroy/building-a-generic-multitenancy-extension-for-quarkus-from-idea-to-maven-central-7c4045c404a3" rel="noopener noreferrer"&gt;https://medium.com/@mstauroy/building-a-generic-multitenancy-extension-for-quarkus-from-idea-to-maven-central-7c4045c404a3&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What this extension solves (in plain terms)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tenant resolution&lt;/strong&gt; is the missing “glue” between the HTTP request and whatever tenant isolation strategy you use downstream.&lt;/p&gt;

&lt;p&gt;This extension gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a consistent way to resolve &lt;code&gt;tenantId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;configurable strategy: &lt;strong&gt;Header / JWT / Cookie&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;a clean place to validate &amp;amp; normalize tenant ids&lt;/li&gt;
&lt;li&gt;a shared runtime API you can extend with your own resolver&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s intentionally lightweight: it focuses on &lt;strong&gt;tenant resolution&lt;/strong&gt;, not on re-implementing Quarkus security or ORM internals.&lt;/p&gt;




&lt;h2&gt;
  
  
  When you should use it (and when you shouldn’t)
&lt;/h2&gt;

&lt;p&gt;Use it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you have multiple services and you want a &lt;em&gt;single tenant contract&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;you keep duplicating tenant parsing logic across codebases&lt;/li&gt;
&lt;li&gt;you need consistent behavior for “missing tenant” / “invalid tenant”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may not need it if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;your scenario is purely &lt;strong&gt;OIDC multitenancy&lt;/strong&gt; (tenant-aware auth provider selection) and tenant id never needs to be resolved independently&lt;/li&gt;
&lt;li&gt;you already have a centralized gateway that injects tenant id consistently and you never read from JWT/cookie&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick start (Maven Central)
&lt;/h2&gt;

&lt;p&gt;Add the runtime module you need.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### HTTP runtime

&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;io.github.mathias82&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;quarkus-multitenancy-http-runtime&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;0.1.15&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

### ORM runtime

&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;io.github.mathias82&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;quarkus-multitenancy-orm-runtime&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;0.1.15&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

Header strategy
quarkus.multi-tenant.http.enabled=true
quarkus.multi-tenant.http.strategy=header
quarkus.multi-tenant.http.header-name=X-Tenant

Call it:
curl -H "X-Tenant: tenant1" http://localhost:8080/api/users

JWT strategy (tenant inside claims)

quarkus.multi-tenant.http.enabled=true
quarkus.multi-tenant.http.strategy=jwt
# example claim name (adjust to your token)
quarkus.multi-tenant.http.jwt-claim=tenant_id

Cookie strategy (browser clients)

quarkus.multi-tenant.http.enabled=true
quarkus.multi-tenant.http.strategy=cookie
quarkus.multi-tenant.http.cookie-name=tenantId


Demo (run locally)

If you want to see it working end-to-end with multiple datasources, there’s a demo project in the repo.

docker-compose up -d
mvn quarkus:dev

GitHub repo: https://github.com/mathias82/quarkus-multitenancy

Notes &amp;amp; best practices

A few things I learned while building this:

- Decide precedence (Header vs JWT vs Cookie) once and document it.
- Validate tenant ids (empty/length/pattern) to avoid weird bugs and security issues.
- Make “missing tenant” behavior consistent across services (400 vs 401 vs default tenant).

Read the full article

If you want the full breakdown (idea → extension modules → design choices → Maven Central publishing), the complete write-up is on Medium:

https://medium.com/@mstauroy/building-a-generic-multitenancy-extension-for-quarkus-from-idea-to-maven-central-7c4045c404a3

If you’re using tenant resolution in Quarkus today, I’d love to hear what works best for you (header vs JWT vs cookie) and what constraints you have.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>quarkus</category>
      <category>java</category>
      <category>multitenant</category>
      <category>multitenancy</category>
    </item>
  </channel>
</rss>
