12 min read

Grafana vs Looker Studio for Site Health Dashboards

Most teams do not choose a dashboard tool for their audit pipeline — they inherit whichever one the organisation already uses for something else. That is usually fine, right up until the dashboard quietly becomes the way people find out that something is broken. This page is part of Wiring Health Scores into Dashboards & Alerts and compares Grafana and Looker Studio for site-health work, with the operational question stated explicitly rather than left to emerge later.

Which tool each audience earns A two by two grid. The vertical axis is whether the dashboard has to drive alerting; the horizontal is who reads it. An engineering audience that also needs alerting favours Grafana, where the panel and the alert rule share one query. A stakeholder audience with alerting handled elsewhere favours Looker Studio for its sharing model. An engineering audience with no alerting need can use either. A stakeholder audience that also needs alerting should not be served by one tool at all — the alert belongs in the alerting system regardless of where the chart lives. must drive alerts no alerting need Grafana the panel query and the alert rule are the same expression, reviewed together Split them chart wherever you like, but alerting belongs in the alerting system Either pick on sharing and cost, because nothing operational depends on it Looker Studio scheduled email delivery and permissioning that non-engineers already have stakeholders engineers The axis nobody states out loud is who gets paged. A dashboard that must drive alerting is an operational system; one that must reach a quarterly review is a document.

Comparison Table

Dimension Grafana Looker Studio
Dashboard definition JSON, version-controlled and deployable Edited in a web UI; no reviewable source of truth
Alerting First-class; rules evaluate the same queries panels use None; a reporting surface only
Warehouse connectivity Datasource plugins for BigQuery, Postgres, Prometheus and more Native BigQuery connector, plus community connectors
Refresh model Per-panel interval, or push via a metrics endpoint Cached extracts or live query, per data source
Access model Accounts and teams you administer Link sharing with the identity provider most staff already use
Scheduled delivery Via reporting plugins or the paid tier Built in — scheduled email delivery of a PDF
Cost shape Self-hosted infrastructure, or a per-user cloud tier Free at the point of use
Templating Repeating panels over a variable, e.g. one row per section Limited; usually one page per breakdown

The rows that decide it are the first two. Everything else is a preference; alerting and version control are the properties that determine whether the dashboard is a component of the system or a description of it.

Five properties that decide it Two columns pairing the same five concerns. Grafana defines dashboards as JSON in version control, evaluates alert rules from the same queries the panels use, connects to a warehouse through a datasource plugin, is self-hosted or paid-hosted, and is accessed by people with an account you administer. Looker Studio defines dashboards through a web editor with no reviewable source, has no alerting of its own, connects natively to BigQuery, is free to use, and shares by link with permissions most organisations already run. GRAFANA Dashboards are JSON in git reviewable, diffable, deployable Alert rules share panel queries one expression, two consumers Warehouse via a datasource plus Prometheus, Loki and the rest Self-hosted or paid cloud a system you operate LOOKER STUDIO Edited in a web UI no reviewable source of truth No alerting of its own it is a reporting surface, not a pager Native BigQuery connector and scheduled email delivery Free, shared by link permissions your org already runs Neither list is a verdict. The question is whether the dashboard is part of the operational path — if it is, the top two rows dominate everything else.

Two parity configurations

Both configurations below read the same serving layer described in the parent guide, so the number on the screen is the number the scoring pipeline computed, in both tools.

// grafana/dashboards/site-health.json — deployed from the repository.
{
  "title": "Site health — composite score by section",
  "refresh": "15m",
  "templating": { "list": [
    { "name": "section", "type": "query", "datasource": "audit-warehouse",
      "query": "SELECT DISTINCT section FROM serving.scores_current ORDER BY 1" }
  ]},
  "panels": [
    { "type": "timeseries", "title": "Composite score — $section (all devices)",
      "datasource": "audit-warehouse",
      "targets": [{ "rawSql":
        "SELECT run_date AS time, composite_score FROM serving.scores_history WHERE section = '$section' ORDER BY 1",
        "format": "time_series" }],
      "fieldConfig": { "defaults": { "min": 0, "max": 100 } } },
    { "type": "stat", "title": "Serving layer age",
      "datasource": "audit-warehouse",
      "targets": [{ "rawSql":
        "SELECT EXTRACT(EPOCH FROM (now() - MAX(served_at))) AS age FROM serving.scores_current" }],
      "fieldConfig": { "defaults": { "unit": "s",
        "thresholds": { "steps": [
          { "color": "green", "value": null }, { "color": "red", "value": 7200 }]}}}}
  ]
}

The Serving layer age panel is not decoration. It is the tile that distinguishes a healthy site from a stopped pipeline, and in Grafana it can carry an alert rule off the identical query — which is exactly the property that makes the tool operational rather than descriptive.

For Looker Studio the equivalent is a BigQuery view, because the tool has no place to put a query that is reviewable:

