Skip to main content

dbt-metabase

PyPI License: MIT Ruff uv

Integration between dbt and Metabase.

If dbt is your source of truth for database schemas and you use Metabase as your analytics tool, dbt-metabase can propagate table relationships, model and column descriptions and semantic types (e.g. currency, category, URL) to your Metabase data model, and extract questions and dashboards as exposures in your dbt project.

Requirements

Requires Python 3.10 or above.

For development, you will need uv installed.

Usage

You can install dbt-metabase from PyPI:

pip install dbt-metabase

Sections below demonstrate basic usage examples, for all CLI options:

dbt-metabase --help

Manifest

Before running dbt-metabase, you need a compiled manifest.json file to parse. These are part of the dbt artifact generated during compilation.

Once dbt compile finishes, manifest.json can be found in the target/ directory of your dbt project.

See dbt documentation for more information.

Metabase API

All commands require authentication against the Metabase API using one of these methods:

  • API key (--metabase-api-key)
    • Strongly recommended for automation, see documentation (Metabase 49 or later).
  • Username and password (--metabase-username / --metabase-password)
    • Fallback for older versions of Metabase and smaller instances.

Exporting Models

Let's start by defining a short sample schema.yml as below.

models:
  - name: stg_users
    description: User records.
    columns:
      - name: id
        description: Primary key.
        data_tests:
          - not_null
          - unique

      - name: email
        description: User's email address.

      - name: group_id
        description: Foreign key to user group.
        data_tests:
          - not_null
          - relationships:
              arguments:
                to: ref('groups')
                field: id

  - name: stg_groups
    description: User groups.
    columns:
      - name: id
        description: Primary key.
        data_tests:
          - not_null
          - unique

      - name: name
        description: Group name.

This is already enough to propagate the primary keys, foreign keys and descriptions to Metabase:

dbt-metabase models \
    --manifest-path target/manifest.json \
    --metabase-url https://metabase.example.com \
    --metabase-api-key mb_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX= \
    --metabase-database business \
    --include-schemas public

Open Metabase and go to Settings > Admin Settings > Table Metadata, you will notice that id column in stg_users is now marked as "Entity Key" and group_id is a "Foreign Key" pointing to id in stg_groups.

Try running dbt-metabase models --help to see all the options available for fine tuning.

Foreign Keys

Native relationship tests and column-level constraints are the recommended ways of defining foreign keys, however you can override them with fk_target_table and fk_target_field meta fields. If both are set for a column, meta fields take precedence.

- name: country_id
  description: FK to User's country in the dim_countries table.
  config:
    meta:
      metabase.fk_target_table: analytics_dims.dim_countries
      metabase.fk_target_field: id

You can provide fk_target_table as schema_name.table_name or just table_name to use the current schema. If your model has an alias, provide that alias rather than the original name.

Semantic Types

Now that we have foreign keys configured, let's tell Metabase that email column contains email addresses:

- name: email
  description: User's email address.
  config:
    meta:
      metabase.semantic_type: type/Email

Once you run dbt-metabase models again, you will notice that email column is now marked as "Email".

Below are common semantic types (formerly known as special types) accepted by Metabase:

  • type/PK
  • type/FK
  • type/Number
  • type/Currency
  • type/Category
  • type/Title
  • type/Description
  • type/City
  • type/State
  • type/ZipCode
  • type/Country
  • type/Latitude
  • type/Longitude
  • type/Email
  • type/URL
  • type/ImageURL
  • type/SerializedJSON
  • type/CreationTimestamp

See Metabase documentation for a more complete list.

Visibility Types

You can optionally specify visibility for tables and columns, this controls whether they are displayed in Metabase.

Here is how you would hide that email column:

- name: email
  description: User's email address.
  config:
    meta:
      metabase.semantic_type: type/Email
      metabase.visibility_type: sensitive

Below are the visibility types supported for columns:

  • normal (default) - This field will be displayed normally in tables and charts.
  • details-only - This field will only be displayed when viewing the details of a single record.
  • sensitive - This field won't be visible or selectable in questions created with the GUI interfaces.

Tables support the following:

  • No value for visible (default)
  • hidden
  • technical
  • cruft

If you notice any changes to these, please submit a pull request with an update.

Other Meta Fields

In addition to foreign keys, semantic types and visibility types, Metabase also accepts the following meta fields:

- name: model_name
  config:
    meta:
      metabase.display_name: another_model_name
      metabase.visibility_type: normal
      metabase.points_of_interest: Relevant records.
      metabase.caveats: Sensitive information about users.
  columns:
    - name: column_name
      config:
        meta:
          metabase.display_name: another_column_name
          metabase.visibility_type: sensitive
          metabase.semantic_type: type/Number
          metabase.has_field_values: list
          metabase.coercion_strategy: keyword
          metabase.number_style: decimal
          metabase.decimals: 3

