
The Manual Grind: Why AWS & GCP Billing Data Breaks Spreadsheets
The process of multi-cloud cost reconciliation often begins not with a strategy, but with a sigh. It’s the tedious, multi-day task of exporting billing files from AWS and GCP, forcing them into a spreadsheet, and trying to make sense of two entirely different data schemas. This manual effort is more than an annoyance; it’s a primary source of cost visibility gaps. According to the FinOps Foundation’s State of FinOps 2024 report, the average organization detects 32% waste in their cloud spend. Much of this waste thrives in the blind spots created by disconnected billing data, where comparing the cost of a compute instance on AWS versus GCP requires a manual, error-prone translation layer.
The core problem is that cloud providers have no incentive to make their billing data compatible. AWS Cost and Usage Reports (CUR) and GCP’s Billing Export to BigQuery are powerful, but they speak different languages. One calls a VM “EC2”, the other “Compute Engine”. One uses `lineItem/UnblendedCost`, the other `cost`. This isn’t just a naming issue; it reflects different pricing models, resource hierarchies, and tagging systems that make a simple, unified cost view impossible without significant engineering effort.
Step 1: Unifying Data Extraction from Disparate Sources
The first technical hurdle is getting consistent, granular data out of each cloud. While both AWS and GCP allow exporting detailed billing data, the setup and structure vary significantly.
AWS Cost and Usage Reports (CUR)
CUR is the gold standard for AWS cost data. It provides the most detailed information available, including resource IDs and user-defined cost allocation tags. Setting it up requires creating an S3 bucket and configuring the report delivery. I run a variant of this check periodically to ensure our CUR configurations are active, as a deactivated report can create a blind spot for weeks.
# Create an S3 bucket for your CUR reports
aws s3api create-bucket --bucket your-cur-bucket-name-unique \
--region us-east-1
# Define the CUR report details in a JSON file (cur-definition.json)
# { "ReportName": "ThalaxoCUR", "TimeUnit": "HOURLY",
# "Format": "text/csv", "Compression": "GZIP",
# "AdditionalSchemaElements": ["RESOURCES"],
# "S3Bucket": "your-cur-bucket-name-unique", "S3Prefix": "cur",
# "S3Region": "us-east-1", "AdditionalArtifacts": [] }
# Create the Cost and Usage Report
aws cur put-report-definition --report-definition file://cur-definition.json
GCP Billing Export to BigQuery
GCP’s approach is more direct, integrating natively with BigQuery. This is an advantage for analysis, as the data lands in a queryable format. However, you must enable the export on a per-billing-account basis. The raw export contains nested fields and repeated records, requiring SQL knowledge to flatten and analyze effectively.
# Enable billing export to BigQuery for a project
# This requires having a BigQuery dataset ready (e.g., 'billing_data')
gcloud beta billing projects link my-gcp-project-id \
--billing-account 012345-67890A-BCDEF0
# You would then configure the export from the GCP Console's Billing section
# to point to your BigQuery dataset. There is no direct CLI command to
# configure the export itself, it's a console-driven setup.
Once exported, the real work begins: mapping dozens of columns like AWS’s `product/productFamily` to GCP’s `service.description` and `sku.description`.
Step 2: The Core of Multi-Cloud Cost Reconciliation: Normalization
At 80+ VMs across two providers, this is where native tools stop being enough and start being a liability. You need a single, coherent view, which means creating a normalized data schema. This typically involves a data pipeline (using ETL tools or custom scripts) that transforms both AWS and GCP data into a common format before loading it into a data warehouse like BigQuery or Snowflake.
A minimal normalized schema should include:
- `provider` (e.g., ‘aws’, ‘gcp’)
- `account_id`
- `service_normalized` (e.g., ‘Compute’, ‘Storage’, ‘Database’)
- `sku_description`
- `usage_date`
- `cost_usd`
- `tags_normalized` (a key-value map or JSON field)
Tag normalization is a common failure point. AWS tags are case-sensitive, while GCP labels are not. A tag like `Team: Alpha` on AWS and `team: alpha` on GCP will be treated as two separate entities unless your normalization logic explicitly handles case conversion and key mapping. This is critical for accurate showback and chargeback. For a deeper dive into financial modeling, see our guide on the cost of cloud cost optimization software.
Step 3: Where Native Tools Like Cost Explorer Hit a Wall
AWS Cost Explorer does one thing well—visibility for AWS. Everything else is your problem. It cannot see your GCP or Azure spend, making it fundamentally unsuitable for true multi-cloud reconciliation. Attempting to use it for a multi-cloud environment is like trying to balance a company’s books by only looking at one bank account. You can get deep insights into a fraction of your spending, but you have no context for the total picture.
This CLI command is useful for quickly pulling AWS-specific costs, but it highlights the core limitation. The data it returns is an island.
# Get daily unblended costs for EC2 from the last 7 days from AWS
aws ce get-cost-and-usage --time-period Start=$(date -v-7d +%Y-%m-%d),End=$(date +%Y-%m-%d) \
--granularity DAILY \
--metrics "UnblendedCost" \
--filter '{ "Dimensions": { "Key": "SERVICE", "Values": [ "Amazon Elastic Compute Cloud - Compute" ] } }'
The output of this command is valuable, but it will never contain a line item for a Google Compute Engine instance. This forces teams into a painful cycle: analyze AWS in Cost Explorer, analyze GCP in its Billing console, export both to CSV, and manually merge them. This process is not FinOps; it’s data entry.
Conclusion: Automating Reconciliation for Actionable Insights
The manual process of multi-cloud cost reconciliation is unsustainable. It consumes valuable engineering time, is prone to errors, and delivers insights that are days or weeks out of date. The goal of FinOps is not to create perfect spreadsheets, but to drive intelligent decisions about resource usage. This requires automated data ingestion, normalization, and a unified platform for analysis.
Tools like Thalaxo are built to solve this specific problem. They connect directly to cloud billing APIs, handling the complex task of data mapping and normalization behind the scenes. This allows teams to focus on analyzing a single, coherent cost dataset rather than wrestling with data pipelines. As a newer platform launched in 2025, Thalaxo’s SOC 2 Type II audit is in progress (started June 2026), and while its integrations with GCP are expanding, its mature AWS support already provides the automated rightsizing and idle detection that manual reconciliation can’t offer. By automating the foundational layer of cost visibility, teams can move from reactive reporting to proactive optimization. Explore our pricing to see how it fits your scale.
