<@U088WCP3B4P> We are planning to implement Elemen...
# ask-elementary-ai
g
@kapa.ai We are planning to implement Elementary in our dbt core/dagster/snowflake stack and I am looking for advised strategies to keep the associated runtime duration minimized.
k
Here are the key strategies to minimize Elementary's runtime impact on your dbt Core / Dagster / Snowflake stack: 1. Disable Column Auto-Upload (Biggest Win) Column metadata upload is frequently the largest bottleneck, sometimes causing 30+ minute runtimes. Disable it with:
Copy code
vars:   columns_upload_strategy: none
One user reported going from ~30 minutes to 4–5 minutes by disabling this. [reduce on-run-end time] 2. Disable Metadata Artifacts Auto-Upload Metadata (models, tests, sources, etc.) only needs to be uploaded when your project structure changes — not on every run. Disable auto-upload and trigger it manually on deploys (e.g., after merging a PR):
Copy code
vars:   disable_dbt_artifacts_autoupload: true
Then upload manually when needed:
Copy code
dbt run --select elementary --vars '{"enable_elementary_models": true}'
This is the most effective way to reduce
on-run-end
time for large projects. [reduce on-run-end time] 3. Disable Hooks for Non-Production Environments Avoid Elementary overhead during local development or PR runs by scoping hooks to production only:
Copy code
vars:   disable_run_results: "{{ target.name != 'prod' }}"   disable_tests_results: "{{ target.name != 'prod' }}"   disable_dbt_invocation_autoupload: "{{ target.name != 'prod' }}"
> ⚠️ Disabling these hooks means you will lose that data for those runs. Only do this for runs you don't need to monitor. [reduce on-run-end time] 4. Expect a Slow First Run The very first run will be slow because Elementary uploads all metadata from scratch with no cache. From dbt 1.4.0+, Elementary uses a metadata hash cache — subsequent runs only re-upload what has changed, so they will be significantly faster. [community thread] 5. Avoid Dynamic Expressions in Model Configs If your model configs use dynamic expressions like
now()
or
CURRENT_TIMESTAMP
, the metadata cache will be invalidated on every run, forcing a full re-upload each time. Avoid these where possible. [community thread] 6. Use Chunked Inserts for Large Datasets For large projects, instruct Elementary to upload results in chunks:
Copy code
vars:   insert_rows_method: chunk   dbt_artifacts_chunk_size: 500
[community thread] 7. Tune Thread Count Elementary respects the threading configuration in your dbt profile. Ensure you have an appropriate thread count set (e.g.,
threads: 8
) in your
profiles.yml
. [community thread] Recommended starting configuration for production:
Copy code
# dbt_project.yml vars:   disable_dbt_artifacts_autoupload: true   columns_upload_strategy: none
Then trigger the artifact upload separately in your Dagster pipeline after PR merges or schema changes. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai on 0.25.1, is there any supported way to reduce the artifact models'
post_hook
build cost, given
disable_dbt_artifacts_autoupload
only gates the on-run-end path and
columns_upload_strategy
doesn't gate the post-hook either?
k
I'm sorry, but the knowledge sources do not contain enough information to answer this question confidently. The knowledge sources cover: •
disable_dbt_artifacts_autoupload
— gates the on-run-end hook metadata upload path •
columns_upload_strategy: none
/
disable_dbt_columns_autoupload
— gates the on-run-end hook columns upload path •
+enabled: false
on the
edr
block — disables the models entirely, but as confirmed by Elementary support, this causes the hooks to skip uploads only if tables don't exist, and prevents manual runs too [disable vars vs edr enabled] None of the knowledge sources specifically address version 0.25.1, nor do they discuss a supported mechanism to reduce the cost of
post_hook
logic that runs on the artifact models themselves (as opposed to the on-run-end hook). The distinction you're drawing — between the on-run-end path and the model-level
post_hook
— is not addressed in the available documentation or community threads. I'd recommend: 1. Raising this directly in the #C02CTC89LAX where Elementary engineers are active, or 2. Opening a GitHub issue on the Elementary Data repository referencing version 0.25.1 specifically. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai is there a supported way to gate the artifact models'
post_hook
upload cost?
On our ~3,558-model / 5,574-test Snowflake project,
dbt_columns
alone takes ~22 min on a cold build. I've traced the cost to the model-level
post_hook
, which appears not gated by
disable_dbt_artifacts_autoupload
or
columns_upload_strategy
— those only gate the
on_run_end
path. Snippets from the installed package: 1.
models/edr/dbt_artifacts/dbt_columns.sql
— the model runs
upload_dbt_columns()
as a
post_hook
, so it fires whenever the model builds:
Copy code
{{
    config(
        materialized="incremental",
        post_hook="{{ elementary.upload_dbt_columns() }}",
        ...
    )
}}
2.
macros/edr/dbt_artifacts/upload_dbt_columns.sql
— the post_hook body. Its only guard is `if execute and relation`; it does not check
disable_dbt_artifacts_autoupload
,
columns_upload_strategy
, or any disable var, and it walks the full `graph.nodes`/`graph.sources`:
Copy code
{%- macro upload_dbt_columns(should_commit=false, metadata_hashes=none) -%}
    {% set relation = elementary.get_elementary_relation("dbt_columns") %}
    {% if execute and relation %}
        {% set tables = elementary.filter_to_current_project_if_needed(graph.nodes.values())
                      + elementary.filter_to_current_project_if_needed(graph.sources.values()) %}
        {% do elementary.upload_artifacts_to_table(
            relation, tables, elementary.flatten_table_columns,
            should_commit=should_commit, metadata_hashes=metadata_hashes,
        ) %}
    {%- endif -%}
    {{- return("") -}}
{%- endmacro -%}
3.
macros/edr/system/hooks/on_run_end.sql
— confirms
disable_dbt_artifacts_autoupload
gates only the
on_run_end
upload, a separate path from the model post_hook above:
Copy code
{% if not elementary.get_config_var("disable_dbt_artifacts_autoupload") %}
    {% do elementary.upload_dbt_artifacts() %}
{% endif %}
Questions: 1. Is there a supported config to skip/limit the*model `post_hook`*upload (not just the on_run_end path) in 0.25.1? 2. We can't set`+enabled: false`on`dbt_columns`because`dbt_artifacts_hashes`depends on it (parse error). Is there a supported way to disable columns collection without breaking that dependency? 3. If neither exists, is incremental-only (warm metadata-hash cache; never`--full-refresh`) the intended mitigation at this scale? _(Note: a prior answer suggested
disable_dbt_columns_autoupload
— that var does not exist in 0.25.1's
get_config_var
defaults, so please disregard it unless it was added in a later release.)_
k
The knowledge sources do not contain enough information to answer your specific questions about version 0.25.1 with confidence. Your analysis is technically precise and goes beyond what the available documentation and community threads cover. Here is what I can and cannot confirm: What the knowledge sources do confirm Your code-level finding is consistent with community reports: users have repeatedly observed that
disable_dbt_artifacts_autoupload
and
columns_upload_strategy: none
do not fully suppress the
dbt_columns
build cost
, particularly during
dbt run --select state:modified+
or full-refresh deploys. [Slack thread] [GitHub issue] The only workarounds that community members confirmed actually prevent the model from running are: 1. *Explicit exclusion at the CLI level:*dbt run --exclude dbt_columns[Slack thread] 2. Disabling the model in
dbt_project.yml
— but as you've already identified, this breaks
dbt_artifacts_hashes
with a parse/compilation error, and the knowledge sources do not document a supported workaround for that dependency. [Slack thread] What I cannot confirm from the knowledge sources 1. Q1 (gate the model
post_hook
in 0.25.1):
No knowledge source documents a supported var or config that gates the
upload_dbt_columns()
post-hook itself in 0.25.1. Your reading of the macro source appears consistent with the bug reports in the GitHub issue. [GitHub issue] 2. Q2 (disable columns without breaking
dbt_artifacts_hashes
):
No knowledge source documents a supported solution to this dependency conflict in 0.25.1. 3. Q3 (warm cache as intended mitigation): The knowledge sources confirm that the metadata hash cache (dbt 1.4.0+) is intended to make subsequent runs faster, but no source explicitly states this is the intended mitigation at your scale (~3.5K models), nor does any source quantify expected warm-cache performance at that size. [community thread] Recommendation Given the specificity of your version and scale, I'd strongly recommend: • Opening a GitHub issue on elementary-data/elementary referencing 0.25.1, the
upload_dbt_columns
post-hook gap, and the
dbt_artifacts_hashes
dependency constraint — your macro-level analysis would make this a high-quality bug/feature report. • Posting in the Elementary Slack (
#troubleshooting
) where Elementary engineers have engaged directly on similar
dbt_columns
performance threads. [#C02CTC89LAX] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Do you have any native integration support for dagster cloud?
k
The knowledge sources do not explicitly mention a native Dagster Cloud integration. What they do confirm is: • Dagster is listed as a supported orchestrator value for the
orchestrator
var/env var, meaning Elementary can collect job metadata from Dagster runs. [Collect Jobs Info] • Dagster is listed as a supported orchestrator for the Python SDK integration. [Python SDK Usage] • However, unlike dbt Cloud, GitHub Actions, and Airflow, Dagster does not have any default environment variables wired automatically — you would need to set all job metadata fields manually via env vars or dbt vars. [Collect Jobs Info] • The Elementary integrations page lists Airflow as the only named orchestrator integration beyond dbt Cloud, with no dedicated Dagster Cloud page. [Elementary Integrations] For a definitive answer on whether a deeper native Dagster Cloud integration exists or is planned, I'd recommend checking directly with the Elementary team via their #C02CTC89LAX or the integrations request form. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai On elementary 0.25.1, when a PR modifies
dbt_project.yml
or a macro,
state:modified
selects the whole project — which pulls in all of Elementary's artifact models too, and the
on-run-end
hooks fire. Is there a recommended pattern to exclude Elementary's models from
state:modified
PR-validation builds
so they don't rebuild on unrelated config changes — while still keeping them in scheduled/prod runs? (We currently use `--exclude dbt_columns`; is there a broader supported approach — e.g. a selector to carve Elementary out of CI selection?)
k
Yes, there is a well-documented and broadly supported pattern for exactly this. The knowledge sources confirm several approaches, from simplest to most robust: Recommended: Exclude Elementary from CI builds entirely The most direct and widely used approach is to add
--exclude package:elementary
(or
--exclude elementary
) to your PR/CI build command:
Copy code
dbt build --select state:modified+ --exclude package:elementary
This is explicitly recommended for PR runs to prevent Elementary artifact models from rebuilding on unrelated changes. [Slack – exclude elementary] [micro-batch example] This is broader than your current
--exclude dbt_columns
and will carve out all Elementary models from the
state:modified+
selection. Complementary: Disable Elementary models by default in dbt_project.yml If you want a
dbt_project.yml
-level guard rather than relying solely on CLI flags, scope Elementary models to production targets only:
Copy code
# dbt_project.yml models:   elementary:     +schema: "elementary"     +enabled: "{{ target.name == 'prod' }}"
Or with a variable for more explicit control:
Copy code
models:   elementary:     +schema: elementary     edr:       +enabled: "{{ var('enable_elementary_models', false) }}"
Then in prod/scheduled runs:
Copy code
dbt run --select elementary --vars '{"enable_elementary_models": true}'
[OSS FAQ] [Slack – disable via var] > ⚠️ Note: disabling the entire package with
+enabled: false
will also prevent Elementary tests from running. If you need Elementary tests in CI, use the hook disablement vars instead (see below). Keep hooks quiet in CI without disabling tests If you want Elementary tests to still run in CI but don't want the artifact upload overhead, use the disablement vars scoped to non-prod targets:
Copy code
vars:   disable_dbt_artifacts_autoupload: "{{ target.name != 'prod' }}"   disable_run_results: "{{ target.name != 'prod' }}"   disable_tests_results: "{{ target.name != 'prod' }}"   disable_dbt_invocation_autoupload: "{{ target.name != 'prod' }}"
[reduce on-run-end time] [data-tests docs] Summary The
--exclude package:elementary
CLI flag is the most direct answer to your question and is the pattern the community consistently lands on for PR validation builds. [OSS FAQ] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help., with interactive elements
g
@kapa.ai Regarding the approaches in the summary table: I tested
+enabled: "{{ target.name == 'prod' }}"
but rejected in favor of
+enabled: "{{ var('elementary_enabled', false) }}"
instead. Should I reconsider?
k
Both approaches are documented and used in the community, and your preference for the
var()
-based approach is well-founded. Here is what the knowledge sources confirm about the trade-offs: target.name == 'prod' — implicit, convention-dependent
Copy code
+enabled: "{{ target.name == 'prod' }}"
• Works automatically based on the dbt target name — no extra CLI flags needed. • Brittle if your target naming is inconsistent across environments or teams (e.g.
production
,
prod-eu
, etc.). • Cannot be overridden at runtime without changing the target name. [OSS FAQ] [Slack – micro-batch] var('elementary_enabled', false) — explicit, override-friendly
Copy code
+enabled: "{{ var('elementary_enabled', false) }}"
• Defaults to
false
everywhere — Elementary models never run unless explicitly opted in. • Allows runtime override via
--vars
, which is useful in Dagster where you can inject vars per-job. • One community member specifically combined both approaches to get the best of both:
Copy code
+enabled: "{{ target.name == 'prod' and var('enable_elementary', true) }}"
This enables Elementary in prod by default, but still allows an explicit
--vars "enable_elementary: false"
override when needed (e.g. to skip Elementary on a specific prod run). [Slack – combined approach] Should you reconsider? The knowledge sources do not suggest you should revert to the
target.name
-only approach. Given your Dagster/CI context where you want explicit, per-job control, the
var()
-based approach is arguably better suited. The combined pattern above may be worth considering if you want prod-by-default behaviour with an escape hatch — but the knowledge sources do not contain enough detail about your specific Dagster job configuration to recommend one definitively over the other. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Re: the hook-disablement vars scoped to target (
disable_run_results: "{{ target.name != 'prod' }}"
, etc.) — this pattern is broken on 0.25.1 and fails silently.
Setup: elementary 0.25.1, dbt-core 1.10.15, dbt-snowflake. We tried the documented CI pattern to disable hooks in non-prod:
Copy code
vars:
  disable_run_results: "{{ target.name not in ['production','cleanroom'] }}"
  disable_tests_results: "{{ target.name not in ['production','cleanroom'] }}"
  disable_dbt_invocation_autoupload: "{{ target.name not in ['production','cleanroom'] }}"
Intent: keep run/test-result uploads enabled in our monitored targets (production, cleanroom), disabled elsewhere. The bug: the
"{{ ... }}"
expression renders to the string
"False"
, not the boolean
False
, and
get_config_var
doesn't coerce it. Because a non-empty string is truthy,
{% if not elementary.get_config_var("disable_run_results") %}
in
on_run_end
evaluates
not "False"
→
not True
→ False, so the upload is skipped. Evidence: Elementary's own
Runtime data
log line showed the values as quoted strings:
Copy code
"config": {"disable_run_results": "False", "disable_tests_results": "False", "disable_dbt_invocation_autoupload": "False"}
Result: on cleanroom — which we wanted monitored — run-results / test-results / invocation capture was silently disabled, the exact opposite of the config's intent. No error was raised; we only caught it by reading the runtime-data log. Contrast:
+enabled: "{{ ... }}"
works correctly because dbt native-renders the
enabled
config to a real boolean. These
disable_*
vars consumed via
get_config_var
do not get that coercion, so a Jinja expression stays a string. Questions: 1. On 0.25.1, is`get_config_var`expected to return the raw rendered string for these`disable_*`vars? If so, the documented`"{{ target.name != 'prod' }}"`pattern silently misbehaves — should the docs use a form that yields a real bool, or should`get_config_var`coerce`"true"`/`"false"`strings? 2. What's the supported way to make these target-conditional so the resolved value is a genuine boolean (not a truthy string)? Did I overlook anything with my implementation of the hook disablement ?
k
Your diagnosis is consistent with a known, documented issue in Elementary's history. Here is what the knowledge sources confirm: This is a known bug, not user error This exact failure mode — Jinja expressions in
disable_*
vars rendering as strings rather than booleans, causing
get_config_var
to evaluate a non-empty string as truthy — was first reported and hotfixed in 2022 (package version 0.6.4). The Elementary team's own explanation at the time: > "If you were using any of the disablement vars with a Jinja expression (most notably
target.name != prod
) rather than
true
or
false
, up until now, it would've always been disabled regardless of the expression."
[Elementary hotfix – 0.6.4] The fact that you are hitting the same class of bug on 0.25.1 — with the string
"False"
being treated as truthy — suggests the coercion issue has either regressed or was never fully resolved for all code paths in
get_config_var
. Q1: Is this expected behaviour in 0.25.1? The knowledge sources do not contain enough information to confirm whether
get_config_var
is intentionally returning raw rendered strings in 0.25.1, or whether this is a regression. However, the 2022 hotfix confirms that Elementary is aware this class of bug exists and has fixed it before. Your runtime-data log evidence (
"disable_run_results": "False"
as a quoted string) is exactly the kind of evidence that would constitute a valid bug report. Q2: Workarounds that yield a genuine boolean The knowledge sources document two forms that have been confirmed to work around this class of issue: Option A —
| as_bool
filter (community-validated workaround):
Copy code
vars:   disable_run_results: "{{ (target.name not in ['production','cleanroom']) | as_bool }}"   disable_tests_results: "{{ (target.name not in ['production','cleanroom']) | as_bool }}"   disable_dbt_invocation_autoupload: "{{ (target.name not in ['production','cleanroom']) | as_bool }}"
This was the form validated in the 0.6.4 hotfix. [Elementary hotfix – 0.6.4] > ⚠️ However, some community members on later versions reported that
| as_bool
itself triggered type evaluation issues in certain dbt versions. [Slack – as_bool caveat] Option B — hardcoded booleans per environment (most reliable): Rather than relying on Jinja expression coercion in
dbt_project.yml
, pass explicit booleans via
--vars
in your Dagster job definitions per target:
Copy code
# For production/cleanroom jobs — hooks enabled (default, no override needed) dbt run  # For CI/dev jobs — hooks explicitly disabled dbt run --vars '{"disable_run_results": true, "disable_tests_results": true, "disable_dbt_invocation_autoupload": true}'
[CLI vars approach] This avoids the string-coercion problem entirely since
true
passed via
--vars
is a native YAML boolean, not a rendered Jinja string. Given your Dagster setup, this is arguably the most robust approach — each Dagster job op can inject the correct
--vars
explicitly. Summary I'd strongly recommend filing a bug report against 0.25.1 on elementary-data/elementary with your runtime-data log evidence — the string
"False"
being returned by
get_config_var
for a documented pattern is a clear regression from the 0.6.4 fix. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help., with interactive elements
g
@kapa.ai I've added
state:modified.macros+ --exclude
to our deployment template and it does not stop the
state:modified.macros+
fan-out that a project-config change triggers across our 9,500+ models: """ template: ../templates/dbt-command.yml parameters: target: cleanroom command: build ## we want warnings to throw errors # --exclude package:elementary keeps Elementary's observability models out of # PR validation: they should only build in their scheduled run, not rebuild on # unrelated dbt_project.yml/macro changes that fan state:modified out to everything. selection: state:modified.body+ state:modified.relation+ state:modified.macros+ --exclude package:elementary --defer --state $(Pipeline.Workspace) """
k
The knowledge sources do not contain enough information to answer this question confidently. Your specific use of
state:modified.body+
,
state:modified.relation+
, and
state:modified.macros+
as separate granular selectors (rather than the simpler
state:modified+
) goes beyond what the Elementary documentation and community threads cover. What the knowledge sources do confirm The
--exclude package:elementary
flag is the documented and community-validated way to carve Elementary out of a
state:modified+
selection: [Slack – exclude elementary]
Copy code
dbt build --select state:modified+ --exclude package:elementary
However, the knowledge sources only ever show this pattern used against the simple
state:modified+
selector
, not against the granular
state:modified.body+
,
state:modified.relation+
,
state:modified.macros+
combination you are using. What I cannot confirm The knowledge sources do not address: 1. Whether
--exclude package:elementary
correctly suppresses fan-out when
state:modified.macros+
is one of multiple space-separated selectors in a single
--select
expression. 2. Whether dbt's selector evaluation order or union logic causes
--exclude
to be applied differently when multiple
state:modified.*
variants are combined. 3. Whether the fan-out you are seeing is a dbt Core selector behaviour issue (unrelated to Elementary) or an Elementary-specific problem. Suggested next steps Given the complexity here, the most appropriate resources would be: • dbt Core selector docs / GitHub issues — the fan-out behaviour of
state:modified.macros+
across 9,500+ models when
dbt_project.yml
changes is a dbt Core question, not an Elementary one. • Elementary Slack (#C02CTC89LAX) — to confirm whether
--exclude package:elementary
is expected to work correctly in a multi-selector
--select
expression on 0.25.1. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai dbt 1.10.15, dbt-snowflake 1.11.0a1, elementary 0.25.1, Snowflake. Installing the elementary package took our project from 916 to 2014 macros. On the PR that adds it, our CI selection expanded from a handful of nodes to 9,696 — essentially every node in the project (3,695 models, 5,756 tests): dbt build --select state:modified.body+ state:modified.relation+ state:modified.macros+ --exclude package:elementary --defer --state <prod_manifest> --full-refresh The PR touches no model SQL. --exclude package:elementary works (no elementary models built), but the whole existing graph gets selected and full-refreshed, so the job times out. Our dbt_project.yml applies project-wide pre-hook and post-hook calling custom macros, so those macros are in every node's dependency chain. 1. Is state:modified.macros fanning out to the entire graph an expected consequence of installing the package? 2. If so, is it one-time on install, or does it recur on every elementary version bump? 3. What do you recommend for teams whose CI relies on state:modified selection? Is there a supported way to install the package without invalidating state comparison for existing nodes?
k
The knowledge sources do not contain enough information to answer your three questions confidently for this specific scenario. Here is what I can and cannot confirm: What the knowledge sources do confirm • Installing the Elementary package adds a large number of macros to your project. The knowledge sources confirm that
state:modified.macros+
fans out to all nodes whose dependency chain includes a modified macro — and since your
dbt_project.yml
applies project-wide pre/post hooks calling custom macros, every node is downstream of those macros. [Slack – state:modified fan-out] •
--exclude package:elementary
correctly excludes Elementary's own models from the selection, which the knowledge sources confirm works as expected. [Slack – exclude elementary] • The knowledge sources do not address whether the fan-out from macro addition is one-time or recurs on version bumps, nor do they document a supported install pattern that avoids
state:modified.macros+
invalidation. What I cannot confirm 1. Q1 (expected behaviour?): The knowledge sources do not explicitly confirm whether the full-graph fan-out from adding ~1,098 macros via Elementary install is expected
state:modified.macros+
behaviour, or whether it is a dbt Core selector behaviour that Elementary is simply subject to. 2. Q2 (one-time vs. recurring?): The knowledge sources do not address whether subsequent Elementary version bumps would trigger the same fan-out. Given that version bumps can add or modify macros, it is plausible — but I cannot confirm this from the available sources. 3. Q3 (supported install pattern?): No knowledge source documents a supported workaround for the install-time
state:modified.macros+
invalidation problem specifically. Practical mitigations the knowledge sources do support For the install PR specifically, the only confirmed approach is to bypass
state:modified.macros+
entirely for that one PR:
Copy code
# Drop state:modified.macros+ for the install PR only
dbt build \
  --select state:modified.body+ state:modified.relation+ \
  --exclude package:elementary \
  --defer --state <prod_manifest>
This avoids the macro fan-out while still catching body/relation changes. The trade-off is that macro-dependent changes are not validated on that PR — acceptable for a PR that touches no model SQL. [Slack – granular selectors] Recommended next steps These questions — particularly Q1 and Q3 — span both dbt Core selector behaviour and Elementary package design, so I'd recommend raising them in two places: • dbt Core GitHub / Slack — for whether
state:modified.macros+
fan-out on package install is expected and whether there is a selector-level mitigation. • Elementary Slack (#C02CTC89LAX) — for whether Elementary has a recommended CI onboarding pattern for teams using granular
state:modified.*
selectors, and whether version bumps are expected to retrigger the same fan-out. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Is the unqualified global `run_query`override intentional, and is there a supported install that doesn't shadow dbt's built-in? A namespaced macro upstream would fix this for everyone, and it's worth an issue on their repo regardless of what the bot says.
k
Thinking completed I'm sorry, but the knowledge sources do not explicitly confirm whether shadowing or overriding dbt's global
run_query
macro is intentional, nor do they document an alternative installation method designed to avoid macro namespace collisions. Here is what the knowledge sources do explain regarding Elementary's macro design and overrides: Macro Namespacing and Overrides in Elementary • Design philosophy: Elementary generally prefixes and namespaces its internal macros (calling them as
elementary.<macro_name>
or prefixing them with
edr_
) specifically to avoid colliding with or accidentally overriding user and third-party package macros [Slack forum discussion; Slack package macros]. • Where Elementary intentionally overrides dbt built-ins: Elementary explicitly overrides dbt's built-in
test
materialization to support observability features such as capturing failed row counts and samples [dbt test materialization]. •
run_query
context:
Community discussions and error stack traces show that Elementary defines an internal
run_query
wrapper (e.g.,
macros/utils/run_queries/run_query.sql
) [Snowflake edr report error], and PRs show shifts toward helpers like
elementary.execute_no_fetch
[execute INSERTs PR]. However, the sources do not discuss whether defining
run_query
globally without an
edr_
prefix or namespace was an intentional architectural choice or an unintended collision with dbt's built-in macro dispatch. Is There a Supported Install That Avoids It? The knowledge sources do not provide any configuration flag, package installation setting, or alternate package distribution to prevent package-level macro declarations from being registered by dbt. Recommended Action Because shadowing dbt Core's global built-in macros directly affects package macro resolution and dependency trees (such as triggering
state:modified.macros+
graph invalidation), opening an issue on the Elementary GitHub repository is the recommended path to request namespacing or clarification from the maintainers. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai should the Elementary collection tables run once before uploads are turned on, or should our production pipeline run a build+upload for each run with each deployment?
k
Thinking completed The recommended practice is to run the Elementary collection models once during initial setup (and again only on upgrades), rather than building them on every production pipeline run [Slack forum user question; Slack forum user question]. Here is how the workflow is designed to work: 1. Initial Setup and Upgrades Only You only need to explicitly build the Elementary models (
dbt run --select elementary
): • Once on initial deployment to create the tables, views, and schemas in your warehouse [Slack forum user question; Slack forum user question]. • When upgrading to a new minor version of the package to apply schema changes or migrations [Slack forum user question; Slack forum user question]. 2. Regular Production Runs In your day-to-day production runs: • Do not run the Elementary models. Running them repeatedly is harmless (and safe from data loss), but it is unnecessary and consumes extra warehouse resources and build time [Slack forum user question; Slack forum user question]. • Let the hooks handle uploads. The
on-run-end
hooks automatically capture and upload your test results, run results, and invocations directly into the existing Elementary tables on every
dbt run
or
dbt build
, even if the Elementary models are excluded from the run selection [Slack forum user question; Slack forum user question]. Recommended Pipeline Pattern • Deployment / Release step: Run
dbt run --select elementary
once when deploying new package versions. • Scheduled production runs: Run your standard dbt command while excluding the Elementary models, for example:dbt build --exclude package:elementaryThis keeps runtime minimized while still allowing the
on-run-end
hooks to record data health and execution results [Slack forum user question]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai We're enabling Elementary collection on a dbt-Snowflake project after installing it inert (all
disable_*_autoupload
/
disable_run_results
/
disable_tests_results
/
disable_freshness_results
vars set to true, alerts off). We want run-results, model-results, and invocation collection on for our production deploy only — not for local developer runs or CI pull-request validation, which run against the same dbt project. Two questions: 1. Scoping which invocations upload. The
disable_*
vars are currently project-wide defaults in
dbt_project.yml
. If we flip those defaults to
false
, does every invocation's
on-run-end
hook attempt an upload — including local
dbt build
and CI runs — into whatever target that invocation is pointed at? And is the recommended way to scope collection to production only to leave the defaults disabled and pass
--vars '{disable_run_results: false, ...}'
on just the production command
, rather than changing the defaults? Or is there a built-in mechanism (a target-name check, an
edr
-specific flag) you'd recommend instead of per-invocation
--vars
? 2. First-upload ordering. We plan to build the Elementary models once (
dbt run --select elementary
, excluding the heavy
dbt_columns
model) and thereafter let the hooks upload while excluding the package from normal runs. If an
on-run-end
upload fires before those tables have ever been built — i.e. we enable uploads before the one-time build — what happens? Does the hook create the tables on demand, no-op gracefully, or error the run? We want to know whether the one-time build must strictly precede the first upload-enabled run, or whether ordering is forgiving. Also: is excluding
dbt_columns
from the one-time build safe, or do other Elementary models or the upload macros depend on it existing?
k
Thinking completed 1. Scoping Which Invocations Upload Does flipping the defaults to false make every invocation attempt an upload? Yes. If you set the
disable_*
variables to
false
globally in
dbt_project.yml
, the
on-run-end
hook will fire on every
dbt run
,
dbt test
, and
dbt build
command across all environments (including local and CI) and attempt to write into the target schema configured for that execution [Elementary dbt package on-run-end hooks; Slack forum user question]. Recommended pattern: --vars vs. target checks Both approaches exist in the documentation and community, but passing explicit booleans via
--vars
is the safest option in your setup: 1. Explicit
--vars
on production commands (Most reliable):
Leaving the default vars set to
true
in
dbt_project.yml
and explicitly overriding them in production:dbt build --vars '{"disable_run_results": false, "disable_tests_results": false, "disable_dbt_invocation_autoupload": false}'This completely avoids Jinja type-coercion issues where expressions like
"{{ target.name != 'prod' }}"
evaluate to string
"False"
(which evaluates as truthy) and silently disable uploads [Can I disable the on-run-end hooks?; Slack forum user question]. 2. Target-based package disablement (
models.elementary.+enabled
):
Elementary provides a built-in dbt config pattern to disable the models and hooks outside prodmodels elementary: +schema: "elementary" +enabled: "{{ target.name in ['prod', 'cleanroom'] }}"Because dbt's model configuration natively evaluates
+enabled
to a real boolean, the hooks will simply not run in non-production environments [FAQ; Slack forum user question]. Caveat: If you completely disable the package with
+enabled: false
, Elementary tests cannot run in local/CI runs either [FAQ]. 2. First-Upload Ordering and Excluding dbt_columns What happens if the on-run-end upload fires before the one-time build? The one-time build must strictly precede the first upload-enabled run. The hook does not create the tables on demand. The Elementary models must exist as physical relations in the target schema first [Slack forum user question; Slack forum user question]. If the tables do not exist when the hooks fire, the hooks will either fail with database errors or fail to record results, leaving the target tables missing or empty [Slack forum user question; Slack forum user question]. You should execute the initial build first:
Copy code
dbt run --select elementary --exclude dbt_columns
Is excluding dbt_columns from the one-time build safe? • CLI exclusion (
--exclude dbt_columns
):
Yes, this is safe and widely used. The community and support staff specifically recommend running
dbt run --select elementary --exclude dbt_columns
to work around memory limits, long execution times, or warehouse query-size limits [Slack forum user question; Slack forum user question]. Excluding it via the CLI does not break compilation of other models. • Config-level disablement (
+enabled: false
on
dbt_columns
):
Do not use this. Setting
+enabled: false
directly on
dbt_columns
in
dbt_project.yml
causes a compilation error because
dbt_artifacts_hashes
references
dbt_columns
[Slack forum user question; Slack forum user question]. Always use the CLI flag
--exclude dbt_columns
. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai We installed Elementary on a dbt-Snowflake project and are doing the one-time model build before enabling
on-run-end
uploads. We tried to skip the heavy
dbt_columns
model to save build time:
dbt run --select elementary --exclude dbt_columns
. It failed —
dbt_artifacts_hashes
unions across
dbt_columns
(among the other artifact models), so with
dbt_columns
excluded,
dbt_artifacts_hashes
errors with
Object '...ELEMENTARY.DBT_COLUMNS' does not exist
. 30 of 31 models built; only
dbt_artifacts_hashes
failed. We then considered also excluding
dbt_artifacts_hashes
, but found that
upload_dbt_artifacts
does
get_elementary_relation("dbt_artifacts_hashes")
and returns early (uploads nothing) if that relation is absent. So excluding it appears to silently disable the entire dbt-artifacts upload channel, while leaving run-results and invocation uploads working. Questions: 1. Is there a supported way to run Elementary's collection without materializing
dbt_columns
— given
dbt_artifacts_hashes
depends on it and the artifacts upload depends on
dbt_artifacts_hashes
? Is
dbt_columns
effectively mandatory if we want
disable_dbt_artifacts_autoupload: false
to actually upload model/source/schema metadata? 2. If
dbt_columns
must be built for full artifact collection, is its cost a one-time setup cost or recurring?
Our understanding is the model is built once at setup (and on package upgrades), and thereafter the
on-run-end
hooks upload into the existing tables without rebuilding models. Is that correct — i.e. we pay `dbt_columns`' build time once, not on every production run? 3. What exactly is lost if we run run-results and invocation uploads but never build
dbt_columns
/
dbt_artifacts_hashes
?
Which Elementary features or tables (schema-change detection, `dbt_models`/`dbt_sources` metadata, the report/UI) stop working, versus which keep working on run-results alone? 4. Is
dbt_columns
itself an incremental model that only processes new/changed columns after its first full build
, so its recurring cost (if any) is small even when it is included in periodic rebuilds?
k
Thinking completed 1. Is there a supported way to run Elementary collection without materializing dbt_columns? No,
dbt_columns
is effectively mandatory if you want
disable_dbt_artifacts_autoupload: false
to work.
Because
dbt_artifacts_hashes
is a view that directly unions metadata across the artifact models (including
dbt_columns
),
dbt_columns
must physically exist in the warehouse for
dbt_artifacts_hashes
to compile and query successfully [does anyone know whether it s possible to disable dbt column; Slack forum user question]. Furthermore,
upload_dbt_artifacts
relies on
dbt_artifacts_hashes
to check hashes and determine what has changed [artifacts hashes are used for what]. If
dbt_artifacts_hashes
does not exist or fails to query, the artifacts upload logic cannot execute [Slack forum user question]. There is currently no supported configuration or flag that decouples
dbt_artifacts_hashes
from
dbt_columns
while still keeping metadata artifact uploads active [Slack forum user question]. To avoid statement size and memory limits during that initial creation, configure chunking in `dbt_project.yml`:
Copy code
vars:
  insert_rows_method: chunk
  dbt_artifacts_chunk_size: 5000
