Modeling overview

How Flax's dbt-compatible, git-backed semantic model turns raw warehouse tables into governed, reusable metrics

Flax's semantic model is the shared definition of your business: what a "customer" is, how "revenue" is calculated, and how tables relate. You define it once in YAML, and everyone — analysts, viewers, the AI assistant, and the API — explores the same governed metrics. This page is for anyone setting up or maintaining the model.

#Defined once, explored everywhere, governed by review

The semantic layer follows three principles:

  • Defined once. A dimension or measure is written a single time. Every query, chart, and sheet reuses that definition, so "revenue" means the same thing across the whole organization.
  • Explored everywhere. The model powers the query builder, dashboards, Sheets, the AI assistant, and the API — all against one source of truth.
  • Governed by review. The model is git-backed. Changes are code changes: reviewed, versioned, and auditable. Edits made in the UI open a pull request rather than silently mutating production (see Write-back).

The spec is dbt-compatible YAML. If you already have a dbt project, Flax reads your models/**/*.yml directly; Flax-specific concepts live under a flax: extension key so a file stays a valid dbt schema file.

#What a model contains

A model maps a warehouse table (or dbt model) to a queryable surface with three building blocks:

Concept Purpose
Dimensions Attributes to group and filter by — status, country, order date.
Measures Aggregations — count, sum(amount), count_distinct, and more.
Joins Relationships to other models so cross-model queries work.
version: 2

models:
  - name: orders
    description: One row per order placed in the store.
    flax:
      primary_key: order_id
      dimensions:
        - name: status
          type: string
          sql: ${status}
      measures:
        - name: total_revenue
          type: sum
          sql: ${amount}
      joins:
        - name: customers
          type: left
          sql_on: ${orders.customer_id} = ${customers.customer_id}

Models can also declare a primary_key (for correct counts over fan-out joins) and access_filters (row-level security).

#Next steps