Connect a source

Connect AWS

Connect an AWS account with a CloudFormation stack, the AWS CLI, Terraform or an IAM role, and read its cost from a FOCUS 1.2 Data Export.

Costfluent reads AWS cost through a read-only IAM role in your account. The role trusts one Costfluent principal, and only with the external ID Costfluent issues to your organization. No access keys are exchanged.

Cost comes from an AWS Data Export in the FOCUS 1.2 format, delivered daily to a private S3 bucket in your own account. It carries amortized cost, list cost, charge categories, regions, resource IDs and tags. Until the first delivery arrives, and for any month the export does not cover, Costfluent reads Cost Explorer instead.

For the carbon footprint report, a second Data Export of AWS's CARBON_EMISSIONS table delivers AWS's monthly emissions estimates to the same bucket and prefix.

How Costfluent connects

ActionResourceWhy
ce:GetCostAndUsage*History before the export's first delivery, accounts without an export, and the monthly control total.
ce:GetReservationUtilization*The Reserved Instances the account holds, with their utilization and end dates, read daily into Commitments.
ce:GetSavingsPlansUtilizationDetails*The Savings Plans the account holds, with their utilization and end dates, read daily into Commitments.
organizations:ListAccounts*Which member accounts a management account's cost covers.
cost-optimization-hub:ListRecommendations*The rightsizing, idle, upgrade and commitment purchase recommendations Cost Optimization Hub computes, read daily into Savings.
cost-optimization-hub:ListEnrollmentStatuses*Whether the account is enrolled in Cost Optimization Hub, so a hub that is not turned on shows as the step that turns it on rather than as a refused permission.
billing:GetCredits*The credits AWS has granted the account, or in a management account its organization, with their remaining amounts and expiry, read daily onto the connection's Credits card.
s3:ListBucketthe export bucketFinds each month's delivery.
s3:GetObjectthe export bucket's objects under costfluent/Reads that delivery.

Cost Explorer, Organizations, Cost Optimization Hub and billing:GetCredits have no resource-level permissions, so their resource is *; it grants no access to anything else in the account. billing:GetCredits only reads the credits: the role cannot redeem or change one. The S3 grant exists only when there is an export. It reads object contents only under the export's prefix, costfluent/, and lists the whole bucket, which shows key names but not contents. The carbon emissions export lies under the same prefix, so the role reads it with the same two permissions.

Terraform module versions from 0.4.0 and stacks created from the current template grant exactly this. A role created earlier lacks billing:GetCredits and keeps working: AWS refuses Costfluent's daily credit read, and the grants entered on the Credits card count instead (Credits) until you update the role. A role created with module version 0.2.1 or earlier, or from the template of that time, can also read every object in the export bucket.

Prerequisites

Connect the management account of your AWS Organization once. Its export covers every member account, and Costfluent lists the members on the connection. Connecting a member account as well would count its cost twice, so Costfluent refuses a connection whose accounts another AWS connection already covers.

A member account connected on its own gets its own export, which holds only that account's cost. A service control policy can block Data Exports in a member account; there, set CreateCostExport to false on AWS's quick-create page, and the account is read from Cost Explorer only. A standalone account is treated like a management account.

Connect

Connect with the AWS Console

This is the default route.

  1. Open Settings, then Integrations, select AWS, and open the Connect tab.
  2. Keep the suggested Display name or enter your own, such as Production, then select Connect Costfluent via AWS Console. AWS opens a CloudFormation quick-create page in us-east-1, with every parameter filled in. Keep the console in that region: anywhere else, CloudFormation refuses the template (Troubleshooting). The stack keeps its export bucket in us-east-1 too; to keep the delivered files elsewhere, such as in the EU, connect with Terraform or the IAM console.
  3. Acknowledge that the stack creates IAM resources, and create it. The stack also creates the FOCUS 1.2 export and the carbon emissions export, each under a name of its own, so the account can also be connected to another Costfluent organization with a stack of its own. The carbon export needs sustainability:GetCarbonFootprintSummary for whoever creates the stack; CreateCarbonExport set to false on that page leaves it out.
  4. Wait on the Costfluent page. When the stack finishes, it reports back, and "AWS connected. AWS delivers the first export within 24 to 72 hours; until then, Costfluent reads Cost Explorer." appears without anything to paste. If the browser blocked the new tab, Open the AWS console beside the waiting message opens it.