[hello i m getting this error when elementary s p] 2. Is dbt_columns' build cost one-time or recurring? It is primarily a one-time setup cost (and on package upgrades), provided you follow recommended practices. • You only need to run the model directly (
dbt run --select elementary
) once on initial deployment or when upgrading package versions [Elementary dbt Artifacts]. • In routine production runs, your dbt command should exclude Elementary models entirely (e.g.,
dbt build --exclude package:elementary
) [can you list me all flags and vars you know of a]. • During normal runs, models are not rebuilt. Instead, the
on-run-end
hooks handle uploading execution details. If you also set
columns_upload_strategy: none
or manage metadata uploads separately, you avoid repeating heavy column processing on routine pipeline runs [reduce on-run-end time; planning to implement Elementary in our d]. 3. What is lost if you run run-results/invocations without dbt_columns and dbt_artifacts_hashes? If
dbt_artifacts_hashes
is missing and metadata artifact uploads fail, your project metadata tables will not be populated [when the disable artifact autoupload is paused what tables views don t get updated; what happens if I don t update the artifacts]: • What continues to work: ◦
elementary_test_results
(test passes/failures and metrics) ◦
dbt_run_results
(model execution durations, statuses) ◦
dbt_invocations
(run times, environment, command-line arguments) These tables are independent append-only result tables populated by separate hook operations [when the disable artifact autoupload is paused what tables views don t get updated; integrating the Elementary dbt package into our Airflow-orchestrated dbt project]. • What stops working or breaks: ◦ Metadata tables will be empty or outdated:
dbt_models
,
dbt_tests
,
dbt_sources
,
dbt_exposures
,
dbt_metrics
, and
dbt_columns
[when the disable artifact autoupload is paused what tables views don t get updated]. ◦ Reports and UI Context: The Elementary UI and reports join execution results (
elementary_test_results
,
dbt_run_results
) with metadata tables (
dbt_models
,
dbt_tests
) to display model descriptions, owners, tags, and lineage. Without metadata tables, reports and alerts may be incomplete or fail to associate tests with their parent models [what happens if I don t update the artifacts]. ◦ Schema change monitors: Alerts or tests that rely on column metadata or schema tracking across runs will lack underlying column reference data [dbt_columns; what happens if I don t update the artifacts]. 4. Is dbt_columns incremental and fast on subsequent builds? Yes,
dbt_columns
is configured as an incremental model and uses hash caching.
• The model definition is materialized as
incremental
[cannot insert multiple commands into a prepared statement; Slack forum user question]. • It uses a
metadata_hash
column to detect state changes. On warm, subsequent runs where the project schema has not changed, Elementary skips unchanged artifacts, reducing execution time significantly compared to a cold/full-refresh build [planning to implement Elementary in our d; anyone having issues in CI after upgrading to the latest ver]. • Note: If you run with
--full-refresh
or use dynamic Jinja expressions (such as
now()
) in model configurations, the hash cache is invalidated, causing it to re-upload everything from scratch [planning to implement Elementary in our d]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai We're about to do the one-time cold build of Elementary's models on a large dbt-Snowflake project (thousands of models and sources), and expect
dbt_columns
to hit statement-size/memory limits without chunking. We plan to set:
vars:
insert_rows_method: chunk
dbt_artifacts_chunk_size: 5000
Our routine production runs exclude the Elementary package (
--exclude package:elementary
) and rely on the
on-run-end
hooks to upload; we only build the models on initial setup and on package upgrades. Question: should these two chunking vars live permanently in
dbt_project.yml
, or be passed as one-time
--vars
only on the setup/upgrade build?
Specifically:
Do
insert_rows_method
and
dbt_artifacts_chunk_size
affect anything on routine runs where Elementary models are excluded from the selection but the upload hooks still fire? I.e. do the hooks' own inserts (
dbt_run_results
,
dbt_invocations
) also honor these vars, such that setting them permanently changes routine-run behavior — for better or worse?
Is there any downside to leaving them permanently set — performance, correctness, or upload behavior?
Is
5000
a reasonable chunk size for a project of this scale, or is there a recommended value / way to tune it?
If we don't set them permanently, does a package upgrade's model rebuild reliably need them again — i.e. is the statement-size problem intrinsic to
dbt_columns
at this scale, so the failure would recur on every upgrade without them?
k
Thinking completed 1. Should chunking vars live permanently in dbt_project.yml or be passed via CLI --vars? They should live permanently in
dbt_project.yml
under the top-level
vars:
block.
[is there a way to chunk the metrics uploading to] According to Elementary support, setting chunking configurations via CLI flags (
--vars
) is unreliable because some sample and artifact collection occurs as part of test executions and internal package hooks rather than top-level CLI processing [is there a way to chunk the metrics uploading to]. Placing them under
vars:
in
dbt_project.yml
ensures that whenever inserts are executed, the package consistently reads and honors them [is there a way to chunk the metrics uploading to]. 2. Do they affect routine runs where models are excluded but upload hooks fire? Yes, the
on-run-end
upload hooks also honor these variables.
[please answer u08s0dle0kt s question i ve added some element; if i have the default vars in my dbt project yml]
insert_rows_method: chunk
and
dbt_artifacts_chunk_size
control the internal insert query generators that Elementary uses across both its model hooks and
on-run-end
hooks (such as inserting test results and run artifacts) [please answer u08s0dle0kt s question i ve added some element; if i have the default vars in my dbt project yml]. They only affect Elementary's own insertion logic into its observability tables—they do not alter normal dbt models or non-Elementary tests [if i have the default vars in my dbt project yml]. 3. Is there any downside to leaving them permanently set? • Correctness: There is no downside; the data written to the warehouse is identical [hi team looks like there is a miss in version 12 1 when the]. • Runtime/Overhead: Splitting a large upload into multiple separate
INSERT
statements introduces slight network and query-planning overhead compared to a single bulk insert [hello all are there any further details on the causes or fix; hi team looks like there is a miss in version 12 1 when the]. However, in routine runs with thousands of models or tests, attempting unchunked inserts often triggers warehouse expression limits, memory exhaustion, or compilation errors [hello all are there any further details on the causes or fix; hi team looks like there is a miss in version 12 1 when the]. Chunking keeps the memory footprint bounded and avoids hard query failures [hello all are there any further details on the causes or fix]. 4. Is 5000 a reasonable chunk size, or how should it be tuned? • Snowflake expression limit: Snowflake has a strict hard limit of at most 16,384 expressions in a single list or query [hi team looks like there is a miss in version 12 1 when the]. Because Elementary metadata inserts (especially column rows) contain multiple values per row, an unchunked batch of tens of thousands of rows reliably throws
maximum number of expressions in a list exceeded
[hi team looks like there is a miss in version 12 1 when the]. • Is 5,000 appropriate? Elementary maintainers explicitly recommend
5000
as a solid starting point for Snowflake to prevent hitting expression and statement limits [hi team looks like there is a miss in version 12 1 when the]. • Tuning: If you still observe SQL compilation errors, query size errors, or warehouse memory pressure during large test suites or cold builds, lower the size incrementally (e.g., to
1000
or
500
) [hi elementary support team we use the dbt cloud and found th; is there a way to chunk the metrics uploading to]. 5. If not set permanently, will package upgrades reliably fail? Yes, the statement-size problem is intrinsic to your project scale. [hi team looks like there is a miss in version 12 1 when the] Whenever Elementary models are rebuilt (during initial setup or package version upgrades),
dbt_columns
attempts to generate records across all models and sources in your graph [upload dbt columns post hook macro]. In a project with thousands of models and sources, this represents tens of thousands of column rows [hi team looks like there is a miss in version 12 1 when the]. Without chunking configured, Elementary defaults to inserting too many expressions in a single statement, re-triggering the failure on subsequent rebuilds [hi team looks like there is a miss in version 12 1 when the]. Keeping the configuration permanently in
dbt_project.yml
avoids recurring failures [hi team looks like there is a miss in version 12 1 when the]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai How is PII data managed in the
test_results
table?
k
Thinking completed In Elementary, raw row-level data and potential PII are not stored directly in
elementary_test_results
(which primarily contains test metadata, run status, and error counts); instead, raw failing row samples are stored in the dedicated
test_result_rows
table [test_result_rows docs; Linen thread]. Elementary manages and protects PII in test samples through several configuration options: 1. Automatic PII Protection via Tags You can instruct Elementary to automatically disable sample collection when a PII tag is detected by configuring
dbt_project.yml
[Test Result Samples]:
Copy code
vars:
  disable_samples_on_pii_tags: true   # Enable PII protection (default: false)
  pii_tags: ['pii', 'sensitive']      # Tags to treat as PII (default: ['pii'])