See Metabase documentation for details and accepted values.

Synchronization

By default, dbt-metabase waits for tables and columns to be synchronized between your dbt project and Metabase database, otherwise the export fails when the sync timeout expires.

If you have known discrepancies between dbt and Metabase and wish to proceed without synchronization, set the sync timeout to zero (e.g. --sync-timeout 0). This is discouraged, because you will still encounter errors if you have a table or column in your dbt project that is missing from Metabase and dbt-metabase attempts to export it.

Exposure Extraction

dbt-metabase allows you to extract questions and dashboards from Metabase as dbt exposures in your project:

dbt-metabase exposures \
    --manifest-path ./target/manifest.json \
    --metabase-url https://metabase.example.com \
    --metabase-api-key mb_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX= \
    --output-path models/ \
    --exclude-collections "temp*"

Once the execution completes, check your output path for exposures files containing descriptions, creator details and links for Metabase questions and dashboards:

exposures:
  - name: number_of_orders_over_time
    description: '
      ### Visualization: Line

      A line chart depicting how order volume changes over time

      #### Metadata

      Metabase Id: __8__

      Created On: __2021-07-21T08:01:38.016244Z__'
    type: analysis
    url: https://metabase.example.com/card/8
    maturity: medium
    owner:
      name: Indiana Jones
      email: indiana@example.com
    depends_on:
      - ref('orders')

Native query questions will have SQL code blocks inside the descriptions, formatted to look nice in dbt docs. These YAML files can be committed to source control to understand how exposures change over time.

Try running dbt-metabase exposures --help to see all the options available for fine tuning.

Configuration

There are 3 levels of configuration in decreasing order of precedence:

  • CLI arguments, e.g. --manifest-path target/manifest.json
  • Environment variables, e.g. MANIFEST_PATH=target/manifest.json
  • Configuration file, e.g. manifest_path: target/manifest.json

Try running --help for any command to see the full list of CLI arguments and environment variables.

A configuration file can be created in ~/.dbt-metabase/config.yml for dbt-metabase to pick it up automatically or anywhere else by specifying dbt-metabase --config-path path/to/config.yml (must come before the command). Here is an example YAML file:

config:
    manifest_path: target/manifest.json
    metabase_url: https://metabase.example.com
    metabase_api_key: mb_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
    # Configuration specific to models command
    models:
      metabase_database: business
    # Configuration specific to exposures command
    exposures:
      output_path: models

Note that common configurations are in the outer block and command-specific ones are in separate blocks.

Programmatic API

Alternatively, you can invoke dbt-metabase programmatically. Below is the equivalent of CLI examples:

from dbtmetabase import DbtMetabase, Filter

# Initializing instance
c = DbtMetabase(
    manifest_path="target/manifest.json",
    metabase_url="https://metabase.example.com",
    metabase_api_key="mb_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=",
)

# Exporting models
c.export_models(
    metabase_database="business",
    schema_filter=Filter(include=["public"]),
)

# Extracting exposures
c.extract_exposures(
    output_path=".",
    collection_filter=Filter(exclude=["temp*"]),
)

See function header comments for information about other parameters.

Metadata

Release files for dbt-metabase 1.7.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dbt-metabase 1.7.5
File Size Uploaded Provenance
dbt_metabase-1.7.5.tar.gz 847.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for dbt-metabase 1.7.5
File Interpreter ABI Platform
dbt_metabase-1.7.5-py3-none-any.whl Python 3 none any Details

Total release size: 878.0 kB

Release files / dbt_metabase-1.7.5.tar.gz

Download URL dbt_metabase-1.7.5.tar.gz
Size 847.5 kB
Tags Source
SHA-256 checksum
How to use checksums
558ff77538745113737445e7631a55bc30a04c649e0a231ed7780b6d2a4e174e
BLAKE2b-256 checksum
How to use checksums
04e6430cc27aff7613390cd31e2cae929082a009ed7267a387b6e522801f10b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 6, 2026.

Transparency log

Release files / dbt_metabase-1.7.5-py3-none-any.whl

Download URL dbt_metabase-1.7.5-py3-none-any.whl
Size 30.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c5852dbb2f2598107eb6d5239a5d3d8265aadd07827014e7e5600b368cbb56b
BLAKE2b-256 checksum
How to use checksums
3d58f0608a86ef23ed436be713d41c523499044ee929375a1d2e6fa38af631c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 6, 2026.

Transparency log

Security for dbt-metabase 1.7.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for dbt_metabase-1.7.5.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.7.5 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page