Blog ·
The tenant filter is a safety net, not a floor
Hibernate's tenant filter is a safety net. Treating it as the mechanism is how you get one company's data on another company's screen.

Hibernate’s tenant filter is a safety net. Treating it as the mechanism is how you get a leak.
In a multi-tenant system you can add a filter to your entities and have the ORM append the company condition to your queries. It works, it’s elegant, and it catches the query someone forgot to scope.
What the filter doesn’t cover
Then you find what it doesn’t cover:
- Native queries. Straight to the driver, no filter.
- Any entity that doesn’t declare it. The worst leak I found was in a dashboard whose entity had never been annotated — metrics aggregating across every company, with no second line to save it.
- Super-admin paths and any code that deliberately bypasses the context.
- Anything running outside a transaction with the tenant resolved — background jobs, startup code.
- Derived query methods, if your architecture rules only inspect annotated queries. That’s how a
countByEstadowalked past mine.
None of that is a flaw in the filter. It’s a flaw in believing a net is a floor.
The doctrine: explicit filtering
Every query scopes by company because it was written to, and the filter exists to catch the human error. Belt and suspenders, in that order.
One thing worth doing regardless: an automated test that seeds two companies and walks the main read paths with a token from one, asserting nothing from the other comes back. It turns “the filter is active” from a belief into a fact the pipeline checks on every change.
Leaking one company’s data into another’s screen is the worst bug this class of system can have. It deserves two independent mechanisms and a test that proves both. In YSY Empresa, our multi-tenant ERP, we audit specifically for this class of failure across every module — it’s why isolation is verified on every query, not assumed by convention.