-- Deployed to BigQuery; Looker Studio reads the view, never raw SQL in a panel.
CREATE OR REPLACE VIEW `audit.serving_scores_reporting` AS
SELECT
  run_date,
  section,
  device,
  composite_score,
  coverage,
  imputed_share,
  scoring_version,
  TIMESTAMP_DIFF(CURRENT_TIMESTAMP(), MAX(served_at) OVER (), SECOND) AS serving_age_s
FROM `audit.serving_scores_history`
WHERE run_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 180 DAY);

Pushing every expression into a view is the workaround for the missing source of truth: the dashboard becomes a thin rendering of something that is in version control, and a panel that quietly acquires its own arithmetic is visible as a diff on the view rather than invisible inside the editor.

Verification

set -euo pipefail
# 1. The Grafana dashboard in the repo matches what is deployed.
curl -sS -H "Authorization: Bearer $GRAFANA_TOKEN"   "$GRAFANA_URL/api/dashboards/uid/site-health"   | jq -S '.dashboard | del(.version, .id)' > /tmp/live.json
jq -S 'del(.version, .id)' grafana/dashboards/site-health.json > /tmp/repo.json
diff /tmp/repo.json /tmp/live.json && echo "PASS: deployed dashboard matches the repository"

# 2. No panel computes a composite of its own.
grep -oE '"rawSql": "[^"]+"' grafana/dashboards/*.json   | grep -iE '(\*|\+)[[:space:]]*[0-9.]+[[:space:]]*(\*|\+)'   && { echo "FAIL: arithmetic in a panel query"; exit 1; }   || echo "PASS: no scoring arithmetic in any panel"

# 3. The staleness threshold matches the shared config.
[ "$(jq -r '.serving.stale_after_s' "$THRESHOLD_CONFIG")"   = "$(jq -r '..|.thresholds?.steps?[1]?.value // empty' grafana/dashboards/site-health.json | head -n1)" ]   && echo "PASS: staleness threshold matches the shared config"

Expected output is three PASS lines. The second check is the one worth keeping permanently — it is a cheap grep that catches the exact regression this comparison is about, a panel quietly acquiring its own version of the score.

Failure Modes

Three ways the choice bites later Three rows. A Looker Studio dashboard used as the de facto alerting surface means nothing fires when nobody is looking. A Grafana instance nobody operates becomes an outage of its own during the incident it was meant to help with. And dashboards edited in a UI with no source of truth cannot be reviewed, restored or reasoned about after the person who built them leaves. SITUATION WHAT GOES WRONG FIX A reporting tool became the way people notice that something broke Nothing fires unattended the surface only works while a human is looking at it Move alerting out to the alerting system; keep the report as a report The dashboard is down during the incident it exists to help with Nobody operates it a self-hosted tool is a service with its own availability Own it, or host it treat it as production, or buy the hosted version A panel changed and nobody can say when, why or by whom No reviewable source the dashboard exists only as state inside a web editor Define it as code JSON in the repository, deployed like anything else All three are consequences of the same unstated decision: whether this dashboard is a document that describes the system or a component that is part of it.

Looker Studio caches an extract and the dashboard is hours behind

The BigQuery connector defaults to caching, so a tile can render a stale snapshot with no indication. The serving_age_s column in the view above exists to make that visible; put it on the dashboard as a scorecard, not in a detail page nobody opens.

Grafana panels drift from the repository

Someone edits a panel in the UI to answer a question during an incident and never reverts it. The diff check above catches it on the next CI run; without it, the repository copy quietly becomes fiction. Set the instance to provisioned dashboards where the UI is read-only if the drift keeps recurring.

The two tools disagree about the same section

Almost always a scope difference rather than a data difference — one is filtered to a device class or excludes a section the other includes. Compare the populations before comparing the numbers, exactly as described in the parent guide, and render the scope on every tile in both tools.

FAQ

Which of the two should drive alerting?

Grafana, if either of them does. Its alert rules evaluate the same queries the panels use, so the chart and the page cannot disagree and both are reviewed in one change. Looker Studio has no alerting at all, which is not a defect — it is a reporting surface. The failure mode to avoid is letting a reporting surface become the de facto way people notice something is broken, because it only works while someone happens to be looking at it.

Does it matter that Looker Studio dashboards are not in version control?

It matters as much as the dashboard matters. For a quarterly stakeholder report, an unversioned dashboard is an acceptable trade for sharing that works with permissions the organisation already runs. For anything on the operational path it is a real cost: a panel can change without a diff, an expression can acquire arithmetic nobody reviewed, and after the person who built it leaves there is no source to read. Pushing every expression into a database view recovers most of that.

Can the same serving layer feed both tools?

Yes, and it should. The whole point of a pre-computed serving layer is that every consumer reads the same rows rather than re-deriving anything, so pointing Grafana at it over a datasource and Looker Studio at it through a BigQuery view gives two renderings of one number. What must not happen is either tool computing its own composite from component metrics, because that immediately reintroduces the disagreement the layer exists to prevent.