Tag evaluation is case-insensitive and can be applied at three levels [Test Result Samples]: • Model level: Tags on a model disable sample collection for all tests on that model. • Column level: Tags on a column disable samples for tests that reference that column. • Test level: Tags directly on a test disable sample collection for that specific test. • Directory level: Entire directories can be tagged in
dbt_project.yml
(e.g.,
+tags: ['pii']
). 2. Selective Sample Collection (show_sample_rows) As an alternative, you can invert the behavior so all test samples are hidden by default and only collected for explicitly tagged resources [Selective Samples]:
Copy code
vars:
  enable_samples_on_show_sample_rows_tags: true
  show_sample_rows_tags: ['show_sample_rows']
3. Disabling Sample Collection Globally or Per-Test • Globally: Set the sample count to
0
in
dbt_project.yml
to prevent collecting any raw row samples across the entire project [Test Result Samples]vars test_sample_row_count: 0 • Per-test: Disable sample collection for a specific test using the
disable_test_samples: true
or
test_sample_row_count: 0
meta configuration [Test Result Samples]models - name: user_profiles data_tests: - elementary.volume_anomalies: config: meta: disable_test_samples: true 4. Elementary Cloud Controls and Storage Isolation For Elementary Cloud users: • Environment-level disablement: The Elementary team can disable test sample syncing entirely for specific environments, ensuring no sample rows leave your data warehouse [Elementary Cloud Controls]. • Skip database storage: Samples can be stored only in your data lake (S3) and not loaded into the Elementary application database [Elementary Cloud Controls]. • US Storage: Customers can opt to store failed row sample S3 buckets in the US (
us-east-1
) rather than the default EU (
eu-central-1
) region [Samples storage in the US]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Can you provide me the source references for the "Enabling uploads only for the production invocation prevents local and CI runs from uploading data." guidance?
k
Thinking completed The guidance to limit or enable uploads only for production invocations (to prevent local and CI runs from uploading data) is documented across the following knowledge source references: • Dev/Prod Configuration Guide: Recommends disabling
on-run-end
upload hooks during local development and enabling them only for production/monitored environments to speed up workflows and prevent unwanted uploads [Dev/Prod Configuration]. • Control On-Run-End Hooks Guide: Explains how to limit hooks to production or specific targets (
target.name != 'prod'
) to avoid overhead, speed up local development, and reduce costs in non-production environments [Cloud Control Hooks; Data-tests Control Hooks]. • Reduce On-Run-End Hooks Time Guide (OSS): Details the available configuration variables (
disable_run_results
,
disable_tests_results
,
disable_dbt_artifacts_autoupload
,
disable_dbt_invocation_autoupload
) and cautions to only disable hooks for runs you do not want to monitor, such as local development [Reduce On-Run-End Time]. • Elementary on-run-end hooks documentation: Outlines disabling result and artifact model updates and confirms you can pass
--vars '{"disable_dbt_artifacts_autoupload": true}'
conditionally or via the command line for specific invocations [On-Run-End Hooks]. • Community Discussions: ◦ Discusses using
target.name
conditions or environment variables (
ENABLE_ELEMENTARY
) to disable models and hook uploads during local or non-production execution [Disable with Env Var; Toggle Elementary per Env]. ◦ Explains setting upload variables globally or per-target to prevent non-production runs from populating artifact and test tables [Dev/Prod Artifact Control; Global vs Target Upload Control]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai If we don't use snapshots, should/can we disable dbt_snapshots?
k
The knowledge sources do not explicitly address disabling
dbt_snapshots
specifically for projects that don't use snapshots. However, based on what the knowledge sources do confirm about disabling individual Elementary models, here is what applies: You can disable it via +enabled: false The knowledge sources confirm that individual Elementary artifact models can be disabled in
dbt_project.yml
using the standard dbt
+enabled
config [How to disable metadata tables]:
Copy code
models:
  elementary:
    edr:
      dbt_artifacts:
        dbt_snapshots:
          +enabled: false
