AI Engineering

The Path Is the Policy: How We Eliminated Row-Level Security Filters

How Auraa enforces multi-tenant isolation by addressing instead of row-level security filters, using tenant-scoped Delta paths that can't be misconfigured.

The Path Is the Policy: How We Eliminated Row-Level Security Filters
7:36

Website_1 13

 
 

Editor's note (2026-05-12). When this post was published, Auraa used Databricks Synced Tables (managed DLT pipelines) to mirror Delta → Lakebase. In May 2026, we replaced Synced Tables with GovernanceWriter parallel fan-out: the repository layer dual-writes to silver Delta and Lakebase as a single unit of work. The architectural decision (selective Lakebase mirroring, Delta as sole write authority) is unchanged; only the mechanism shifted from infrastructure-managed sync to application-managed fan-out. References to "Synced Tables" below now mean GovernanceWriter dual-write.

Multi-tenant data platforms face a tension that every platform team navigates differently. Every tenant wants strong isolation guarantees. Every agent, analyst, and API endpoint wants seamless retrieval. The conventional resolution is a middleware layer: row-level security filters that rewrite every query to inject a WHERE tenant_id = ? predicate.

This works. It also fails in subtle ways. A missed filter exposes cross-tenant data. A new query path that bypasses the interceptor creates a vulnerability. A direct table access skips the rewrite entirely. You end up auditing middleware rather than trusting architecture.

Auraa uses a different approach. There are no row-level filters in the critical path. Isolation is enforced by addressing, not filtering.

Three Decisions That Compound

The architecture rests on three foundational choices:

  1. Metadata is data. All platform state — user roles, tool registries, quality rules, execution logs, lineage graphs — flows through the same Bronze/Silver/Gold medallion pattern as business data. Delta Lake is the single write authority for both. There is no separate operational database.
  2. Organization is configuration. Project structure within a tenant is not hardcoded. It is a per-tenant choice — schema-per-project, catalog-per-project, or environment-catalog — resolved at runtime by TenantPathResolver into fully qualified Unity Catalog paths.
  3. Retrieval adapts to the consumer. Delta remains the sole write authority. GovernanceWriter (UC-323) dual-writes selected tables to Lakebase in the same unit of work, providing sub-second API reads and connection pooling for workloads that need them.

Each decision is independently valuable. Their compounding is what makes the architecture interesting.

Isolation by Construction

When a component calls TenantPathResolver.resolve("customer", project_id="alpha", layer="silver"), the resolver returns a fully qualified path:


# Strategy: Schema per Project
aura_tenant_acme.project_alpha_silver.customer
# Strategy: Catalog per Project aura_project_acme_alpha.silver.customer
# Strategy: Environment-Catalog, Source-Schema aura_tenant_acme_prod.crm.customer

The path encodes the tenant boundary. There is no tenant_id column to forget. There is no filter to misconfigure. A component that resolves paths correctly cannot access another tenant's data, because the other tenant's data lives at a different Unity Catalog address.

This property holds for both writes and reads. DataDuct writes ingested data to the resolved path. An agent retrieves metadata from the resolved path. The same resolver, the same isolation, applied uniformly to every operation.

One Pattern, Two Payloads

Because metadata is data, platform state and business data follow the same medallion pattern through the same tenant-scoped paths:

  • Role assignments flow through governance.tenant_principal_roles (Bronze → Silver)
  • Tool registry definitions flow through registry.tools (published by Foundra at init, read by MCP at runtime)
  • Data quality rules and results live alongside the business tables they govern

An agent asking "which tables have data quality failures?" queries the same Delta tables, through the same resolver, with the same isolation guarantees as an analyst asking "what were last month's sales?" The retrieval pattern is uniform; only the payload differs.

Write Once, Retrieve Many Ways

Delta as the single write authority doesn't mean Delta is the only retrieval surface. The Lakehouse provides multiple modes:

Consumer Retrieval Mode Latency
Spark SQL analytics Direct Delta read Seconds
Agent tool invocation SQL Warehouse via MCP Sub-second
REST API SQL Warehouse endpoint Sub-second
Auth middleware (high-concurrency) Lakebase via GovernanceWriter dual-write Read-your-own-write

The auth middleware — which must resolve tenant and role on every API request — is a perfect example. Role assignments are written to Delta (preserving the full append-only audit trail). In the same unit of work, GovernanceWriter mirrors the current-state Silver row to Lakebase. The middleware queries Lakebase for sub-second, connection-pooled point lookups. The write path and the read path are independently optimized without violating the single-source-of-truth invariant.

Environment Portability Without Code Changes

The environment-as-catalog model means dev, staging, and prod each have their own catalog, their own data, their own roles — but the same code:

aura_tenant_acme_dev.crm.customer    ← dev data, dev roles 
aura_tenant_acme_prod.crm.customer ← prod data, prod roles

Pipeline code never contains environment-specific paths. The TenantPathResolver injects the correct catalog at runtime. Quality rules defined in dev apply in prod — same rule, same resolver, different catalog. Agents tested in dev work in prod — same tool definitions, correct context from the resolver.

This is the compounding effect. Once you commit to treating organization as configuration and metadata as data, environment portability falls out naturally from the architecture rather than requiring explicit tooling to manage.

The Honest Trade-offs

The TenantPathResolver becomes critical infrastructure. A resolver bug means writes land in the wrong location. Auraa mitigates this through immutable frozen dataclass design (the resolver is a pure function over immutable inputs), exhaustive strategy testing, and factory-only construction that validates the strategy before returning an instance.

Strategy migration post-onboarding is non-trivial by design. Changing a tenant's organization strategy requires data movement, metadata re-registration, and grant re-application. The choice of strategy is foundational, not a runtime toggle. Choose carefully at onboarding.

Each Lakebase-mirrored table adds a parallel write to every mutation. Tables serving API endpoints or high-concurrency reads justify the dual-write cost. Tables consumed only by Spark batch jobs don't. The judgment isn't hard for clear cases; it requires more thought for tables with mixed access patterns. (Pre-May 2026 this was a DLT compute cost; with GovernanceWriter it's a write-latency cost paid by the mutating component.)

The Principle

Decide how to store early (metadata is data — everything goes through Delta and the medallion). Decide where to store flexibly (organization as configuration — let tenants choose the right isolation model). Decide how to retrieve pragmatically (selective sync — optimize reads for each consumer without duplicating the write path).

The result is a system that is simpler to reason about, harder to misconfigure, and more flexible for tenants with different requirements.

The path is the policy. Delta is the authority. The Lakehouse is the surface.

 

Building multi-tenant platforms on Databricks?

See how Covasant designs tenant-isolated, single-source-of-truth lakehouse architectures that trade misconfiguration risk for structural guarantees, without sacrificing retrieval performance.

 

Similar posts

Get notified on new marketing insights

Be the first to know about new B2B SaaS Marketing insights to build or refine your marketing function with the tools and knowledge of today’s industry.