Building Cloud Cost Trend Charts That Actually Surface Billing Patterns

Generic monthly trend charts show you that costs went up. The charts below show you why โ€” flat-line orphan signatures, ratio inversions, security event fingerprints, and AI spend drift. Each one is a specific query against your FOCUS billing data.

A line chart of total monthly cloud spend is the least useful visualization you can build. It tells you the total went up, which you already knew from the invoice. The charts that generate action are the ones that reveal a specific billing shape: the perfectly flat OCU line that means an orphaned Knowledge Base is running, the ratio inversion that means your AI inference costs collapsed while the vector store kept billing, the overnight spike in a region your team has never used.

This article covers four chart types โ€” each targeting a specific class of billing problem โ€” with the Athena SQL that powers them and the Grafana configuration that renders them.

Prerequisites

All queries run against a FOCUS 1.2 billing table in Athena. If your pipeline is not yet set up, see the ETL Architecture article. For Grafana, you need the Athena data source plugin (grafana-athena-datasource) configured with read access to your billing workgroup. AWS also publishes the open-source COAST dashboard project as a starting point if you want a pre-built baseline.


Chart 1 โ€” Daily Cost by Service (Spike and Drift Detection)

What it reveals: Cost spikes (a service doubles overnight), new services appearing (a line that starts from zero), and steady drift (a line climbing 5% per week without an obvious event). This is your primary operational chart โ€” the one you look at every morning.

-- Daily cost by top services โ€” last 60 days
-- Run as a Grafana time series: X = charge_date, Y = daily_cost, series = servicename
SELECT
  DATE(chargeperiodstart)      AS charge_date,
  servicename,
  SUM(billedcost)              AS daily_cost
FROM focus_billing
WHERE chargeperiodstart >= CAST(DATE_ADD('day', -60, CURRENT_DATE) AS TIMESTAMP)
  AND chargecategory = 'Usage'
  AND chargeclass    = 'Regular'
  AND billedcost     > 0
GROUP BY
  DATE(chargeperiodstart),
  servicename
ORDER BY
  charge_date DESC,
  daily_cost  DESC;

Grafana config: Time series panel, group by servicename for series splitting. Set the Y-axis to USD. Add a threshold line at your daily budget for each service. The visual signature you are looking for: a new line appearing (new service), a line that kinks upward sharply (spike), or a line with zero variance that is higher than expected (floor cost).

The shape to recognize โ€” new service line: A service that has never appeared in your account shows up as a line that starts from the left edge of the chart with no prior history. This is the visual equivalent of the new-region zero-threshold security rule. Any line that starts mid-chart without a corresponding deployment event is an investigation trigger.


Chart 2 โ€” OCU vs Inference Ratio (Orphaned KB Detection)

What it reveals: The cross-service signature of an orphaned Bedrock Knowledge Base โ€” OpenSearch Serverless OCU charges continuing while Bedrock inference drops to zero. The ratio is the signal: when OCU cost is more than 10ร— inference cost, the collection is almost certainly idle or orphaned.

-- Daily OCU cost vs Bedrock inference cost โ€” last 60 days
-- Render as two-line chart; the gap between lines is the waste signal
SELECT
  DATE(chargeperiodstart)                                          AS charge_date,
  SUM(CASE
    WHEN servicename LIKE '%OpenSearch%'
     AND x_usagetype LIKE '%OCU%'
    THEN billedcost ELSE 0
  END)                                                             AS ocu_cost,
  SUM(CASE
    WHEN servicename LIKE '%Bedrock%'
     AND x_usagetype LIKE '%InvokeModel%'
    THEN billedcost ELSE 0
  END)                                                             AS inference_cost
FROM focus_billing
WHERE chargeperiodstart >= CAST(DATE_ADD('day', -60, CURRENT_DATE) AS TIMESTAMP)
  AND chargecategory = 'Usage'
  AND chargeclass    = 'Regular'
GROUP BY DATE(chargeperiodstart)
ORDER BY charge_date DESC;

Grafana config: Two-line time series panel โ€” one line for ocu_cost, one for inference_cost. When the KB is active, both lines track together. When the KB is deleted (or abandoned), inference_cost drops to zero while ocu_cost continues perfectly flat. The visual gap is unmistakable โ€” a horizontal OCU line above a flatlined inference line is the orphaned KB signature.

Add a ratio panel: A stat panel showing ocu_cost_30d / NULLIF(inference_cost_30d, 0) as a current ratio. Green below 2ร—, yellow 2โ€“10ร—, red above 10ร—. This gives you an at-a-glance health indicator for every account running Bedrock KBs.


Chart 3 โ€” Security Billing Heatmap (New Region / New Service)

What it reveals: Which accounts started billing in new regions or for new services in the last 7 days โ€” the visual form of the zero-threshold security rule. A cell that lights up in this heatmap is an immediate investigation trigger, not a cost concern.