The AWS Connect tab with a short introduction, Connect Costfluent via AWS Console and More connection options

The Connect tab for AWS, with the console route and More connection options.

The link is valid for 24 hours and connects only to the organization that created it. If Costfluent's part of the stack fails, the page and CloudFormation both show the reason, and the stack rolls back. If another part of the stack fails first, the page says "The stack has not reported back. Its “Events” tab in CloudFormation names the resource that failed." and links Troubleshooting, which says which parameter turns that resource off.

Connect with the AWS CLI

On the Connect tab, keep the suggested Display name or enter your own, then under More connection options, choose AWS CLI. Costfluent shows an aws cloudformation create-stack command with the same template and parameters, and the connection takes that name when the stack reports back. Run it with credentials for the account you are connecting:

TerminalCode
aws cloudformation create-stack \ --stack-name Costfluent-1a2b3c4d \ --template-url <the template URL Costfluent shows> \ --capabilities CAPABILITY_IAM \ --region us-east-1 \ --parameters ParameterKey=CostfluentPrincipalArn,ParameterValue=... # and the rest

The stack reports back exactly as the console route does.

Connect with Terraform

Under More connection options, Terraform shows the same configuration with your principal and external ID. The costfluent/cost-access/aws module creates the role and, when you name a bucket, the bucket, the cost export and the carbon emissions export (carbon_export_name, costfluent-carbon by default). The costfluent_aws_provider_info data source reads the principal and external ID for you:

