How two new Apache Iceberg™ specs make governance as portable as your data
by Daniel Weeks, Ryan Blue and Andrei Tserakhau
In our previous posts, we showed how open table formats, open APIs and unified governance are coming together to complete the Open Lakehouse vision. We also introduced cross-engine attribute-based access control, which allows policies defined in Unity Catalog to be enforced consistently when external engines access governed data.
Now, that vision is beginning to materialize in the open. The Apache Iceberg™ community recently advanced two important additions to the Iceberg REST Catalog: read restrictions and catalog labels. Together, they address two distinct challenges: delegating enforcement to an external engine and making governance context portable across catalogs.
In this post we will take a closer look at both new additions to the spec: how they work, key challenges they address, future opportunities for innovation, and when to use them.
Read restrictions address a common engine-to-catalog scenario: an organization governs data in one catalog and wants to query it from various engines or tools.
For any governed query, three things must happen:
When data is accessed from an engine, these responsibilities can be divided in two ways.
With centralized enforcement, all three steps remain within the catalog’s environment. For example, Databricks implements fine-grained access control on dedicated compute by transparently routing queries through a secure filtering fleet. And Unity Catalog’s Cross-engine ABAC feature extends this governance to other engines by putting the filtering fleet behind the Iceberg REST catalog scan/plan APIs to sanitize data before an external engine such as Spark1 or DuckDB processes the result.
With delegated enforcement, the catalog receives the requesting identity and evaluates policy, then returns the resulting row and column restrictions to an engine it trusts to enforce them. Here, trust means that the catalog can rely on the engine to enforce the restrictions and prevent users from bypassing them. Engines such as Spark and DuckDB are untrusted when users control the runtime because those users can execute arbitrary code or access the underlying data directly. A securely configured Trino deployment is an example of a trusted engine because it provides native enforcement for row filters and column masks.
Delegated enforcement requires a common contract between the catalog and engine. The Iceberg community adopted read restrictions to provide that contract.
When a reader loads a table through the Iceberg REST Catalog, the catalog evaluates the applicable policies for the requesting principal and request context. It can return required column-projection actions and row-filter expressions, and the trusted engine must apply those restrictions as it reads the table.

Two design decisions are important to understanding the proposal’s current scope.
First, the engine does not receive the policy as the administrator defined it. Instead, it receives the outcome for a particular principal, expressed as filtering or masking instructions that it must apply. This creates a common enforcement contract between the engine and catalog. The initial spec defines a bounded vocabulary: nine predefined column-projection actions and standardized row-filter expressions such as comparisons or set membership. Many real-world enterprise policies depend on subqueries, lookup tables or custom UDFs, which cannot be expressed within the read restrictions vocabulary. This has an important implication: policies can be represented only when the catalog can reduce their result to the vocabulary defined by the standard, otherwise you lose policy semantics.
Second, the specification defines what a trusted engine must enforce, but not how the catalog establishes that trust. A claim from the client is not sufficient, so system administrators and implementations must use security mechanisms appropriate to their environment. Iceberg community discussions have considered mechanisms such as mTLS and OAuth, but trust ultimately remains outside the protocol (Iceberg community discussion).
Read restrictions are best suited for direct engine-to-catalog access scenarios where the source catalog’s policies are simple and a trusted engine can enforce the resulting decision. Many implementation questions remain, such as how an engine securely propagates the end user’s identity and attributes, how a catalog distinguishes the user from the engine acting on the user’s behalf, and how credentials are bound to their intended recipient. As implementations emerge, we’re excited to collaborate with the Iceberg community to work through these challenges and evolve the standard.
Catalog labels address a different scenario: governance across federated catalogs.
Many enterprises now connect multiple catalogs, such as Unity Catalog, Snowflake, AWS Lake Formation and Google Cloud Knowledge Catalog, through federation and open APIs. This is more complex than an engine-to-catalog integration because each catalog serves its own users, applications, and engines through distinct identity models, policy languages, and semantics.
Any unified governance solution that works at enterprise scale must:
Catalog labels, recently adopted by the Iceberg community, is the first step towards this vision. Labels allow catalogs to exchange lightweight key-value metadata at the table and column level via Open APIs. Labels can indicate that a field contains PII, associate a dataset with a business domain, or provide semantic hints for AI models. Because the proposal is general, labels can support many use cases beyond access control, including discovery, ownership, cost attribution, AI context, and data quality.
When a consuming catalog loads a table from a producing catalog via catalog federation, the producing catalog returns table and column-level labels.

