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
| Action | Resource | Why |
|---|---|---|
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:ListBucket | the export bucket | Finds each month's delivery. |
s3:GetObject | the 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.
- Open Settings, then Integrations, select AWS, and open the Connect tab.
- 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.
- 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:GetCarbonFootprintSummaryfor whoever creates the stack;CreateCarbonExportset tofalseon that page leaves it out. - 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 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:
Code
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
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
- Under More connection options, choose AWS IAM Console.
- Create an IAM role with the Trust policy Costfluent shows. It names Costfluent's principal and your External ID.
- Attach the Permissions policy to the role.
- 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.
- 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.
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.
| Dimension | For AWS | From |
|---|---|---|
| Provider | aws | The connection |
| Provider name | Amazon Web Services; for a Marketplace charge, the seller | PublisherName |
| Sub-account | The member account's ID; the payer account's for a charge without one | SubAccountId, else BillingAccountId |
| Service | The AWS service | ServiceName |
| Region | The region's name; Global for a charge without one | RegionId, RegionName |
| Resource | The resource's name, or the last segment of its ID | ResourceName, else ResourceId |
| Charge category | Usage, Purchase, Tax, Credit or Adjustment, as the export states it | ChargeCategory |
| Service category | The FOCUS category the export states; a model sold through AWS Marketplace for Amazon Bedrock, which the export files under Other, is AI and Machine Learning | ServiceCategory, ServiceName |
| SKU | The usage type, such as USE1-Claude4.6Sonnet-input-tokens; the SKU ID where the export states none | SkuMeter, else SkuId |
| SKU ID | The product's SKU code, such as B4BCD9J5Z8MQHZ5K | SkuId |
| Operation | The operation billed, such as RunInstances or PutObject | x_Operation |
| Charge description | The line's own text, such as $0.096 per On Demand Linux m5.large Instance Hour | ChargeDescription |
| Resource type | The kind of resource, as the export states it | ResourceType |
| Invoice ID | The invoice the line is billed on | InvoiceId |
| Invoice issuer | The AWS entity that invoices the line, such as Amazon Web Services EMEA SARL or Amazon Web Services, Inc. | InvoiceIssuerName |
| Billing period | The month invoiced, such as 2026-03; a correction to an earlier month is filed under the month that bills it | BillingPeriodStart |
| Product family, Resource group | Never filled; they hold Azure cost | |
| Tag | Every key of the row's tags, cost categories included, plus aws:payerAccountId | Tags, BillingAccountId |
| Segment | Your allocation rules | Segments and allocation rules |
| Cluster, Namespace | Never filled; they hold Kubernetes cost (Connect Kubernetes) | |
| Virtual tag | Your virtual tag rules | Virtual 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
versionto~> 0.4, then runterraform init -upgradeandterraform apply. - IAM console: add the
CreditsReadOnlystatement 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.
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
Code
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: setCreateCarbonExporttofalse. Its usual cause is a creator withoutsustainability:GetCarbonFootprintSummary; the connection then has no carbon emissions data.FocusExportorExportBucket: setCreateCostExporttofalse, 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.FocusExportorCarbonExportwithCannot 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 (BucketExistsandExportExistsset totrue) and setCreateCarbonExporttofalse.
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.