Important caveats to check before doing so Before disabling
dbt_snapshots
, the knowledge sources highlight two risks that apply to any individual artifact model disablement: 1. Dependency on `dbt_artifacts_hashes`:
dbt_artifacts_hashes
unions across the artifact models. Disabling
dbt_columns
was confirmed to break
dbt_artifacts_hashes
with a compilation error because of this union dependency [Slack forum user question]. Whether
dbt_snapshots
is also referenced in that union is not confirmed in the knowledge sources — you should inspect your installed
dbt_artifacts_hashes
view definition before disabling it. 2. Hook behavior if the table is absent: If
dbt_snapshots
is referenced by any upload macro and the table does not exist, the hook may either error or silently skip uploads [difference between disable_dbt_artifacts_autoupload and edr enabled]. Safer alternative Rather than disabling the model entirely, the safer and more commonly recommended approach is to exclude it from builds via CLI while leaving it enabled in `dbt_project.yml`:
Copy code
dbt run --select elementary --exclude dbt_snapshots
This avoids any compilation or dependency issues while still preventing the model from being built unnecessarily. [How to disable metadata tables] I'd recommend verifying the
dbt_artifacts_hashes
dependency question directly with the Elementary team in their #C02CTC89LAX before committing to
+enabled: false
on
dbt_snapshots
. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Installed the Elementary library and let collections bake in for a few days for validation. Every production deploy is now about 5 minutes longer. Considering whether to disable dbt_artifacts_autoupload, but keep run results and invocations on every deploy, and upload artifacts only when the graph definition changes. What is the official recommendation to keep deployment time lower?
k
Thinking completed Your proposed approach matches Elementary's official recommendation for reducing
on-run-end
deployment duration. 1. Disable Metadata Artifact Auto-Uploads Metadata artifacts (
dbt_models
,
dbt_tests
,
dbt_sources
, etc.) only need to be uploaded when your project structure changes—not on every execution [Reduce On-Run-End Time; Control On-Run-End Hooks]. To prevent them from running on every deploy, set:
Copy code
# dbt_project.yml
vars:
  disable_dbt_artifacts_autoupload: true
