Skip to main content

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. That context includes:
  1. Selection of entities and sub-selection of fields, that are accessible when using the domain
  2. Selection of filters that must be applied on every query on the domain
  3. Selection of parameter 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:
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:
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
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.

Filters

Domain may control how data is filtered. There are two types of filters: Semantic and Source.
AspectSemantic FiltersSource Filters
ScopeApply to all queries in a domainApply only when source entity is queried
TimingEnforced after semantic resolution, may add JOINsApplied early, directly on source tables
PurposeGovernance & access controlPerformance optimization (e.g., partitions) and removing duplicate data (with conditional filtering)
CaveatsCan slow queries by introducing extra joinsMay alter computed values due to order of filtering
Best UseConsistent 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,
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. The display_name and description fields are optional.
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 on the domain above that asks for part count:
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.

Semantic Filters using Parameters

A common use case is filtering data based on a parameter 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:
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).
If filtering data through a filtering dimension, make sure it is cross filtering the data with a one-to-many filtering direction.

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, which is common when dealing with either Multi-Grain Data or Slowly Changing Dimensions with Multiple Versions
Source filters are only supported on attributes that come from an entity source table.
A source filter is only applied if the source is part of the query.
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'
Caution: Source filters apply before any other computation is done, which can change the values of calculated attributed. See filtering order for more details.When in doubt, use a semantic filter, not a source filter.

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.
  • Correctness with Multi-Grain tables.
See Conditional Filters for more details.
Conditional Filters are usually used to reduce data at the source, thus they are typically used within source filters.

Domain Hierarchy

Domain hierarchy functionality is currently in Beta. Contact support@honeydew.ai to activate it for your account.
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:
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 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
# 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:
# 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:
# 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:
# 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:
# Parent
labels: [production, sales]

# Child
labels: [analytics]

# Result: [production, sales, analytics]

Metadata Inheritance

Metadata sections are matched by name. Within each section, items are matched by key:
# 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:
entities:
  - name: sensitive_entity
    merge: remove

filters:
  - name: legacy_filter
    merge: remove

parameters:
  - name: OLD_PARAM
    merge: remove
This works for entities, filters, source_filters, and parameters.

Multiple Inheritance

Extend multiple parent domains for composition:
# 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

# 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 for more details.

Domains as a context for dynamic datasets

A dynamic dataset 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.
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 by scoping native data warehouse RLS policies to a domain-specific role.
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
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.
Domain-level settings take precedence over the global data warehouse configuration. Domains without specific settings default to the global configuration for your Honeydew account.
Configure the Snowflake role and warehouse in the domain’s snowflake metadata section. Both fields are optional.
metadata:
  - name: snowflake
    metadata:
      - name: role
        value: <role name>
      - name: warehouse
        value: <warehouse name>
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.

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.

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:
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>
  - ...
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: <section name>
    metadata:
      - name: <key>
        value: <value>
      - ...
  - ...
Fields:
  • name: Name of domain
  • extends: Optional list of parent domains to inherit from
  • display_name, owner, description, labels, tags, folder, hidden: Metadata
  • 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 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 examples for AI, Tableau and Power BI)