MCMMCM DocsEngineering (Internal)
HLDModulesFinOps
v1.2 is unreleased — see v1.1 for the current stable release.

Cost

AWS and Azure cost ingestion, reconciliation, normalization, and stored cost fields.

Cost

The Cost area of FinOps collects per-resource cost data for supported AWS and Azure accounts. Daily jobs load provisional usage for the previous day, and the monthly reconciliation job refreshes the previous month once provider billing data is finalized.

For canonical provider, resource type, and category terminology, see the Provider and Resource Reference.

Collection Schedule

ProcessTimingPurpose
Daily collectionOnce per dayIngest yesterday's cost data at per-resource granularity.
Monthly reconciliation9th of each monthRe-fetch the full previous month and mark finalized entries as reconciled.

Provider billing data is finalized at different times:

ProviderData Finalization DateReconciliation Behavior
AWS7th of the following monthRe-fetch the full previous month from AWS CUR on the 9th.
Azure5th of the following monthRe-fetch the full previous month from Azure Cost Details on the 9th.

Provider modifications made after the reconciliation date are not captured by the monthly reconciliation run.

AWS Cost Collection

AWS cost data is collected from AWS Cost and Usage Report data exported to an MCM-managed S3 bucket.

Required IAM Permissions

PermissionPurpose
s3:CreateBucketCreate the CUR export bucket during setup.
s3:ListBucketList available CUR export objects.
s3:GetObjectDownload CUR CSV files.
s3:DeleteObjectClean up old export objects.
bcm-data-exports:ListExportInspect existing billing data exports.
bcm-data-exports:CreateExportCreate the CUR 2.0 export.
bcm-data-exports:GetExportRead export configuration and status.
bcm-data-exports:DeleteExportRemove the export when the account is deleted or FinOps expires.
cur:putReportDefinitionCreate or update CUR report definitions where required.
ce:ListCostAllocationTagsRead cost allocation tags.
ce:UpdateCostAllocationTagsStatusEnable required cost allocation tags.
organizations:DescribeOrganizationRead AWS organization context for billing setup.

CUR Setup

StepDetail
Create S3 bucketBucket name MCM-cur-{AccountID} in us-east-1.

CUR Export Settings

SettingValue
Export typeStandard data export
Export nameMCM-cur-report or preferred configured name
Data tableCUR 2.0
Include resource IDsYes
Time granularityDaily
Compressiongzip text/csv
File versioningOverwrite existing
S3 bucketMCM-cur-{AccountID}
S3 path prefixMCM or preferred configured prefix
S3 regionus-east-1

Reference: AWS CreateExport API

AWS Daily Flow

  1. Download the CUR CSV file from the configured S3 path.
  2. Filter data for yesterday, such as July 3 00:00:00-23:59
    when the job runs on July 4.
  3. Normalize the data to the stored cost schema.
  4. Store cost records with reconciled=false.
  5. Maintain a maximum of three monthly folders in the CUR bucket.
  6. Delete the oldest monthly folder on the 9th of each month.

AWS Failure Scenarios

ScenarioAction
Cannot create CURRetry on every Job until CUR is set up.
Cannot connect to S3Retry up to 3 times with a 10-second delay; log and skip if still failing.
CSV file not found in S3Retry up to 3 times with a 10-second delay; log and skip if still failing.
Invalid data in CSVLog the problematic record and skip it.
Missing S3 permissionsStore the error with Job details.

Azure Cost Collection

Azure cost data is collected from the Azure Cost Details Report API and normalized into the same stored schema as AWS cost data.

Required Permission

PermissionPurpose
Microsoft.CostManagement/generateCostDetailsReport/readGenerate and download Azure cost details reports.

Azure Daily Flow

  1. Generate cost data with the Azure Cost Details Report API, filtered for yesterday.
  2. Download the report CSV from the Blob link returned by the API response.
  3. Normalize the data to the stored cost schema.
  4. Store cost records with reconciled=false.