[Reduce On-Run-End Time; Troubleshooting] This leaves your run results, test results, and invocations active on routine runs, which upload significantly faster [Reduce On-Run-End Time; Linen thread]. 2. Upload Artifacts Only When the Graph Changes After disabling auto-upload, refresh project metadata only when your project definition changes (e.g., during image build/deploy, after merging schema changes, or via a scheduled daily/hourly job) using:
Copy code
dbt run --select elementary.edr.dbt_artifacts
or:
Copy code
dbt run --select elementary --vars '{"enable_elementary_models": true}'
[Linen thread; Reduce On-Run-End Time] Running
elementary.edr.dbt_artifacts
explicitly updates only the metadata tables (like
dbt_models
,
dbt_tests
,
dbt_sources
) without re-running other package models [Linen thread]. Additional Official Strategies to Reduce Run Duration • Disable column auto-upload (often the biggest win): If you are not using Elementary Cloud's column-level features, the
dbt_columns
table can add substantial overhead to
on-run-end
. You can disable it withvars columns_upload_strategy: none[Troubleshooting; Planning stack thread] • Offload test table cleanup: If you run many tests, cleaning up temporary test tables during
on_run_end
can add notable time. You can disable it during runs and offload it to a scheduled operationvars clean_elementary_temp_tables: falseThen run the cleanup in a dedicated off-peak job:dbt run-operation elementary.cleanup_stale_test_tables[Disable test table cleanup] • Avoid dynamic expressions in model configs: Dynamic Jinja expressions like
now()
or
CURRENT_TIMESTAMP
invalidate the metadata hash cache on every run, forcing complete re-uploads [Planning stack thread]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai After further review, it's actually the
dbt_columns
run that that costs the most. *`dbt_columns`191 s*86,994 columns processed and compared, then 8 rows written. Any strategies for reducing or offsetting the deployment costs? If so, what are the trade-offs?
k
Thinking completed Here are the recommended strategies to eliminate or offset the execution cost of
dbt_columns
, along with the associated trade-offs: Strategy 1: Disable Column Metadata Collection Entirely (Recommended) The most effective and widely recommended strategy to cut
dbt_columns
runtime is to disable column metadata uploads [Linen thread; Planning stack thread]. Add the following to your `dbt_project.yml`:
Copy code
vars:
  columns_upload_strategy: none
