GCP FinOps: A Survival Guide to Google’s Financial Spaghetti
How This Ecosystem Works
When you open the Billing Console and see your monthly total, you are looking at a ready-made report built on top of a dozen internal mechanisms. Google does not provide a single “give me all my costs” API. Instead, data is scattered across several independent services, each answering its own narrow question. To avoid drowning in this ecosystem, it is helpful to keep a simple model in mind: there are sources of control (who pays and what the spending limits are), sources of truth (what was actually spent, down to a specific disk), and sources of intelligence (what can be optimized and what the impact will be). Mixing up these three categories is the main reason why people spend weeks trying to figure out where to get FinOps data in GCP.
Control and Forecast Sources
The first group includes the Cloud Billing API, Budget API, and Catalog (Pricing) API. They do not tell you how much you spent yesterday. They tell you who is paying, how much you are allowed to spend, and the base price of resources.
Cloud Billing API is a registry of billing accounts and their links to projects. As long as a company has one account and a couple of projects, you can ignore it—everything is visible in the console. But once an organization grows to dozens of projects, multiple legal entities, or a reseller model, this API becomes critical. You can programmatically check which account each project is linked to, ensure billing hasn’t dropped off (which instantly stops all paid services), and automate the transfer of projects between accounts during corporate restructuring.
| Parameter | Meaning | When it’s useful |
name / displayName | Billing account ID and name | Mapping accounts if there are several in the organization. |
open | Whether the account is currently active | Alerting if an account is unexpectedly suspended or closed. |
masterBillingAccount | Link between a sub-account and a master account | Relevant for resellers and partnership programs. |
billingEnabled (on project) | Whether billing is enabled for a specific project | Preventive monitoring—a project without billing will eventually lose access to paid services. |
Budget API is the programmatic version of the “Budgets & alerts” section. Its purpose is not to stop spending (GCP does not physically block resources based on a budget—a common misconception), but to notify you of overspending in time so you can react manually or via automation. Two parameters are fundamentally important here: the budget scope filter and the threshold calculation basis.
The scope filter (budgetFilter) defines which piece of infrastructure a specific budget covers. It can be the entire account, specific projects, specific services, or even a slice by user labels. Team-level budgets are built entirely on labels: if all resources of your data science team are tagged with team=ml, you can create a budget specifically for this label and receive an alert when the team exceeds its limit, without affecting the budgets of others.
The threshold basis (spendBasis) is the difference between “already spent” (CURRENT_SPEND) and “forecasted spend by the end of the month” (FORECASTED_SPEND). This is a key feature that is often overlooked. If you set an alert only for actual spend, you find out about the problem after it has happened. The forecasted threshold warns you in advance—for example, if on the 5th of the month the algorithm sees that at the current spending rate you will blow the budget by the 20th, it alerts you immediately instead of waiting for the actual overspend.
| Parameter | Meaning | When it’s useful |
budgetFilter (projects/services/labels) | The infrastructure slice covered by the budget | Budgets by team, environment (prod/staging), or product. |
amount (specifiedAmount / lastPeriodAmount) | A fixed amount or auto-calculation based on the previous period | lastPeriodAmount is useful for dynamic teams without a stable spending plan. |
thresholdRules (0.5, 0.8, 1.0, 1.2…) | Trigger thresholds as a fraction of the budget | Escalation—from a mild notification to a critical alert. |
spendBasis (CURRENT_SPEND / FORECASTED_SPEND) | Calculation basis: actual or forecast | Forecasting buys you time to react before an actual overspend occurs. |
notificationsRule | Where the alert goes (Pub/Sub, email) | Integration with Slack/PagerDuty via a Pub/Sub trigger. |
Catalog API (or Pricing API) is Google’s official price list for every Stock Keeping Unit (SKU). It is important to understand its purpose: it is not what you pay, but what the item costs “by default,” without your custom discounts. The difference between the list price and your actual billing price is the measure of how effectively your volume or committed use discounts are working. The second use case is forecasting: before you launch a new project or migrate to a different machine type, you can calculate the expected cost based on planned usage volume and the current price list, without waiting for the actual invoice.
| Parameter | Meaning | When it’s useful |
serviceId | Product ID (Compute Engine, Cloud Storage, etc.) | Entry point for getting SKUs of a specific service. |
pricingExpression / tieredRates | Pricing grid, often tiered by volume | “What-if” calculations when changing resource configurations. |
usageType (OnDemand/Preemptible/Commit1Yr) | Consumption model | Comparing the economics of different capacity purchasing models. |
serviceRegions | Regions where the price applies | GCP prices are regional, not global—this must be factored into calculations. |
Sources of Factual Data
This is the core of all analytics: exporting actual cost data into BigQuery. Without it, the rest of the picture is just management and forecasting, not facts.
Standard usage cost export provides daily costs by project, service, and SKU. Here, you should pay attention not only to the cost amount but also to the credits structure. This is a separate array of records reflecting volume discounts (Sustained Use Discount), capacity reservations (Committed Use Discount), promo credits, and the free tier. A common beginner mistake is subtracting credits from cost as if they were two independent numbers, even though credits are already stored as negative values, so the final total is just their sum. Another frequently missed field is cost_type: besides regular expenses, you will find adjustment (retroactive corrections, like invoice recalculations) and tax. If you do not separate these, you might misinterpret a spending spike—it could just be a last-month accounting correction, not a surge in actual consumption.
| Parameter | Meaning | When it’s useful |
service / sku | Product and specific tariff position | Basic grouping for any report. |
usage_start_time / usage_end_time | Time interval of consumption | Building daily, weekly, or monthly trends. |
project / location | Project and region | Breakdown by teams (via projects) and data centers. |
cost / currency | Spend amount and currency | Core metric; requires attention in multi-currency accounts. |
credits (name, amount, type) | Discounts and credits, separate from the base amount | Analyzing how effectively CUD/SUD are utilized. |
usage.amount / usage.unit | Physical volume of consumption (hours, GBs, requests) | The foundation for calculating unit economics. |
cost_type | Regular spend, adjustment, or tax | Separating actual spending growth from accounting adjustments. |
labels | Custom resource tags | Chargeback—allocating costs across teams/products. |
Detailed usage cost export includes the same dataset plus one critical additional field: resource.name (the name of a specific virtual machine, disk, or bucket). It sounds like a minor detail, but in practice, this is the key to any “where is the money going” investigation. The Standard export will tell you that Compute Engine cost $40,000 this month. The Detailed export will tell you that $15,000 of that was burned by three specific virtual machines someone forgot to shut down after a test three months ago. Without this level of granularity, FinOps is just pretty charts with no actionable insights.
Pricing export is the same price list provided by the Catalog API, but dumped directly into BigQuery as a table. This eliminates the need to pull a separate API and merge data manually. Its purpose is to allow a direct “actual amount paid” vs. “list price without discounts” comparison using a single query entirely within the BigQuery SQL environment.
Carbon Footprint export is a niche but increasingly demanded feature. It provides the carbon footprint across the same dimensions as costs: project, service, region, and month. The fields contain a breakdown by scope 1, 2, and 3 (direct emissions, electricity consumption emissions, and indirect supply chain emissions). The primary use case is building a combined “money spent vs. CO2 produced” report, as companies increasingly require this unified view for ESG reporting rather than two separate documents.
Sources for Optimization
Recommender API does not provide cost data; it provides ready-made recommendations that Google generates by analyzing your actual consumption. Inside the Recommender, there are many separate “recommenders,” each tailored to a specific scenario. One finds virtual machines that are heavily over-provisioned in CPU and memory relative to their actual load (rightsizing). Another spots completely unused disks and instances. A third analyzes your spending patterns over the last few weeks and suggests whether you should buy committed use discounts. Every recommendation comes with a potential financial savings estimate and a priority from P1 to P4. The practical approach is not to review these occasionally in the console, but to regularly aggregate them via API into a dedicated table. This allows you to view recommendations alongside actual costs and track how much of the proposed savings teams are actually implementing versus ignoring for months.
Cloud Asset Inventory is technically not about money at all; it is about organizing your corporate resources. But its role in financial analytics is crucial. Billing data captures the state of resource labels at the exact moment of usage. However, labels can change—a resource might be transferred to a different owner, team, or environment after the cost was recorded. Asset Inventory provides the actual state of the resource today. By joining it with billing data via the resource name, you get a much more reliable picture of “who is responsible for this cost now,” rather than “who was responsible when it was created.”
How the Sources Connect
No single source answers a real business question on its own—the answer almost always emerges at the intersection of two sources. Here is the logic behind the main combinations (conceptually, without code).
- Joining actual costs with the price list answers the question “how well are our discounts working?” We take the actual amount for a SKU from the billing export, take the price of the same SKU from the pricing export, and multiply the price by the consumption volume. This gives us the hypothetical “if we had zero discounts” amount. The difference between the actual cost and this hypothetical sum is your discount efficiency. If this efficiency is close to zero for a specific SKU (meaning you are paying almost the list price), it is a direct signal to look into buying committed capacity for that specific item.
- Joining actual costs with recommendations answers the question “how much money is left on the table and why aren’t we taking it?” We join by resource name: on one side, how much the resource actually cost over a period; on the other, how much the recommender promises to save on that same resource. The result is a list with two side-by-side columns: current cost of waste vs. potential savings. Sorted in descending order, this becomes an actionable backlog for the optimization team, not just an abstract report.
- Joining costs with the carbon footprint answers the ESG question. We compare two metrics—money and kilograms of CO2 equivalent—by project, service, and month simultaneously. This reveals if emissions are growing faster than costs (which happens, for example, when migrating workloads to a region with a “dirtier” power grid, even if the price remains the same).
- Joining costs with business metrics is arguably the most valuable combination for management. Any internal table containing a business metric (number of orders, active users, processed requests) is mapped by date against the daily cost sum. As a result, instead of an absolute figure like “we spent $40,000,” you get a relative metric: “we spent $0.80 per processed order.” The absolute number means nothing on its own. A 20% increase in cloud costs while business grows by 35% is actually an efficiency improvement, not a problem. Without mapping against business metrics, this is easily mistaken for overspending.
- Joining costs with user labels and folder hierarchy answers the question of accountability: how much was spent by a specific team, environment (prod vs. test), or product. This is the foundation of chargeback and showback practices. You either physically bill internal teams for consumed cloud resources, or you simply show them their share of the costs regularly. The latter heavily increases awareness and curtails uncontrolled spending—engineers spend much more carefully when they see a number with their name next to it.
From Data to Dashboards: A Practical Example
Imagine a typical mid-sized company with a dozen GCP projects (some production, some test environments for multiple teams). Here is what the journey from turning on the first export to a mature FinOps setup usually looks like.
First, the Detailed Billing Export is enabled. Without it, resource-level granularity is impossible. Most companies start with just the Standard export and spend weeks trying to figure out why they cannot find a specific expensive resource. Next, the Pricing Export is connected to calculate discount efficiency right away, and a regular (e.g., weekly) dump of the Recommender API into a separate table is scheduled. This requires little effort but provides immediate value.
On this foundation, you usually build not one, but several dashboards tailored to different roles. A CFO, a DevOps engineer, and a Team Lead need fundamentally different slices of the exact same data.
| Dashboard | Question it answers | Who uses it | Data sources |
| Executive Overview | How much are we spending now, are we within budget, what is the end-of-month forecast? | CFO, C-level Management | Standard export + Budget API |
| Resource Investigation | Which exact resource is generating the cost and why? | Engineers, FinOps Specialists | Detailed export |
| Discount Efficiency | How well are current commitments working, what should we buy next? | FinOps, Cloud Procurement | Billing export + Pricing export |
| Optimization Backlog | What exact actions will yield savings and how much? | Engineering Teams | Billing export + Recommender API |
| Unit Economics | How much does one unit of business activity cost, and how is it trending? | Product Management | Billing export + Internal business tables |
| Team Chargeback | How much did each team spend and what is their growth dynamic? | Team Leads, Finance | Billing export + labels + project hierarchy |
The Executive Overview dashboard is usually the simplest in structure but the most sensitive in content. It has a few big numbers at the top (month-to-date spend, percentage of budget, end-of-period forecast) and one trend graph by day broken down by core services. Its job is to provide answers in a ten-second glance without requiring a deep dive into details.
The Resource Investigation dashboard is built exactly the opposite way. It is a drill-down table: from service to specific SKU, from SKU to specific resource name, with project and time-period filters. This is where an engineer goes when they see an anomalous cost spike and need to find the culprit in two minutes, rather than reading a summary report.
The Discount Efficiency dashboard is interesting because it almost always shows the same pattern in growing companies: discount efficiency gradually drops. This happens because new services and regions are launched without commitments, while old commitments were calculated for last year’s infrastructure. This dashboard acts as a direct trigger to talk to the finance team about revising capacity purchases.
The Optimization Backlog works best when it is not a static report, but a live list with status tracking (e.g., “spotted”, “in progress”, “done”). Without this workflow, Recommender API suggestions tend to pile up and get ignored for months because there is no physical place to track them as engineering tasks.
Unit Economics is the most strategic of all dashboards because it translates the conversation from engineering language into business language. When costs grow proportionally with (or slower than) the business, it is a sign of health, not a reason to panic, even if the absolute cost figure looks intimidating at first glance.
Finally, the Chargeback dashboard is a cultural tool, not just a reporting one. When each team regularly sees its slice of the company’s total bill next to other teams, people’s behavior changes organically, without the need for strict top-down limits or approvals.
This is the complete picture: control sources set the boundaries and forecasts, factual sources show what really happened, intelligence sources suggest what to do about it, and joining the data across them transforms scattered numbers into six specific, actionable tools for different roles in the company.
Uncontrolled BigQuery queries, over-provisioned infrastructure, and hidden cloud waste often build up silently as data platforms scale. Rather than cutting resources blindly or imposing rigid limits that stall engineering velocity, effective cost control requires a precise, architectural review of your workload. My FinOps on GCP service is designed to identify query inefficiencies, optimize data partitioning, and align your cloud expenses directly with technical and business value. We focus on finding the root causes of runaway bills—from unoptimized transformations to redundant storage—without compromising system performance. If you are looking for a calm, data-driven approach to make your Google Cloud environment predictable and cost-efficient, I invite you to explore the details.