Reference: Azure Cost Details Report API

Azure Failure Scenarios

ScenarioAction
Azure Cost Details API failureRetry up to 3 times with a 10-second delay.
Invalid CSV dataLog and skip invalid records.
Missing API permissionStore error in Job Detail.
API rate limit hitRetry based on API response headers.

Stored Cost Fields

Cost records are stored in the FinOps data model used by the API and dashboards. Labels and provider tags are stored separately from the normalized cost row so they can be searched and joined by account and resource.

FieldTypeDescriptionRequired Behavior
ProviderstringCanonical provider name, such as AWS or Azure.Stored for every record.
Account IDstringAccount identifier from provider onboarding.Stored for every record.
Account NamestringCloud account display name.Stored when available.
RegionstringResource region.Skip the record if missing.
CategorystringCategory such as Compute, Network, or Storage.Default to Other when unknown.
Resource TypestringCanonical uppercase snake-case resource type such as AWS_EC2 or AZURE_VM.Default to Other when unknown.
Resource NamestringResource display name.Default to Resource ID when missing.
Resource IDstringUnique provider resource identifier.Skip the record if missing.
Cost TypestringDIRECT_COST or TRANSFER_COST.Default to DIRECT_COST.
Cost Sub-typestringProvider usage metric or charge subtype.Default to Other when unknown.
QuantitynumberAmount of resource usage.Skip the record if missing.
Quantity UnitstringUsage unit such as Hrs or GB.Skip the record if missing.
Cloud CostnumberCost in the provider billing currency.Skip the record if missing.
Cloud Cost UnitstringBilling currency code such as USD.Skip the record if missing.
CostnumberCost normalized to USD for cross-provider dashboards.Stored when conversion is available.
Start DatedateStart of the cost interval.Skip the record if missing.
End DatedateEnd of the cost interval.Skip the record if missing.
Reconciledbooleanfalse for daily records, true after monthly reconciliation.Stored for every record.
Tagslist of {key, value}Raw provider tags.

AWS CUR Field Mapping

MCM FieldMapping LogicAWS CUR Field
ProviderStatic value: AWS.
RegionExtract from product data where key is region.product
Resource TypeRegex match on Resource ID.line_item_resource_id
CategoryDerived from the canonical resource mapping in the Provider and Resource Reference.
Resource NameExtract from labels where key is user_name.resource_tags
Resource IDDirect map.line_item_resource_id
Cost TypeTRANSFER_COST if value contains transfer or data transfer, else DIRECT_COST.product_product_family
Cost Sub-typeDirect map.line_item_usage_type
QuantityDirect map.line_item_usage_amount
Quantity UnitDirect map.pricing_unit
Cloud CostDirect map.line_item_unblended_cost
Cloud Cost UnitDirect map.pricing_currency
Start DateExtract start from interval.identity_time_interval
End DateExtract end from interval.identity_time_interval
Reconciledtrue for monthly reconciliation; false for daily collection.

Azure Field Mapping

MCM FieldMapping LogicAzure Field
ProviderStatic value: Azure.
RegionDirect map.ResourceLocation
Resource TypeRegex match on Resource ID.ResourceId
CategoryDerived from the canonical resource mapping in the Provider and Resource Reference.
Resource NameDirect map.ResourceName
Resource IDDirect map.ResourceId
Cost TypeTRANSFER_COST if MeterName contains Data Transfer, else DIRECT_COST.MeterName
Cost Sub-typeConcatenate MeterCategory and MeterSubCategory.MeterCategory, MeterSubCategory
QuantityDirect map.Quantity
Quantity UnitDirect map.UnitOfMeasure
Cloud CostDirect map.CostInBillingCurrency
Cloud Cost UnitDirect map.BillingCurrencyCode
Start DateDirect map.BillingPeriodStartDate
End DateDirect map.BillingPeriodEndDate
Reconciledtrue for monthly reconciliation; false for daily collection.

On this page