> ## 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](/integration/context-layer/agents).
</Tip>

That context includes:

1. Selection of [entities](/modeling/entities) and sub-selection of fields, that are accessible when using the domain
2. Selection of [filters](/calculations/filters) that must be applied on every query on the domain
3. Selection of [parameter](/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](/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](/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](/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](/modeling/relations#cross-filtering) the data with a `one-to-many` filtering direction.
</Tip>

#### 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](/advanced-modeling/conditional-filtering), which is common when
   dealing with either [Multi-Grain Data](/advanced-modeling/multi-grain-tables#domain-level-deduplication) or
   [Slowly Changing Dimensions with Multiple Versions](/advanced-modeling/slowly-changing-dimensions#advanced%3A-multiple-scd2-fact-and-dimension-%2B-point-in-time-reference-point)

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

A source filter is only applied if the source is part of the query.

```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](/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](/advanced-modeling/slowly-changing-dimensions).
* Correctness with [Multi-Grain](/advanced-modeling/multi-grain-tables) tables.

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

<Tip>
  Conditional Filters are usually used to reduce data at the source, thus they are typically used within source filters.
</Tip>

## Domain Hierarchy

<Info>
  Domain hierarchy functionality is currently in Beta.
  Contact [support@honeydew.ai](mailto:support@honeydew.ai) to activate it for your account.
</Info>

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](/integration/sql-interface) for more details.

### Domains as a context for dynamic datasets

A [dynamic dataset](/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](/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](/performance/aggregate-awareness#automatic-aggregate-caching-in-snowflake).

## Tool-specific domain metadata

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

* [Excel](/integration/bi-tools/excel#grand-totals)
* [Tableau](/integration/bi-tools/tableau#domain)
* [Power BI](/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](/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)
