> ## Documentation Index
> Fetch the complete documentation index at: https://honeydew.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Domains

## Creating Business Context

A user in Finance or Marketing on a semantic layer does not want or may not be allowed access to *everything*.
They want to see semantics relevant to them, with their context applied.

That concept is called in Honeydew a "Domain".

A Domain is a lightweight governance object that allows to build
context for users, as well as maintain access control on data and
on metadata.

<Tip>
  AI access to domains is managed through [agents](/docs/integration/context-layer/agents).
</Tip>

That context includes:

1. Selection of [entities](/docs/modeling/entities) and sub-selection of fields, that are accessible when using the domain
2. Selection of [filters](/docs/calculations/filters) that must be applied on every query on the domain
3. Selection of [parameter](/docs/parameters) overrides that apply in the domain context

### Selecting entities and fields

Domain allows to select entities that participate. For example, a domain that selects a subset
of entities from TPCH:

```yaml theme={null}
type: domain
name: orders_domain
description: Orders Tracing Domain

# Entities and fields that participate
entities:
  - name: lineitem
  - name: orders
  - name: partsupp
  - name: part
```

#### Selecting entity fields

By default, all fields from an entity are included in the domain. You can control which fields
are included using **field selectors** - string patterns evaluated in the order they are listed.

**Field selector syntax:**

* `*` - Include all fields
* `field_name` - Include a specific field
* `-field_name` - Exclude a specific field
* `pattern*`, `*pattern`, `*mid*` - Include fields matching a wildcard pattern
* `-pattern*`, `-*pattern`, `-*mid*` - Exclude fields matching a wildcard pattern

**Evaluation rules:**

* Selectors are evaluated **in the order they are listed**
* The last matching selector determines whether a field is included or excluded
* If no selectors are specified, all fields are included (equivalent to `["*"]`)

**Examples:**

```yaml theme={null}
entities:
  # Include all fields (default behavior)
  - name: customers

  # Include only specific fields
  - name: orders
    fields:
      - order_id
      - order_date
      - order_total

  # Include all fields except specific ones
  - name: employees
    fields:
      - "*"
      - "-salary"
      - "-ssn"

  # Include fields matching a pattern
  - name: products
    fields:
      - product_*

  # Complex selection: all fields, exclude internal, re-include one
  - name: transactions
    fields:
      - "*"
      - "-internal_*"
      - internal_status
```

<Tip>
  Field selectors are evaluated in order. For example, `["*", "-field_a", "field_a"]` will include
  `field_a` because the last matching selector (`field_a`) is an inclusion.
</Tip>

### Filters

Domain may control how data is filtered.

There are two types of filters: **Semantic** and **Source**.

| Aspect       | Semantic Filters                                  | Source Filters                                                                                       |
| ------------ | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Scope**    | Apply to all queries in a domain                  | Apply only when source entity is queried                                                             |
| **Timing**   | Enforced after semantic resolution, may add JOINs | Applied early, directly on source tables                                                             |
| **Purpose**  | Governance & access control                       | Performance optimization (e.g., partitions) and removing duplicate data (with conditional filtering) |
| **Caveats**  | Can slow queries by introducing extra joins       | May alter computed values due to order of filtering                                                  |
| **Best Use** | Consistent rules (e.g., tenant, access filters)   | Performance with large/partitioned data                                                              |

#### Semantic Filters

Filters within a domain apply to every query on the domain. Think of them as filters every user must add to every query.

For example,

```yaml theme={null}
type: domain
name: orders_domain
description: Domestic Orders Tracing Domain

# Entities and fields that participate
entities:
  - name: lineitem
  - name: orders
  - name: partsupp
  - name: part

# Semantic Filters that always apply to every query on the domain
filters:
  - name: ground_shipping
    sql: lineitem.l_shipmode in ('MAIL', 'RAIL', 'TRUCK')
    display_name: Ground Shipping Only
    description: Only include shipments via ground transportation
```

Semantic filter's `sql` field can contain ad-hoc expressions (as in the example above) or
reference named boolean [attributes](/docs/calculations/attributes).
The `display_name` and `description` fields are optional.

<Tip>
  A semantic filter will be always added to a query in a domain context. That means that semantic filters may have a performance impact when they introduce more JOINs.

  For example, this [SQL query](/docs/integration/sql-interface) on the domain above that asks for part count:

  ```sql theme={null}
  SELECT AGG("part.count") FROM domains.orders_domain
  ```

  will include a JOIN to `lineitems` even though it was not directly referenced in the query to make sure only parts that where shipped over ground are included.