Code
provider "aws" { region = "us-east-1" } data "costfluent_aws_provider_info" "this" {} module "costfluent_aws" { source = "costfluent/cost-access/aws" version = "~> 0.4" costfluent_principal_arn = data.costfluent_aws_provider_info.this.principal_arn external_id = data.costfluent_aws_provider_info.this.external_id cost_export_bucket_name = "acme-costfluent-export" # omit in a member account } resource "costfluent_provider" "aws" { key = "aws" display_name = "AWS" credentials = module.costfluent_aws.credentials settings = module.costfluent_aws.settings }

costfluent_provider retries for up to three minutes while the new role propagates through IAM. The module's settings output carries carbon_export_name when it created the carbon emissions export. Creating that export needs sustainability:GetCarbonFootprintSummary for whoever applies the module; without it, set carbon_export_name = "" and the module creates none. To keep the delivered files in the EU, set cost_export_bucket_region; the export itself always runs in us-east-1.

Connect with the IAM console

  1. Under More connection options, choose AWS IAM Console.
  2. Create an IAM role with the Trust policy Costfluent shows. It names Costfluent's principal and your External ID.
  3. Attach the Permissions policy to the role.
  4. Enter the role's IAM role ARN. The Display name is filled in from the Connect tab; enter one if it is empty. If you created a FOCUS 1.2 Data Export yourself, tick I created a FOCUS 1.2 Data Export myself and enter its Export bucket and Export bucket region, and the Carbon export name if you also created a carbon emissions export. Without an export, Costfluent reads Cost Explorer.
  5. Select Connect.

The Permissions policy lets the role read objects only under the prefix costfluent and list the whole bucket, which shows key names but not contents. If the connection sets another export_prefix through the Public API or Terraform, change the prefix in the policy to match.

If you create the export yourself, it must be a FOCUS 1.2 with AWS columns export (FOCUS_1_2_AWS) with every column selected, daily granularity, CSV with GZIP compression, and Overwrite existing data export file, delivered to a bucket the role can read, under the prefix costfluent with the export name costfluent-focus. A carbon emissions export beside it is a Data Export of the CARBON_EMISSIONS table with every column, in Parquet, to the same bucket and prefix; costfluent-carbon is the name the module gives it. The CloudFormation stack names its two exports costfluent-focus-… and costfluent-carbon-…, with a suffix that differs for each connection.

Data and freshness

History and first delivery

Connecting reaches back as far as your plan's backfill does, and at most six months (Manage connections). AWS delivers the first export within 24 to 72 hours of creating it. Until then, the connection shows cost from Cost Explorer, and Costfluent replaces it with the export's rows once the delivery arrives. Costfluent re-reads the current month on every sync, and the previous month for the first fifteen days, because AWS updates the previous month for up to two weeks after it closes. When AWS updates a closed month's export after that, for example for a refund or a credit, Costfluent collects that month again, as far back as your plan's history reaches and at most three years. A month first read from Cost Explorer is read again from the export once the export delivers it.

Months before the export's first delivery, and any month it does not cover, come from Cost Explorer, which reports cost by service and account but carries no tags and no resources: rules cannot claim that cost, and tag coverage counts it as untagged. A cost report, Coverage on the Segments page and the "Tag coverage" card name those months.

Yes No Read again once theexport delivers it A month ofAWS cost Has the exportdelivered it? Export rows, withtags and resources Cost Explorer: by serviceand account, no tagsand no resources
A month comes from the data export once the export delivers it, with tags and resources; until then, and for any month the export does not cover, it comes from Cost Explorer, by service and account only.

A new export starts with the current month. To bring up to 14 months of history into it, open a case with AWS Support (Billing, Data Exports) from the management account that holds the export, naming the export and the months, and asking to backfill it; a backfill cannot reach back before the account existed. Then collect those months again with a full sync once AWS confirms: Collect older months on the connection's Imports card while it offers older months, or the Public API's sync with "fullSync": true (Automatic syncing).

One day of one export, the organization or account it covers, may hold at most 2,560,000 rows and 4 GiB of cost data. A larger day stops the connection with an error that names the day; contact Costfluent support to collect it.

What it costs you

Costfluent reads the export from outside AWS, so reading it is S3 data transfer out on your bill. A daily export is typically a few megabytes a month. Each Cost Explorer request Costfluent makes costs USD 0.01, and Costfluent makes them only for months the export does not cover, at least two each time it collects one (cost by service, then credits, refunds and tax), for connection checks, and for the monthly control total. Costfluent reads the account's credits with one GetCredits request a day per connection; as of 2026-10-26, AWS's pricing pages list no charge for it.

Carbon emissions export

AWS publishes each month's emissions by the 21st of the next month, and the export's first delivery reaches back to January 2022. Costfluent reads it on the 22nd (Carbon footprint). A stack created from an earlier template, or a module version without carbon_export_name, created no carbon emissions export: create one as Connect with the IAM console describes, or apply the current module version, then set carbon_export_name on the connection through Terraform's settings or the Public API's PUT /v1/providers/{providerId}. Settings you send replace the stored ones, so send every export setting the connection has with it.

Reporting dimensions

What each group-by dimension of a cost report holds for an AWS connection, and the export column it comes from.

DimensionFor AWSFrom
ProviderawsThe connection
Provider nameAmazon Web Services; for a Marketplace charge, the sellerPublisherName
Sub-accountThe member account's ID; the payer account's for a charge without oneSubAccountId, else BillingAccountId
ServiceThe AWS serviceServiceName
RegionThe region's name; Global for a charge without oneRegionId, RegionName
ResourceThe resource's name, or the last segment of its IDResourceName, else ResourceId
Charge categoryUsage, Purchase, Tax, Credit or Adjustment, as the export states itChargeCategory
Service categoryThe FOCUS category the export states; a model sold through AWS Marketplace for Amazon Bedrock, which the export files under Other, is AI and Machine LearningServiceCategory, ServiceName
SKUThe usage type, such as USE1-Claude4.6Sonnet-input-tokens; the SKU ID where the export states noneSkuMeter, else SkuId
SKU IDThe product's SKU code, such as B4BCD9J5Z8MQHZ5KSkuId
OperationThe operation billed, such as RunInstances or PutObjectx_Operation
Charge descriptionThe line's own text, such as $0.096 per On Demand Linux m5.large Instance HourChargeDescription
Resource typeThe kind of resource, as the export states itResourceType
Invoice IDThe invoice the line is billed onInvoiceId
Invoice issuerThe AWS entity that invoices the line, such as Amazon Web Services EMEA SARL or Amazon Web Services, Inc.InvoiceIssuerName
Billing periodThe month invoiced, such as 2026-03; a correction to an earlier month is filed under the month that bills itBillingPeriodStart
Product family, Resource groupNever filled; they hold Azure cost
TagEvery key of the row's tags, cost categories included, plus aws:payerAccountIdTags, BillingAccountId
SegmentYour allocation rulesSegments and allocation rules
Cluster, NamespaceNever filled; they hold Kubernetes cost (Connect Kubernetes)
Virtual tagYour virtual tag rulesVirtual tags

A model sold through AWS Marketplace for Amazon Bedrock states its usage in millions of tokens, as Units; Costfluent stores it as Tokens, one by one, so the Usage measure sums it with other providers' tokens. Other Bedrock usage keeps the unit the export states.

aws:payerAccountId groups and filters like any tag, but Costfluent adds it itself, so it does not make a line tagged for Tagged, tag coverage or a coverage alert (Tags and tag coverage).

Until the first export delivery, and for any month the export does not cover, the rows come from Cost Explorer and carry only Service, Sub-account, the aws:payerAccountId tag and the usage month as Billing period: Region is Global and Resource is empty. Credits and tax are rows of their own, with Charge category Credit or Tax and the Service Credit or Tax; a refund is a Usage row with the Service Refund, marked as a correction, so Include refunds decides whether it counts. Every other row is Usage.

Update or disconnect

After connecting

The Manage tab lists the connection by its display name, with its AWS account ID, Role and Export bucket. Open the gear icon beside it to see whether the role can still be assumed and the bucket read, which workspaces the connection feeds, which billing months have been imported, and the Accounts card: the management account as Collecting and each member account as Covered. Run checks runs those checks again and reports each one separately.

Update the role

A role created before billing:GetCredits was added keeps working without it (How Costfluent connects). To let Costfluent read your credits from AWS, give the role the action the way you created it:

  • CloudFormation stack: in the CloudFormation console in us-east-1, update the stack, replace its template with the template URL in the command Costfluent shows under More connection options, AWS CLI (Connect with the AWS CLI), and keep every parameter's value.
  • Terraform: set the module's version to ~> 0.4, then run terraform init -upgrade and terraform apply.
  • IAM console: add the CreditsReadOnly statement of the Permissions policy Costfluent shows under More connection options, AWS IAM Console to the role's policy.

Costfluent's next daily read then fills in the grants from AWS.

Removing access

Delete the stack, or destroy the Terraform configuration, to remove the role; Costfluent's access ends with it.

aws cloudformation delete-stack --stack-name Costfluent-1a2b3c4d --region us-east-1

CloudFormation keeps the export bucket, so your history stays in your account. terraform destroy tries to delete the bucket too, and S3 refuses while it still holds files. Remove the connection in Costfluent as well; that erases the cost it imported (Remove a connection).

Troubleshooting

One heading per message, as the connection page, the Connect tab or AWS's quick-create page shows it. Run checks on the connection page runs the two connection checks again.

Costfluent could not authenticate with the AWS credentials.

The role cannot be assumed: its trust policy does not name Costfluent's principal, the external ID in it is not the one Costfluent issued to your organization, or the role was deleted. Compare the role's trust policy with the one under AWS IAM Console on the Connect tab (Connect with the IAM console); a stack created by Costfluent carries both.

Costfluent could not read cost data from AWS.

The role is assumed, but Cost Explorer or the export bucket did not let it read; the message beside the check names the cause. The role needs ce:GetCostAndUsage and, when there is an export, s3:ListBucket on the export bucket and s3:GetObject on its objects under the export's prefix (costfluent/ unless the connection sets another). If one is missing, restore the permissions policy (How Costfluent connects). After terraform destroy or a deleted stack, the role itself is gone, and the first check fails instead.

The bucket or its region can also be set wrong. A message that Costfluent could not address the bucket in its region means the Export bucket region is not one S3 can be reached in, for example a misspelt region. A message carrying S3's own refusal, such as PermanentRedirect or AuthorizationHeaderMalformed for a bucket in another region, or InvalidBucketName, asks you to compare the Export bucket and Export bucket region, which it calls export_bucket and export_bucket_region, with the bucket in the S3 console. A message that AWS could not be reached means S3 did not answer, which says nothing about your settings: connecting saves the connection anyway, and Costfluent checks it again automatically.

Cost Optimization Hub is not turned on for this AWS account

The connection stays healthy and cost keeps arriving; only AWS's own savings findings wait. The Savings recommendations check reads Not run with this sentence, and Savings names the connection while the queue is empty. Turn the hub on from the management account: in the AWS console, open Billing and Cost Management, then Cost Optimization Hub, and select Enable with member accounts included, or run

TerminalCode
aws cost-optimization-hub update-enrollment-status --status Active --include-member-accounts --region us-east-1

Opt in to AWS Compute Optimizer too. AWS takes up to a day to produce the first recommendations, which then appear under Savings, and the next check reads Passed.

Costfluent could not read savings recommendations from AWS.

Cost still arrives, and the connection shows as degraded until this is fixed. Cost Optimization Hub refused the role: the permissions policy lacks cost-optimization-hub:ListRecommendations (How Costfluent connects). A role whose policy also lacks cost-optimization-hub:ListEnrollmentStatuses, as one created before Costfluent read the enrolment does, cannot tell that from a hub that is not turned on, so the message beside the check names both causes. Add both actions to the role's policy, and the next check tells them apart; a hub that is not turned on is then the entry above.

The stack could not connect

CloudFormation ran, but Costfluent's part of it failed; the page shows the reason after the colon, and the stack rolls back. Fix the cause it names and start again from the Connect tab, which issues a new link (Connect with the AWS Console).

The stack has not reported back. Its “Events” tab in CloudFormation names the resource that failed.

Another part of the stack failed before Costfluent's, so nothing reported back. Open the stack in CloudFormation (us-east-1), find the first failed resource on its Events tab, delete the stack, and start again from the Connect tab with the parameter that resource needs:

  • CarbonExport: set CreateCarbonExport to false. Its usual cause is a creator without sustainability:GetCarbonFootprintSummary; the connection then has no carbon emissions data.
  • FocusExport or ExportBucket: set CreateCostExport to false, for example where a service control policy blocks Data Exports in a member account. The connection then reads Cost Explorer only, without resources and tags.
  • FocusExport or CarbonExport with Cannot create duplicate export name, or on AWS's quota: an account holds at most two FOCUS 1.2 exports and two carbon emissions exports. Each new link names its exports apart, so a new link gets past a duplicate name. For a third stack in the account, read an export the account already delivers (BucketExists and ExportExists set to true) and set CreateCarbonExport to false.

A quick-create link also expires after 24 hours.

Template format error: Unrecognized resource types: [AWS::BCMDataExports::Export]

AWS's quick-create page shows this when the console is in another region than us-east-1, for example after the region was switched in its header. The stack's Data Exports exist only in us-east-1, so CloudFormation refuses the template before creating anything. Cancel, switch the console to US East (N. Virginia), and start again from the Connect tab.

AWS account … is already collected by another AWS connection in this organization

The account you are connecting is a member of an organization whose management account is already connected, or is that management account: its cost would be counted twice. Connect the management account once; its members are collected through it (Prerequisites). The refused stack rolls back but keeps its export bucket: delete the stack if it is still listed, then the empty costfluent-export-… bucket in us-east-1.

Resource names and tags are missing

The rows still come from Cost Explorer, which groups cost by service and account only: no resource, no tags, and the region Global. AWS delivers the first export 24 to 72 hours after the stack creates it, and Costfluent replaces those rows once it arrives (History and first delivery). A connection made with CreateCostExport set to false has no export and keeps reading Cost Explorer.