DocsGuides

Guides

Explain why a metric changed

4 min readReviewed July 2026

A dashboard tells you that a metric moved. A useful investigation explains which population changed, how much each segment contributed, and whether the movement represents customer behavior, system behavior, or broken data.

GraphJSON does not provide an automatic root-cause engine. Use its SQL notebook to build a reproducible decomposition, then validate the leading explanation against source systems and operational evidence.

This guide starts after you have detected a meaningful change. For detection methods, use Time-series baselines and anomaly detection.

Freeze the investigation contract#

Write the comparison before slicing the data:

metric: completed checkouts
grain: successful checkout event
current window: 2026-07-20 through 2026-07-26 UTC
baseline window: previous seven complete UTC days
entity: checkout
required maturity: 24 hours
exclusions: test accounts and internal traffic
candidate dimensions: plan, region, platform, release
owner: Growth Engineering

Use complete half-open intervals:

[current_start, current_end)
[baseline_start, baseline_end)

Do not compare a partial Monday with a complete prior Monday, a seven-day window with an eight-day window, or one period before its late events have had time to arrive.

Reproduce the top-line change#

Start with the smallest query that reproduces the dashboard:

WITH periods AS (
  SELECT
    if(
      timestamp >= toUnixTimestamp(toDateTime('2026-07-20 00:00:00')),
      'current',
      'baseline'
    ) AS period,
    count() AS value
  FROM product_events
  WHERE
    JSONExtractString(json, 'event') = 'checkout_completed'
    AND timestamp >= toUnixTimestamp(toDateTime('2026-07-13 00:00:00'))
    AND timestamp < toUnixTimestamp(toDateTime('2026-07-27 00:00:00'))
    AND JSONExtractBool(json, 'is_internal') = false
  GROUP BY period
)
SELECT period, value
FROM periods
ORDER BY period

Confirm the absolute and relative movement:

absolute change = current - baseline
relative change = (current - baseline) / baseline

If this query does not match the chart, stop. Check the time zone, filters, aggregation, deduplication rule, comparison range, and event definition before investigating dimensions.

Rule out a data-pipeline explanation#

A product metric can move because the product changed or because measurement changed. Check:

  • ingestion request success and retry volume
  • expected event volume by producer
  • required-field completeness
  • schema-version distribution
  • producer release and deployment times
  • duplicate rate
  • event occurrence time versus arrival time
  • source-system control totals

If all events from one platform disappear, do not describe that as customer churn until the producer is verified. Use Monitor instrumentation health and Reconcile analytics with source systems.

Build a segment contribution table#

The first useful decomposition asks how much each segment added to the total change:

WITH base AS (
  SELECT
    JSONExtractString(json, 'plan') AS segment,
    if(
      timestamp >= toUnixTimestamp(toDateTime('2026-07-20 00:00:00')),
      'current',
      'baseline'
    ) AS period
  FROM product_events
  WHERE
    JSONExtractString(json, 'event') = 'checkout_completed'
    AND timestamp >= toUnixTimestamp(toDateTime('2026-07-13 00:00:00'))
    AND timestamp < toUnixTimestamp(toDateTime('2026-07-27 00:00:00'))
),
by_segment AS (
  SELECT
    if(segment = '', '(missing)', segment) AS segment,
    countIf(period = 'baseline') AS baseline_value,
    countIf(period = 'current') AS current_value
  FROM base
  GROUP BY segment
)
SELECT
  segment,
  baseline_value,
  current_value,
  current_value - baseline_value AS absolute_change,
  round(
    100 * (current_value - baseline_value) /
      nullIf(baseline_value, 0),
    2
  ) AS relative_change_pct
FROM by_segment
ORDER BY abs(absolute_change) DESC

The segments' absolute changes should sum to the top-line absolute change. That reconciliation is more important than a visually impressive percentage. A new segment with no baseline can have an undefined relative change while still contributing a clear number of events.

Separate mix shift from within-segment movement#

For rates and averages, the total can move even when every segment is stable. Suppose enterprise accounts convert at 40% and starter accounts at 10%. If the traffic mix shifts toward starter accounts, the overall rate falls without either segment getting worse.

For each segment, calculate:

baseline weight
current weight
baseline segment rate
current segment rate

Then compare two counterfactual totals:

mix effect:
  current weights × baseline segment rates

within-segment effect:
  baseline weights × current segment rates

The exact decomposition method depends on the metric. Document the method and ensure contributions reconcile to the total within an understood rounding difference. Do not add percentage-point contributions from incompatible denominators.

Use compatible denominators#

For conversion, failure, or retention rates, decompose the numerator and denominator separately:

SELECT
  period,
  plan,
  uniqExactIf(account_id, attempted = 1) AS eligible_accounts,
  uniqExactIf(account_id, completed = 1) AS completed_accounts,
  round(
    100 * completed_accounts / nullIf(eligible_accounts, 0),
    2
  ) AS conversion_rate_pct
FROM prepared_account_outcomes
GROUP BY period, plan

A falling conversion rate can mean:

  • completions fell
  • eligible attempts grew faster than completions
  • the population mix changed
  • the denominator definition changed
  • recent entities have not had time to convert

Always display the counts beside the rate.

Drill down as a tree, not a fishing expedition#

Choose dimensions from a causal or operational hypothesis:

total checkout change
├─ platform
│  ├─ web
│  ├─ iOS
│  └─ Android
├─ release
├─ plan
└─ region

At each level:

  1. calculate contributions
  2. confirm they reconcile
  3. select the largest decision-relevant branch
  4. inspect one deeper dimension
  5. stop when evidence is actionable

Do not search hundreds of fields and present the largest accidental difference as a cause. High-cardinality identifiers, URLs, error messages, and customer names are usually investigation evidence, not first-line dimensions.

Connect the change to evidence#

A segment explains where the movement occurred, not automatically why. Corroborate it with:

  • release and feature-flag exposure
  • provider incidents
  • acquisition or pricing changes
  • customer lifecycle transitions
  • support contacts
  • application logs and trace identifiers
  • a known change in eligibility or business policy

Use Release-impact analytics for deployment context and Behavioral driver and outcome analysis for associations between earlier behavior and later outcomes.

Unless an experiment or another valid identification strategy supports it, write:

Most of the decline occurred among Android accounts on release 8.14.

not:

Release 8.14 caused the decline.

Publish an investigation record#

Keep a compact decision record beside the alert, incident, or metric review:

observed movement:
comparison windows:
definition version:
top contributing segments:
pipeline checks:
supporting evidence:
excluded explanations:
remaining uncertainty:
decision and owner:
follow-up validation date:

Save the final SQL with a description that names the time zone, windows, denominator, and maturity rule. A screenshot without its query is not a reproducible explanation.

Investigation checklist#

  • Current and baseline windows are complete and comparable.
  • The SQL reproduces the dashboard's top-line value.
  • Instrumentation, duplicates, and late delivery were checked first.
  • Segment contributions reconcile to the total change.
  • Rates show numerator and denominator counts.
  • Mix effects are separated from within-segment movement.
  • Dimensions were chosen from hypotheses, not unlimited field scanning.
  • Small or privacy-sensitive segments are suppressed appropriately.
  • Operational evidence supports the leading explanation.
  • Descriptive evidence is not presented as causal proof.
  • The query, definition, conclusion, and owner are recorded.
Need a hand?

Tell us what you’re building and we’ll point you in the right direction.

Contact support