</Tip>

#### Semantic Filters using Parameters

A common use case is filtering data based on a [parameter](/docs/parameters) that sets user context.

For example, if:

1. Every user operates within a tenant context
2. Data in Snowflake is partitioned by a tenant column (in the example below in a tenant dimension `dim_tenant`, though can be a column in every table)
3. Users are only allowed to see data within their own tenant

Set `$TENANT` user parameter, and use it as a domain filter:

```yaml theme={null}
type: domain

# Entities that participate ..

filters:
  - name: tenant_filter
    sql: dim_tenant.tenant_id = $TENANT
```

Apply the parameter in the manner appropriate for the user queries (whether it is through BI connection settings or Snowflake `SET` statements).

<Tip>
  If filtering data through a filtering dimension, make sure it is [cross filtering](/docs/modeling/relations#cross-filtering) the data with a `one-to-many` filtering direction.
</Tip>

<Warning>
  A semantic filter reaches every entity connected to the filtered one by bi-directional
  [cross-filtering](/docs/modeling/relations#cross-filtering), including in queries that never reference
  the filtered entity. A filter meant to pin one entity can restrict unrelated metrics across the
  domain that way.
</Warning>

#### Source Filters

Source filters are filters that are applied at the source level (unlike semantic filters that apply to the semantic layer as a whole).

The use cases for source filters are:

1. Improving performance with logically partitioned data by always pushing filters below calculated attributes.
2. Removing duplicated data using [conditional filtering](/docs/advanced-modeling/conditional-filtering) on a
   column of the duplicated source itself - a grain column for
   [Multi-Grain Data](/docs/advanced-modeling/multi-grain-tables#domain-level-deduplication), or validity
   columns for
   [Slowly Changing Dimensions](/docs/advanced-modeling/slowly-changing-dimensions#ensuring-filtering-for-a-point-in-time).

   Write such a filter on the duplicated source's own columns. Written on a separate reference
   entity instead, it is skipped by every query that does not reach that entity.

<Note>
  Source filters are only supported on attributes that come from an entity [source table](/docs/modeling/entities#source-table).
</Note>

A source filter is applied wherever its source is read in the query, including when the query never
names that entity and it is pulled in to connect two entities the query does name. A query that
reads none of the filter's source data does not carry it.

```yaml theme={null}
type: domain
name: orders_domain
description: Domestic Orders Tracing Domain

# Entities and fields that participate
entities:
  - name: lineitem
  - name: orders
  - name: partsupp
  - name: part

source_filters:
  - name: shipping_date_in_1994
    sql: lineitem.l_shipdate >= '1994-01-01' and lineitem.l_shipdate < '1995-01-01'
```

<Warning>
  **Caution**: Source filters apply before any other computation is done, which can change the values of calculated attributed.
  See [filtering order](/docs/advanced-modeling/order-of-computation) for more details.

  When in doubt, use a semantic filter, not a source filter.
</Warning>

### Conditional Filtering

In some case, a domain filter is desired **unless the user filtered otherwise**.

The main use cases are:

* Performance on large datasets - reduce the data by default unless the user has explicitly asked for more data.
* Correctness with [Slowly Changing Dimensions](/docs/advanced-modeling/slowly-changing-dimensions).
* Correctness with [Multi-Grain](/docs/advanced-modeling/multi-grain-tables) tables.

See [Conditional Filters](/docs/advanced-modeling/conditional-filtering) for more details.

<Tip>
  Conditional Filters belong in source filters, on the columns of the data being reduced or
  deduplicated. The entity whose value the user picks is detected separately, and does not have to be
  the entity being filtered.
</Tip>

## Domain Hierarchy

Domains can extend one or more parent domains, inheriting
and building upon their configuration.
This enables reusable base domains that compose
into specialized domains.

### Extending Domains

Use the `extends` field to inherit from parent domains:

```yaml theme={null}
type: domain
name: child_domain
extends:
  - parent_domain
```

#### What Gets Inherited

A child domain inherits from its parents:

* All entities and their field selections
* All filters (semantic and source)
* All parameters
* All tags
* All labels (additive)
* All metadata sections

#### How Items Merge

Items in lists are matched by `name`. When a child defines
an item with the same name as a parent:

* **Scalar fields** (like `sql` in filters) are replaced
* **Collection fields** (like `fields` in entities)
  are extended
* Use `merge: remove` to remove an inherited item

```yaml theme={null}
# Parent domain
type: domain
name: parent

entities:
  - name: customers
  - name: orders
  - name: products

filters:
  - name: active
    sql: status = 'active'

---

# Child domain
type: domain
name: child
extends:
  - parent

entities:
  - name: invoices        # Add new entity
  - name: orders          # Extend orders
    fields: [order_id, order_date]
  - name: products        # Remove inherited
    merge: remove

filters:
  - name: active          # Replace parent filter
    sql: status = 'active' AND deleted_at IS NULL

# Result entities: [customers, orders (extended), invoices]
```

### Field Inheritance

When a child extends a parent entity, field operations
apply on top of the inherited field list:

```yaml theme={null}
# Parent
entities:
  - name: customers
    fields: [*]
  - name: orders
    fields: [order_id, order_date, order_status]

# Child
entities:
  - name: customers
    fields: ["-ssn", "-salary"]  # Remove from inherited
  - name: orders
    fields: [order_total]    # Add to inherited

# Result:
# - customers: All fields except ssn, salary
# - orders: [order_id, order_date, order_status, order_total]
```

If the parent has `fields: [*]`, the child already inherits
all fields. To restrict to specific fields, use `-*` first:

```yaml theme={null}
# Parent has all fields
entities:
  - name: customers
    fields: [*]

# Child wants only specific fields
entities:
  - name: customers
    fields: ["-*", id, name, email]
```

### Filter Inheritance

Filters with the same `name` replace parent filters:

```yaml theme={null}
# Parent
filters:
  - name: region_filter
    sql: region = 'US'

# Child
filters:
  - name: region_filter
    sql: region IN ('US', 'CA')  # Replaces parent
  - name: active_only
    sql: status = 'active'       # New filter
```

This applies to both semantic and source filters.

### Label Inheritance

Labels use additive inheritance — child labels are added
to parent labels:

```yaml theme={null}
# Parent
labels: [production, sales]

# Child
labels: [analytics]

# Result: [production, sales, analytics]
```

### Tag Inheritance

Tags are matched by `key`. Child tags with the same `key`
replace the parent tag; new keys are added:

```yaml theme={null}
# Parent
tags:
  - key: env
    value: prod
  - key: team
    value: sales

# Child
tags:
  - key: env
    value: staging  # Replaces parent
  - key: region
    value: us       # New tag

# Result: env=staging, team=sales (inherited), region=us
```

### Metadata Inheritance

Metadata sections are matched by `name`. Within each
section, items are matched by `key`:

```yaml theme={null}
# Parent
metadata:
  - name: snowflake
    metadata:
      - name: role
        value: default_role
      - name: warehouse
        value: default_wh

# Child
metadata:
  - name: snowflake
    metadata:
      - name: warehouse
        value: prod_wh  # Overrides parent
      - name: short_term_cache_ttl_in_seconds
        value: 3600     # New item

# Result: role=default_role (inherited),
#   warehouse=prod_wh (overridden),
#   short_term_cache_ttl_in_seconds=3600 (new)
```

### Removing Inherited Items

Use `merge: remove` to exclude items inherited
from parents:

```yaml theme={null}
entities:
  - name: sensitive_entity
    merge: remove

filters:
  - name: legacy_filter
    merge: remove

parameters:
  - name: OLD_PARAM
    merge: remove

tags:
  - key: deprecated_tag
    merge: remove
```

This works for entities, filters, source\_filters,
parameters, and tags.

### Multiple Inheritance

Extend multiple parent domains for composition:

```yaml theme={null}
# Base data model
type: domain
name: base_sales
entities:
  - name: fact_sales
    fields: [*]
  - name: dim_customer
    fields: [*]

---

# Security configuration
type: domain
name: security_mixin
filters:
  - name: exclude_test
    sql: is_test = false

---

# Performance configuration
type: domain
name: performance_mixin
source_filters:
  - name: partition_recent
    sql: date >= '2024-01-01'

---

# Combined domain
type: domain
name: sales_secure
extends:
  - base_sales
  - security_mixin
  - performance_mixin

entities:
  - name: dim_customer
    fields: ["-*", customer_id]  # Only ID (no PII)

filters:
  - name: public_only
    sql: visibility = 'PUBLIC'
```

Parents are evaluated left-to-right. If multiple parents
define the same item, the rightmost parent wins.
The child overrides all parents.

### Example: Regional Sales

```yaml theme={null}
# Base sales domain
type: domain
name: base_sales

entities:
  - name: customers
    fields: [*]
  - name: orders
    fields: [*]
  - name: products
    fields: [*]

filters:
  - name: exclude_test
    sql: orders.is_test = false

metadata:
  - name: snowflake
    metadata:
      - name: role
        value: analyst_role

---

# US sales domain
type: domain
name: sales_us
extends:
  - base_sales

entities:
  - name: customers
    fields: ["-ssn"]

filters:
  - name: us_region
    sql: customers.country = 'US'

source_filters:
  - name: recent_data
    sql: orders.order_date >= '2024-01-01'

parameters:
  - name: REGION
    value: 'US'

labels:
  - us_market

metadata:
  - name: snowflake
    metadata:
      - name: warehouse
        value: us_warehouse
```

The `sales_us` domain includes:

* All three entities (customers without SSN)
* Both filters (`exclude_test` inherited, `us_region` added)
* Source filter for recent data
* US region parameter
* Snowflake metadata: `analyst_role` inherited,
  `us_warehouse` added

## Interfaces

### Domains on SQL interface

Domains are present as a flat table in the `domains` schema.

* Attributes that are part of the domain are accessible as SQL columns.
* Metrics that are part of the domain are accessible as SQL columns that can be aggregated on.
* All filters of the domain apply (in addition to any filters in the SQL query).

See [SQL interface](/docs/integration/sql-interface) for more details.

### Domains as a context for dynamic datasets

A [dynamic dataset](/docs/dynamic-datasets) can be associated with a domain. In that case, all domain configuration applies to the dynamic dataset query.

## Data Warehouse-specific domain configuration

### Data warehouse access control

Domains can be configured to manage data warehouse session settings,
such as assigning a specific role or linking a designated compute
resource to each domain.

<Tip>
  Domain-level configuration allows you to link user access
  (e.g., via a BI tool, SQL interface, or the Honeydew native
  application) to specific data and cost governance policies.

  This can also be used to enforce
  [row-level security](/docs/security/row-level-security#domain-level-data-warehouse-roles)
  by scoping native data warehouse RLS policies to a domain-specific role.
</Tip>

This configuration is applied in the following scenarios:

1. Queries executed through the Honeydew SQL interface, such as those from a BI tool
2. Queries executed via the Honeydew Native Application
3. Queries run from the Honeydew web user interface

<Note>
  If a third-party tool uses Honeydew only to compile a SQL query and executes the query independently,
  the domain's data warehouse configuration will not apply to that query.
</Note>

Domain-level settings take precedence over the global data warehouse configuration.
Domains without specific settings default to the global configuration for your Honeydew account.

<Tabs>
  <Tab title="Snowflake">
    Configure the Snowflake role and warehouse in the domain's
    `snowflake` metadata section. Both fields are optional.

    ```yaml theme={null}
    metadata:
      - name: snowflake
        metadata:
          - name: role
            value: <role name>
          - name: warehouse
            value: <warehouse name>
    ```

    <Note>
      Domain-level Snowflake role and warehouse configuration
      **does not apply** to deployment actions of Dynamic Datasets
      as views or tables in Snowflake. They are used only for data
      queries executed on the domain or on dynamic datasets
      associated with the domain.
    </Note>
  </Tab>

  <Tab title="Databricks">
    Configure the Databricks catalog and warehouse in the domain's
    `databricks` metadata section. Both fields are optional.

    ```yaml theme={null}
    metadata:
      - name: databricks
        metadata:
          - name: catalog
            value: <catalog name>
          - name: warehouse
            value: <warehouse name>
    ```

    Define
    [row filters](https://docs.databricks.com/aws/en/data-governance/unity-catalog/filters-and-masks)
    in Unity Catalog scoped to the service principal's permissions on that catalog.

    <Note>
      Domain-level Databricks catalog and warehouse configuration
      **does not apply** to deployment actions of Dynamic Datasets.
      They are used only for data queries executed on the domain
      or on dynamic datasets associated with the domain.
    </Note>
  </Tab>

  <Tab title="BigQuery">
    Configure the BigQuery dataset in the domain's `bigquery`
    metadata section.

    ```yaml theme={null}
    metadata:
      - name: bigquery
        metadata:
          - name: dataset
            value: <dataset name>
    ```

    Define
    [BigQuery RLS policies](https://cloud.google.com/bigquery/docs/row-level-security-intro)
    scoped to the service account's IAM access groups on that
    dataset.

    <Note>
      Domain-level BigQuery dataset configuration **does not apply**
      to deployment actions of Dynamic Datasets. It is used only for
      data queries executed on the domain or on dynamic datasets
      associated with the domain.
    </Note>
  </Tab>
</Tabs>

### Snowflake short-term aggregate caching

Domains can be configured to enable short-term aggregate caching in Snowflake.
For more information, see
[Snowflake Short-Term Aggregate Caching](/docs/performance/aggregate-awareness#automatic-aggregate-caching-in-snowflake).

## Tool-specific domain metadata

Domains can carry metadata sections read by specific tools and integrations:

* [Excel](/docs/integration/bi-tools/excel#grand-totals)
* [Tableau](/docs/integration/bi-tools/tableau#domain)
* [Power BI](/docs/integration/bi-tools/powerbi#power-bi-specific-metadata)

## YAML Schema

Each domain is defined by a YAML file in Git, which also tracks and preserves the full history of every change.

The schema for a domain is:

```yaml theme={null}
type: domain
name: <name>
extends:
  - <parent domain name>
  - ...
display_name: <display name>
owner: <owner>
description: |-
  <description>
labels: [label1, label2, ...]
tags:
  - key: <key>
    value: <value>
    source: <snowflake/databricks/bigquery/honeydew/other>
    merge: remove  # Optional: remove inherited tag
  - ...
folder: <folder>
hidden: <True/False/Yes/No>
entities:
  - name: <entity name>
    fields:
      - <field selector>
      - ...
    merge: remove  # Optional: remove inherited entity
  - ...
filters:
  - name: <filter name>
    sql: <filter expression>
    display_name: <display name>  # optional
    description: <description>    # optional
    merge: remove  # Optional: remove inherited filter
  - ...
source_filters:
  - name: <filter name>
    sql: <source filter expression>
    display_name: <display name>  # optional
    description: <description>    # optional
    merge: remove  # Optional: remove inherited source filter
  - ...
parameters:
  - name: <parameter name>
    value: <parameter value>
    merge: remove  # Optional: remove inherited parameter
  - ...
metadata:
  - name: <metadata section name>
    metadata:
      - name: <metadata field name>
        value: <metadata field value>
      - ...
  - ...
```

Fields:

* `name`: Name of domain
* `extends`: Optional list of parent domains to inherit from
* `display_name`, `owner`, `description`, `labels`, `folder`, `hidden`: Metadata
* `tags`: List of key-value tags; matched by `key` when inheriting — child tags replace
  parent tags with the same key; use `merge: remove` to remove an inherited tag
* `entities`: List of entities that participate in the domain
  * `name`: Name of entity
  * `fields`: List of field selectors (if omitted, all fields are included)
    * Each selector is a string: `*`, `field_name`, `-field_name`, or a wildcard pattern
    * Selectors are evaluated in the order listed; last match determines inclusion
  * `alias`: Optional alias for entity
  * `merge`: Optional `remove` to remove inherited entity
* `filters`: List of semantic filters
  * `name`: Unique identifier for the filter
  * `sql`: Filter expression
  * `display_name`: Optional human-readable name
  * `description`: Optional description
  * `merge`: Optional `remove` to remove inherited filter
* `source_filters`: List of source filters
  * `name`: Unique identifier for the filter
  * `sql`: Filter expression
  * `display_name`: Optional human-readable name
  * `description`: Optional description
  * `merge`: Optional `remove` to remove inherited source filter
* `parameters`: List of [parameters](/docs/parameters) and values (override workspace
  or parent domain values)
  * `name`: Parameter name
  * `value`: Parameter value
  * `merge`: Optional `remove` to remove inherited parameter
* `metadata`: Additional metadata sections for the domain
  * `name`: Section name (e.g., honeydew, snowflake)
  * `metadata`: Key-value pairs within the section
    (see [Tool-specific domain metadata](#tool-specific-domain-metadata) for examples)