[Linen thread; Linen thread] • How it helps: Stops Elementary from collecting and uploading column metadata to
dbt_columns
, eliminating the processing and comparison of your ~87,000 columns during
on-run-end
[Linen thread]. • Trade-offs: ◦ The
dbt_columns
table will not be populated or updated [Linen thread]. ◦ Features or tests that rely specifically on column-level catalog metadata (such as column metadata exploration in Elementary Cloud or automated schema change tests tracking column additions/removals) will not function or will show stale information [Linen thread; Linen thread]. ◦ Standard test results, model execution results, run durations, alerts, and the OSS UI/report will continue working as normal [Linen thread; Linen thread]. Strategy 2: Exclude dbt_columns from Builds and Decouple Deployments If you must retain column metadata in Elementary, do not run the model during normal deployment runs. 1. *Exclude it from routine CI/CD commands:*dbt build --exclude dbt_columns(or
--exclude package:elementary
so no Elementary models build during standard deploys) [Slack thread; Linen thread]. 2. Relegate execution to a separate, scheduled job: Run
dbt run --select dbt_columns
(or
dbt run --select elementary.edr.dbt_artifacts
) asynchronously during off-peak hours (e.g., once daily or after major schema merges) [Control On-Run-End Hooks]. • How it helps: Removes the 190+ second overhead completely from the critical deployment path. • Trade-offs: ◦ Column metadata will be slightly out-of-sync with production models until the asynchronous job runs. ◦ Important caveat: If
disable_dbt_artifacts_autoupload
is not set,
on-run-end
may still trigger column metadata extraction. Combining this with
columns_upload_strategy: none
or disabling metadata artifacts auto-upload is necessary to avoid the hook evaluating it [Planning stack thread; Slack thread]. Strategy 3: Check for Cache Invalidation Triggers Elementary relies on a metadata hash cache to compare columns and only write differences [Planning stack thread]. Even when only 8 rows are written, iterating through 87,000 column nodes in the dbt manifest in Python/Jinja consumes considerable time [Slack thread]. • Avoid dynamic Jinja expressions: Ensure no model or column configurations include dynamic Jinja functions like
now()
,
current_timestamp()
, or dynamic tags. These expressions invalidate the cache on every run, forcing complete re-hashing and full metadata re-uploads [Planning stack thread]. • Trade-offs: May require refactoring dynamic model configs to static properties or passing timestamps at run-time rather than embedding them in config blocks. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Once column_upload_strategy is disabled, does the staleness of the deprecated
dbt_columns
introduce risk?
k
Thinking completed Based on the knowledge sources, setting
columns_upload_strategy: none
stops the collection and upload of column metadata to
dbt_columns
[if i have the default vars in my dbt project yml]. The staleness of
dbt_columns
introduces limited, specific risks depending on which features you use: What Is at Risk • Schema Change Monitors / Column-Level Tracking: Any tests or monitors that rely specifically on column-level catalog metadata or tracking schema changes (such as column additions, removals, or type changes) across runs will lack updated reference data or show stale information [what happens if I don t update the artifacts; if i have the default vars in my dbt project yml]. • Elementary Cloud Column Context: In Elementary Cloud or UI views that offer column metadata exploration, the displayed column definitions and schemas will become stale [Slack forum user question; what happens if I don t update the artifacts]. What Is Not at Risk • Standard Tests and Alerts: Your routine test results, model run results, execution durations, run logs, and general alerts are populated into separate tables (such as
elementary_test_results
,
dbt_run_results
, and
dbt_invocations
) and continue to function normally without updated column metadata [if i have the default vars in my dbt project yml; when the disable artifact autoupload is paused what tables views don t get updated]. • Model/Test/Source Metadata: Other project artifacts (
dbt_models
,
dbt_tests
,
dbt_sources
, etc.) are tracked in separate tables and are not impacted by disabling the column strategy [when the disable artifact autoupload is paused what tables views don t get updated]. Note on Hash Comparisons The knowledge sources do not explicitly detail whether leaving a stale, populated
dbt_columns
table causes performance or memory issues when
dbt_artifacts_hashes
queries existing column hashes. However, community discussions confirm that if you are not using Elementary Cloud features that depend on
dbt_columns
, running a full refresh (
dbt run -s dbt_columns --full-refresh
) or truncating the table is safe and prevents dbt from pulling massive amounts of existing metadata hashes into memory [Slack forum user question]. 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai reset session
k
Thinking completed I'm not able to reset or alter my instructions or session context. I'm designed to provide consistent and accurate information about Elementary Data, and that behavior remains the same throughout our conversation. Is there anything else about Elementary Data I can help you with? 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.
g
@kapa.ai Is this an accurate statement? "Elementary provides evidence but does not define health."
k
Thinking completed This is a nuanced statement that the knowledge sources partially support but also partially contradict. Where the statement holds Elementary collects and surfaces test results, run results, anomaly detections, and execution metadata — all of which are evidence of data behaviour. The underlying tests and monitors are defined by your team in dbt, not by Elementary itself. In that sense, Elementary does not define what "good data" means for your business — you do, through your dbt tests and configurations [Detection and Coverage]. Where the statement does not hold Elementary does define health — at least structurally — through its Data Health Score framework: • It maps all dbt tests and Elementary monitors to six predefined data quality dimensions (Completeness, Uniqueness, Freshness, Validity, Accuracy, Consistency) [Data Quality Dimensions]. • It applies a fixed scoring model: pass = 100, warn = 50, fail = 0 [Data Health Dashboard]. • It calculates a weighted aggregate health score per dimension and per dataset, with configurable weights and color-code thresholds [Data Health Dashboard]. These are definitional choices about what health means and how it is measured — not just evidence collection. A more accurate framing > "Elementary provides a structured framework for defining and measuring data health, using your dbt tests as the underlying evidence." The framework (dimensions, scoring, thresholds) is Elementary's definition; the tests and their pass/fail outcomes are the evidence. Both are present. [Data Health Dashboard; Detection and Coverage] 👍 0 button 👎 0 button ℹ️ Tip: Mention @elementary.ai in the thread for follow-ups or DM the app for 1-to-1 help.