The consuming catalog then maps the labels into its own classifications, attributes or native tag model. It then evaluates access using its native identities and policies and enforces controls within its own runtime. For example, if a producing catalog labels an ssn column pii=ssn, the consuming catalog can apply a tag-based policy that masks columns carrying that label.
Because policy enforcement remains local, the consuming catalog preserves the expressiveness of its native policies and avoids calling the producing catalog for each access decision. Each catalog also independently maintains its enforcement records and audit trail.
It is worth keeping in mind that labels are opaque key-value pairs. The standard defines no shared semantics or stable identifiers, and lineage for labels does not extend beyond the source catalog. The consuming catalog receives only the resolved key and value, not whether the label was intended for discovery, access control, cost attribution, or another purpose. Labels therefore make metadata portable, but not its meaning; enterprises still need shared conventions or explicit mappings to interpret labels consistently.
Catalog labels are best suited for catalog-to-catalog scenarios with federation between heterogeneous systems, where the consuming catalog has its own governance system and needs reusable context rather than a separate access decision for every user and request.
Catalog labels is a step towards the long-term vision of open policy exchange. In this world, trusted catalogs exchange governance context and, ultimately, policy definitions through open APIs, while each platform evaluates and enforces controls using its native identity model and runtime. The core idea is that governance and business context, like table metadata, should be open and portable through the Iceberg REST Catalog APIs.
The right model depends on the destination: centralized enforcement for an untrusted engine, read restrictions for a trusted engine, and catalog labels as a foundation for open policy exchange when the destination is another catalog with its own governance system.
Centralized enforcement through scan planning | Read restrictions | Catalog labels | |
How it works | The source catalog evaluates and enforces policy through a secure filtering service, returning only authorized data | At query time, the catalog tells the engine what restrictions to apply for this particular user and asset - e.g. “apply mask_alphanum on column 12” | Catalogs share additional governance or business information about a given table - e.g. “column 12 has classification pii=ssn” |
Best fit | Direct access from an untrusted engine, such as a user-controlled Spark or DuckDB runtime | Direct engine-to-catalog access where the source evaluates policy and a trusted engine enforces the result | Federation between heterogeneous systems with their own identity, policy and enforcement runtime |
Identity and security | Client must translate and pass identity concepts (roles, groups, etc) to the catalog. Enforcement remains within the catalog’s trusted boundary, so unauthorized data never reaches the engine. | The client must translate identity concepts (principals, roles, groups, user attributes) to something that the catalog understands and pass these attributes as part of the request context | The destination uses the identities and attributes it already understands, reducing the sensitive context exchanged between systems |
Scale, performance and availability | Server-side scan planning can optimize data access, but routing governed queries through a filter fleet adds latency and an operational dependency compared with enforcement in the consuming engine. | Browsing, search and queries may repeatedly call the source catalog with limited cache reuse (e.g. listing tables in a schema would require repeated calls for each table per user) | Governance context can be cached and refreshed so that search, browse, and other user experiences are powered natively |
Governance and auditability | The source catalog retains its full native policy expressiveness and records policy evaluation and enforcement within the same trusted environment | Decisions are limited to the standard’s shared vocabulary. Audit records are split across both the source and destination systems. | The destination uses its native policy engine and maintains an end-to-end record of evaluation and enforcement |
Bottom line | Use when the source catalog must guarantee that unauthorized data never reaches an untrusted engine | Use when the destination is a trusted engine and the source policies can be fully expressed with read restrictions | Use when the destination is another catalog that needs scalable governance at native speed across its users and engines |
Read restrictions and catalog labels solve two distinct and important problems for cross-platform governance. Read restrictions give catalogs a standard way to delegate enforcement to trusted engines. Catalog labels make governance and business context portable across catalogs, just like your data is. Along with centralized enforcement through Cross-Engine ABAC, these give enterprises a practical set of options for governing data consistently across engines and catalogs.
Congratulations to the Apache Iceberg community for adopting both proposals. While there is more work ahead, this is a big milestone. We are excited to see more of the ecosystem adopt these foundational building blocks, and to continue working with the community to make unified governance across the open lakehouse a reality.
1Apache Spark’s own security guidance states that user-submitted code runs without restrictions on its behavior and gives users control over the resources assigned to their application. A Spark extension can implement read restrictions, but the deployment qualifies as trusted only when administrators control the runtime and eliminate every path around enforcement since it lacks a table-level access control API, let alone one for fine-grained access control (Iceberg community discussion).
Subscribe to our blog and get the latest posts delivered to your inbox.