-- New region activity: accounts ร— regions with first-seen date in last 7 days
-- where the region has no history in the prior 90 days
WITH history AS (
  SELECT DISTINCT subaccountid, regionid
  FROM focus_billing
  WHERE chargeperiodstart >= CAST(DATE_ADD('day', -97, CURRENT_DATE) AS TIMESTAMP)
    AND chargeperiodstart <  CAST(DATE_ADD('day', -7,  CURRENT_DATE) AS TIMESTAMP)
    AND chargecategory = 'Usage'
),
recent AS (
  SELECT
    subaccountid,
    regionid,
    MIN(chargeperiodstart) AS first_seen,
    SUM(billedcost)        AS total_cost
  FROM focus_billing
  WHERE chargeperiodstart >= CAST(DATE_ADD('day', -7, CURRENT_DATE) AS TIMESTAMP)
    AND chargecategory = 'Usage'
    AND regionid != 'NoRegion'
  GROUP BY subaccountid, regionid
)
SELECT
  r.subaccountid,
  r.regionid,
  r.first_seen,
  r.total_cost,
  'NEW_REGION' AS signal
FROM recent r
LEFT JOIN history h
  ON r.subaccountid = h.subaccountid
 AND r.regionid     = h.regionid
WHERE h.regionid IS NULL
ORDER BY r.first_seen DESC;

Grafana config: Table panel with conditional row coloring โ€” any row with signal = 'NEW_REGION' renders red. Link each row to a drill-down panel filtered by subaccountid and regionid showing the specific resources and services billing in the new region. This is the dashboard equivalent of the Lambda security sensor โ€” same query, visual instead of alerting.


Chart 4 โ€” AI Spend Composition Over Time

What it reveals: How AI-related spend as a proportion of total spend is changing month over month. The FinOps Foundation 2026 data shows AI workloads now represent 18% of cloud spend at AI-forward enterprises, up from 4% in 2023. Tracking this ratio internally tells you whether AI spend is growing proportionately to the value it delivers, or outpacing it.

-- Monthly AI spend vs total spend โ€” last 12 months
-- AI services defined as Bedrock, SageMaker, OpenSearch Serverless (OCU), Rekognition, Comprehend
SELECT
  DATE_TRUNC('month', chargeperiodstart)  AS billing_month,
  SUM(billedcost)                          AS total_spend,
  SUM(CASE
    WHEN servicename IN (
      'Amazon Bedrock',
      'Amazon SageMaker',
      'Amazon Rekognition',
      'Amazon Comprehend',
      'Amazon Textract'
    )
    OR (servicename LIKE '%OpenSearch%' AND x_usagetype LIKE '%OCU%')
    THEN billedcost ELSE 0
  END)                                     AS ai_spend,
  ROUND(
    100.0 * SUM(CASE
      WHEN servicename IN (
        'Amazon Bedrock','Amazon SageMaker',
        'Amazon Rekognition','Amazon Comprehend','Amazon Textract'
      )
      OR (servicename LIKE '%OpenSearch%' AND x_usagetype LIKE '%OCU%')
      THEN billedcost ELSE 0
    END) / NULLIF(SUM(billedcost), 0),
  1)                                       AS ai_pct_of_total
FROM focus_billing
WHERE chargeperiodstart >= CAST(DATE_ADD('month', -12, CURRENT_DATE) AS TIMESTAMP)
  AND chargecategory = 'Usage'
  AND chargeclass    = 'Regular'
GROUP BY DATE_TRUNC('month', chargeperiodstart)
ORDER BY billing_month;

Grafana config: Combo chart โ€” bar chart for total_spend and ai_spend stacked, line overlay for ai_pct_of_total on a secondary Y-axis (percentage). This chart answers the question leadership asks: "Is AI spend under control as a fraction of total cloud investment?"

Note on OpenSearch in the AI definition: The query includes OpenSearch OCU charges (x_usagetype LIKE '%OCU%') in the AI spend bucket because OCU charges are almost exclusively from Bedrock Knowledge Base vector stores in most accounts. If you have a deliberate non-Bedrock OpenSearch Serverless workload, exclude it by adding a ResourceId NOT LIKE 'bedrock-knowledge-base-%' filter.


The Chart Shape Reference

Shape you seeWhat it meansAction
Perfectly flat horizontal line in OCU chart Orphaned OpenSearch Serverless collection โ€” no workload but billing continues Check OpenSearch console for bedrock-knowledge-base-* collections with no active KB
Inference line drops to zero, OCU line continues Bedrock KB deleted without deleting the collection Delete the collection from OpenSearch console โ€” billing stops immediately
New line appearing mid-chart with no prior history New service or new region โ€” could be legitimate deployment or credential compromise Verify against change log โ€” if no authorized deployment, treat as security incident
SageMaker endpoint line flat for 7+ days Idle inference endpoint โ€” no invocations but 24/7 instance billing Check CloudWatch Invocations metric โ€” if zero, delete endpoint or enable scale-to-zero
Egress line growing faster than compute line Data transfer volume increasing relative to workload โ€” possible exfiltration or architectural issue Check DataTransfer-Out-Bytes by service for the diverging account

Find out which billing patterns are hiding in your data right now

The DropInFinOps free assessment maps your current FOCUS export setup against these chart patterns โ€” showing which anomaly signatures are queryable in your data today.

Take the free assessment โ†’