Build and scale the models
behind your business.

Your next report should start with a useful model already in place.

We refactor existing dbt™ projects and build new SQL models around the work your teams need to understand. Explicit grain, shared definitions, and traceable transformations give new analysis a dependable starting point.

Model the business,
layer by layer.

We separate source cleanup from business logic and reporting. Staging models standardize the inputs; intermediate models handle shared transformations; marts organize data for use.

Explicit grain and relationships keep joins from quietly changing what a number means.

5 source events2 completed work items15-minute mean duration
MODEL EXPLORER
mart.work_item_cycle2026-10-26 UTC

Count the work at the right grain.

One row per completed work item. Duration runs from the first accepted start to terminal completion.

Completed items · all timestamps UTC
Work itemStartedCompletedMinutes
W-10109:0009:1212
W-10209:0509:2318
Measure
(12 + 18) / 2 = 15 minutes
Exclusions
Open, canceled, missing-start or invalid-duration items
Owner role
Operations

Two work items, five source events. The event count is not the metric denominator.

Test the definition and its boundaries.

Model changes run through CI before release. Production data checks run separately as records arrive.

✓Unique work_item_id2 / 2
✓Relationships to source items2 / 2
✓Duration ≥ 0 minutes2 / 2
✓Duplicate event fixturepass
✓Out-of-order update fixturepass

We test the business rules and check source totals before a model change reaches your reports.

Follow the calculation to its sources.

Source cleanup, event resolution, and the reporting grain each have a distinct job.

source.events5 events · 2 work items
stg_work_eventsSource IDs · UTC timestamps
int_work_lifecycleResolve event order · calculate duration
work_item_cycle2 rows · one row per completed item
Snowflakedbt
One SQL definition, reused by its callersA Jinja macro packages a repeated calculation. Two reporting models call the same definition. Jinja macro{{ duration(start, end) }} Model AModel BShared SQL · tested in its models

Reuse SQL with Jinja macros.

We use Jinja macros to package repeated SQL with clear inputs, then test the models that call them. Shared datasets belong in shared models. New reports can build on established logic instead of another copy of the same calculation.

Update the selected partitionsExisting partitions remain in place while a selected update is applied. Update keys, late-arrival windows, and backfills define its scope. Existing partitions Selected update + backfill

Scale with incremental models.

Use incremental builds where a full rebuild adds little value. We define update keys, late-arrival windows, and backfill paths, then compare the results with a full build. We inspect query plans for repeated scans and expensive joins, and choose materializations to suit the workload.

Check a change before release and data after it arrivesCI checks keys, relationships, and boundary cases before model release. Production checks run separately against arriving records. CI · before release Unique keysValid relationshipsDuplicate + late-event cases Production · incoming data

Test the logic before release.

Tests for unique keys and valid relationships catch structural issues. Cases cover duplicate events, out-of-order updates, and invalid durations. Model changes run through CI before release; production checks keep validating the data as it arrives.

Keep a measure connected to its definitionThe work-item model carries its grain, calculation, and owner alongside its source lineage. work_item_cycleGrainCompleted itemMeasureMean minutesOwnerOperations SourceLogicMeasure

Make definitions part of the model.

A metric’s calculation, grain, exclusions, and owner belong alongside its code. We connect that documentation to lineage and review changes with the teams using the result.

Expose the fields the team needsReporting fields route to an authorized team. Restricted attributes remain behind warehouse permissions. Reporting fieldsitem_idduration_min Authorized team Restricted attributesWarehouse permissions

Control access at the right layer.

Reporting models should expose the fields each team needs. We exclude unnecessary personal data, separate restricted attributes, and apply permissions in the warehouse. Access rules become part of the model’s design and review, with ownership clear when requirements change.

What does your data need to do next?

Tell us what is changing, where the current system gets in the way, and what your team needs to decide.

Discuss your project