dbt consulting

dbt models your team will actually trust.

Senior dbt consulting inside your own repository. Contracted, unit-tested transformations on Snowflake and BigQuery, built so your analysts stop rebuilding logic and start trusting it. dbt Core, dbt Cloud, Snowflake, and BigQuery.

dbt logo
dbt Developer certification

dbt

Analytics engineering framework for tested SQL models.

Our expertise

We build, refactor, test, document, and review dbt projects.

Snowflake logo
SnowPro Core certification

Snowflake

Cloud data warehouse for analytics and data applications.

Our expertise

We design schemas, tune SQL, manage costs, and support Snowflake delivery.

BigQuery logo

BigQuery

Google Cloud warehouse for large-scale analytical workloads.

Our expertise

We model datasets, optimize queries, and connect BigQuery into pipelines.

AWS logo

AWS

Cloud platform for compute, storage, networking, and managed data services.

Our expertise

We work with AWS data infrastructure, deployment, integration, and operations.

Airflow logo

Airflow

Workflow orchestrator for scheduled data pipelines.

Our expertise

We build DAGs, stabilize retries, improve observability, and clean up operations.

We do not hand over strategy decks. We open pull requests your team can read, run, and own.

SnowPro Core certificationdbt Developer certification

Certified SnowPro Core and dbt Developer. Real dbt delivery on Snowflake and BigQuery for analytics teams.

Most teams feel this before they name it.

The pain shows up later, when the numbers stop being trusted and the bill keeps climbing.

No tests that mean anything

Models ship with unique and not_null and nothing else, so bad joins and broken assumptions reach dashboards silently.

No layering, just one file

A 400 line SQL file instead of staging, intermediate, and marts. Every change risks the whole warehouse.

Brittle runs

Pipelines break and nobody is sure why. Fixes become fire drills instead of planned, reviewed work.

Lineage nobody trusts

Documentation is missing, so analysts rebuild metric logic instead of reusing it. The same number drifts across teams.

A real fix, not a template.

fct_revenue had a silent double-count on refunds, and the only thing that caught it was a spreadsheet the day before close. The model below locks the grain in a contract, runs incrementally, and carries a unit test that asserts the revenue invariant. The reconciliation went from 2 days of spreadsheet work to 0.

Before

models/marts/fct_revenue.sql (before)
-- models/marts/fct_revenue.sql (before)
-- Grain: invoice_id. Source: raw.invoices joined to raw.refunds.
-- Tests: not_null(invoice_id), unique(invoice_id).
-- The reconciliation between fct_revenue and the GL runs in a
-- spreadsheet. The gap is "explained" by a footnote the day before
-- close. The dbt test suite does not catch the double-count.
select
  i.invoice_id,
  i.amount,
  r.refund_amount
from raw.invoices i
left join raw.refunds r using (invoice_id)

After

models/marts/fct_revenue.sql (after)
-- models/marts/fct_revenue.sql (after)
{{ config(
  materialized='incremental',
  incremental_strategy='merge',
  unique_key='invoice_id',
  contract={'enforced': True, 'grain': 'one row per invoice_id'},
  on_schema_change='append_new_columns',
  snowflake_warehouse='transforming_xs',
  tags=['finance', 'marts']
) }}

with invoices as (select * from {{ ref('stg_invoices') }}),
     refunds as (select * from {{ ref('stg_refunds') }})
select
  i.invoice_id,
  i.amount                                            as gross_revenue,
  coalesce(r.refund_amount, 0)                        as refund_amount,
  i.amount - coalesce(r.refund_amount, 0)             as net_revenue,
  i.updated_at
from invoices i
left join refunds r using (invoice_id)
{% if is_incremental() %}
  where i.updated_at > (select max(updated_at) from {{ this }})
{% endif %}

The test that catches it

tests/assert_revenue_balances.yml (the test that catches it)
# tests/assert_revenue_balances.yml
# The test that asserts the revenue invariant in CI.
# Before this, the only check was a spreadsheet the day before close.
unit_tests:
  - name: revenue_reconciles_to_gl
    model: fct_revenue
    given:
      input:
        - ref('stg_invoices')
        - ref('stg_refunds')
    expect:
      sum_revenue_invariant: sum(net_revenue) = sum(gross_revenue) - sum(refund_amount)
  • Sources through refs and staging models, not raw tables
  • Incremental merge, not a full daily refresh
  • A data contract locks the grain, not just the column types
  • A unit test asserts the business invariant, not not_null

The work, end to end.

From a clean setup to a health check, the work covers the parts that actually decide whether people trust the data.

dbt Core and dbt Cloud setup, with CI checks on every PR

Data contracts, generic tests, and unit-tested marts

Incremental models and materialization tuning for cost and speed

Snowflake and BigQuery implementations, including dbt Mesh where it pays off

Migrations from stored procedures or legacy SQL into dbt

dbt audits and health checks with a prioritized roadmap

Two ways to engage.

Pick the shape that fits the gap. Both put code in your repository or account, not a slide deck on a call.

Embedded delivery

A dbt Developer certified engineer embedded in your team: models, contracts, and pull requests in your repo, with daily async updates and a clear handoff.

Project delivery

A scoped dbt build with a clear start, end, and handoff: a migration, a cleanup, or an audit with a prioritized roadmap your team can run.

Analytics engineering support with dbt and Snowflake

We supported model development, refactoring, testing, and documentation on dbt and Snowflake for an analytics team. The result was faster delivery of analytics work and a more maintainable reporting foundation.

Private client, analytics team. Stack: dbt, Snowflake, SQL, Python, Git.

Built in the open.

Real tools and writing from the work, not just claims. Each one is something we actually shipped.

Answered, before the call.

Practical answers for teams scoping this kind of work. If your situation is not covered, the contact step is a short scoping call.

Scoped per engagement. Embedded delivery is billed monthly; project work is a fixed fee. The first step is a short scoping call.

Taking on new work

Let's talk about your data stack.

Share the stack, the blocker, and what needs to work better. We reply with a next step.