What goes in a BigQuery monitoring dashboard in Metabase?
A BigQuery monitoring dashboard tracks job volume, execution time, bytes scanned versus billed, slot utilization, and spend by project — and names the queries responsible. Metabase connects to BigQuery natively, so every card is plain SQL over INFORMATION_SCHEMA.JOBS — no exporter or agent in between.
For: data platform teams, analytics engineers, and whoever owns the warehouse bill. Grain: one row per job, rolled up daily.
Source:
INFORMATION_SCHEMA.JOBS_BY_PROJECT (≈180-day retention — snapshot nightly for more).
What does a BigQuery monitoring dashboard look like?
Here’s the layout this guide builds. Warehouse-level numbers and the month’s spend sit at the top; query volume, performance, errors, and cache behaviour fill the middle; the bottom section follows the money — bytes, slots, and the specific queries that dominate the bill.

An example BigQuery monitoring dashboard in Metabase, built from INFORMATION_SCHEMA.JOBS. Figures are illustrative.
Which cards belong on a BigQuery monitoring dashboard?
Eight cards, updated from the classic list: percentiles instead of averages for execution time, and bytes billed — the number that costs money — beside bytes scanned.
- Jobs — volume per hour, plus queries in flight right now (area + number)
- Query execution time — p50 and p95 by day (line)
- Bytes scanned vs. bytes billed per day (bar)
- Slot utilization against the reservation (line)
- Bytes billed by project, month to date (row)
- Cache hit rate by day (line)
- Failed jobs by error type — rate limits, invalid queries, timeouts (stacked bar)
- Top queries by bytes billed, with estimated cost (table)
What data does the dashboard need?
INFORMATION_SCHEMA.JOBS_BY_PROJECT(orJOBS_BY_ORGANIZATION) — job state, timings,total_bytes_processed,total_bytes_billed,cache_hit,total_slot_ms,error_result, user, and query text.- A nightly rollup table snapshotting the view — both for history beyond ~180 days and so dashboard refreshes don’t re-scan the raw view.
RESERVATIONcapacity (from the reservations views or config) for the slot-utilization goal line.- Optional billing export via Google Cloud billing to reconcile estimated cost against the invoice.
How do you build it?
- Connect BigQuery to Metabase with a service account that can read the region-qualified
INFORMATION_SCHEMAviews. - Schedule a nightly query that appends yesterday’s jobs to a rollup table — always filtered on
creation_time, the column the views are partitioned by. - Model the rollup once (est. cost = TB billed × your on-demand rate) and point every card at the model, so cost math never varies by chart.
- Build the bytes and top-queries cards first — they pay for the dashboard — then performance, errors, and slots.
- Add filters for project, user, and date range, and pin the top-queries table where the data team will actually see it.
Example card SQL
SELECT
DATE(creation_time) AS day,
COUNT(*) AS jobs,
COUNTIF(state = 'RUNNING') AS in_flight,
APPROX_QUANTILES(
TIMESTAMP_DIFF(end_time, start_time, SECOND), 100
)[OFFSET(95)] AS execution_p95_s,
ROUND(SUM(total_bytes_processed) / POW(1024, 4), 2) AS tb_scanned,
ROUND(SUM(total_bytes_billed) / POW(1024, 4), 2) AS tb_billed,
ROUND(SUM(total_bytes_billed) / POW(1024, 4) * 6.25, 0) AS est_cost_usd,
ROUND(100 * COUNTIF(cache_hit) / COUNT(*), 1) AS cache_hit_pct
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 14 DAY)
AND job_type = 'QUERY'
GROUP BY 1
ORDER BY 1; Related
Metrics
Integrations
Dashboards
FAQ
What is a BigQuery monitoring dashboard?
INFORMATION_SCHEMA.JOBS with ordinary SQL: no exporter, no pipeline, no third-party agent.Where does the data come from?
INFORMATION_SCHEMA.JOBS views — JOBS_BY_PROJECT for one project, JOBS_BY_ORGANIZATION for everything (requires an org-level role). Each row is one job: state, start and end time, bytes processed and billed, cache hit, slot-milliseconds, error result, user, and the query text. Two practical notes: the views are region-qualified (`region-us`.INFORMATION_SCHEMA…), so query the region your datasets live in, and they retain roughly 180 days — schedule a nightly append into your own table if you want more history.Why are bytes billed higher than bytes scanned?
total_bytes_billed ≥ total_bytes_processed, and lots of small queries against many tables can bill noticeably more than they scan — visible as the persistent gap between the two bars in the example. Chart both: scanned tells you about query behaviour, billed is the one that costs money.How do I find the queries that cost the most?
SUM(total_bytes_billed) over the month, grouping by the normalized query text or by referenced table. It is normal for a handful of scheduled queries to dominate — in the example, five full scans of an unpartitioned events table account for 61% of month-to-date bytes billed. That table is the to-do list: partitioning, clustering, or materializing the hot subset usually cuts the top offenders by an order of magnitude.On-demand or capacity (slot) pricing — and what changes here?
Does the monitoring itself cost money?
INFORMATION_SCHEMA.JOBS queries bill for the bytes they process like any other query, but the views are small relative to real workloads, and daily rollups touched once a night cost cents. Two habits keep it that way: filter on creation_time (the views are partitioned by it), and point dashboard cards at a nightly rollup table rather than re-scanning the raw view on every refresh — Metabase's own result cache helps too.