BigQuery FinOps Query Pack

Which GCP services changed the most month over month?

Service-level month-over-month movement from the billing export.

Costs money to run — queries your billing export tableChecked 4 Aug 2026
-- Replace the table with your billing export.
-- This scans real data: filter the partition column first.
WITH monthly AS (
  SELECT
    invoice.month                                            AS invoice_month,
    service.description                                      AS service,
    SUM(cost)                                                AS cost,
    SUM(IFNULL((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0)) AS credits
  FROM `PROJECT.DATASET.gcp_billing_export_v1_XXXXXX_XXXXXX_XXXXXX`
  WHERE _PARTITIONTIME >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 70 DAY)
  GROUP BY invoice_month, service
)
SELECT
  service,
  MAX(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)), cost, 0)) AS prior_month,
  MAX(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)), cost, 0)) AS last_month,
  ROUND(
    MAX(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)), cost, 0))
  - MAX(IF(invoice_month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 2 MONTH)), cost, 0)), 2) AS delta
FROM monthly
GROUP BY service
ORDER BY ABS(delta) DESC
LIMIT 50;

What it returns

delta
Last month minus the month before, in your billing currency.
credits
Committed-use and promotional credits, negative amounts.

How to read it

  • This tells you what moved, not why. A service can rise because you used more of it or because a discount expired, and those need opposite responses.
  • Compare complete invoice months only. A partial current month will always look like a collapse.
  • Credits are separate rows with negative amounts. Decide up front whether you are analysing gross or net cost and stay consistent.

Take it further

Run this once, or have it run every day.

Finitizer evaluates this class of question continuously against your live BigQuery estate, tracks how each number moves between runs, and turns findings into assigned tasks. Read-only and keyless.