AWS Accounts
Connect an AWS account to CostLens in one click — CloudFormation provisions the role automatically and CostLens detects the connection with no copy-pasting.
CostLens reads your AWS cost data and resource configuration using a cross-account IAM role. The guided Add Account wizard is the fastest way to connect — it opens a pre-filled CloudFormation stack, creates the role for you, and detects the connection automatically. No IAM console work and no values to copy back into CostLens.
Prefer to do it by hand?
If your organization requires manual IAM review, the manual setup further down still works — same trust model, same role, just typed in yourself.
How it works
| Step | What happens |
|---|---|
| 1. Choose access level | Read-Only (monitoring, reporting, recommendations) or Read/Write (adds Auto-Fix). Read-Only is the default and is enough for everything except applying fixes. |
| 2. Review exactly what's granted | Before anything is created, CostLens shows the precise IAM permissions it's about to request — no surprises. |
| 3. Authorize | Opens AWS CloudFormation with the template, stack name, and parameters pre-filled. You click Create stack. |
| 4. CostLens detects it automatically | The stack's own notifier reports back to CostLens the moment it finishes — you don't need to return to CostLens or paste anything. |
| 5. First sync starts | Billing sync, optimization checks, and AI explanations run automatically once connected. |
Connect a new AWS account
Step 1 — Add Account → AWS → choose access level
From the Accounts page, click Add Account, choose AWS, then choose Read-Only or Read/Write. The next screen shows exactly what CostLens is about to be granted:
| Access level | Grants | Enables |
|---|---|---|
| Read-Only | ReadOnlyAccess, Cost Explorer reads (ce:Get*/ce:List*), Compute Optimizer signals, CUR ingestion (if configured), resource-inventory enumeration | Billing visibility, inventory, anomaly detection, recommendations & savings estimates |
| Read/Write | Everything in Read-Only, plus the specific EC2/EBS/CloudWatch-Logs/S3 actions CostLens's reversible remediations use — never AdministratorAccess or broad admin | Everything in Read-Only, plus Apply Fix and Auto-Fix |
The trust model is a cross-account IAM role assumed via sts:AssumeRole with a unique External ID (confused-deputy protection) — CostLens never creates or stores AWS access keys for this flow.
Step 2 — Authorize
Click Authorize. This opens AWS CloudFormation Quick-Create in a new browser tab, signed into whichever AWS account your browser is currently authenticated as, with everything pre-filled:
- The CostLens-hosted template
- A stack name unique to your CostLens organization (
costlens-<id>) - Your External ID (also shown in CostLens if you need to copy it)
- The access level you chose
Make sure you're signed into the right AWS account
Quick-Create runs against whatever AWS account is active in that browser tab. Double-check the account switcher in the top-right of the AWS Console before clicking Create stack.
Step 3 — Create stack
In the AWS tab, review the stack (nothing to edit — the parameters are already filled in) and click Create stack. CloudFormation provisions an IAM role named CostLensAccessRole, trusting CostLens's account with your External ID, and attaches exactly the permissions your chosen access level requires.
Step 4 — CostLens connects automatically
Once the stack reaches CREATE_COMPLETE, its notifier reports the account ID straight back to CostLens — the wizard's "Finishing automatically…" screen updates on its own within a few seconds, no action needed. First sync (billing → optimization checks → AI explanations) starts immediately.
Stack taking a while, or want to skip waiting?
If auto-detection hasn't finished after about 25 seconds, the wizard offers a manual fallback: type in your 12-digit AWS account ID (found in your AWS Console) and click Connect account to finish immediately — useful if outbound webhooks are blocked in your AWS environment.
Reconnecting, or connecting a second AWS account
CostLens can't see into an AWS account before you grant it access, so it can't always know in advance whether "Authorize" should create a new role or reuse one that already exists. It handles this in two ways:
Automatic reuse. If your organization previously connected an AWS account to CostLens and later removed it, clicking Add Account → AWS shows "Found and verified your existing connection" immediately — CostLens already checked that account's role still works and skips CloudFormation entirely. Click Continue to finish.
Explicit choice. If your organization has connected AWS before but CostLens can't automatically verify a reusable role (e.g. you're adding a genuinely different, second AWS account), the Review screen replaces the single Authorize button with two options:
| Button | Use when |
|---|---|
| New AWS account | You're signed into an AWS account CostLens has never touched — opens Quick-Create (Create stack) |
| Reconnect / update existing | You're signed into an AWS account CostLens has already set up before — opens Update stack, which refreshes the role's trust policy with the current External ID instead of creating a new one |
Seeing "Resource of type AWS::IAM::Role... already exists"?
That means you clicked New AWS account (or plain Authorize) while signed into an AWS account that already has a CostLensAccessRole from an earlier connection. Close that error and use Reconnect / update existing instead — it updates the same stack rather than trying to create a duplicate.
If you go ahead and connect an account that turns out to already be active in your CostLens organization, you'll see "This account already exists — it's already connected. Nothing was added again" on the success screen, rather than a misleading "new account connected" message.
Connect an entire AWS Organization (multi-account)
If you manage many AWS accounts under an AWS Organization, click Connect an organization from the Accounts page instead of adding accounts one at a time:
- Pick a seed account — an already-connected account whose role has organization-level reach (typically the management account).
- First time only: expand "Grant organization-wide access" for a generated script that extends the seed account's role to every member account (via CloudFormation StackSets).
- Click Discover & connect — CostLens enumerates every member account under the seed and connects each one, showing a live per-account result (Connected / Failed / Skipped). Accounts already connected are updated, not duplicated; a failed account gets an "Enter details manually" link so one bad account never blocks the rest.
Alternative: create the IAM role by hand
If you'd rather not use CloudFormation (e.g. your organization requires manual IAM review before any role is created), you can create the role yourself and paste its details into CostLens instead — same trust model, same permissions, same role name.
Step 1 — AWS Console → IAM → Roles → Create role
Log in to console.aws.amazon.com. Search for IAM, open Roles, and click Create role.
Step 2 — Configure the trusted entity
| Field | Value |
|---|---|
| Trusted entity type | AWS account |
| Which AWS account | Another AWS account |
| Account ID | CostLens's AWS account ID (shown in CostLens's onboarding wizard) |
| Options | Check "Require external ID" |
| External ID | Your CostLens organization's External ID — shown on the wizard's manual-entry step ("CostLens External ID", with a Copy button) |
Leave MFA unchecked. Click Next.
Step 3 — Attach permissions
Read-only scan — search for ReadOnlyAccess and attach the AWS-managed policy:
# Covered by ReadOnlyAccess (scanning)
ce:GetCostAndUsage, ce:GetCostForecast
ec2:DescribeInstances, DescribeVolumes, DescribeAddresses
rds:DescribeDBInstances
cloudwatch:GetMetricStatistics
Apply Fix permissions (only if you chose Read/Write) — after creating the role, open it → Add permissions → Create inline policy → JSON, name it CostlensApplyFix, and paste:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "CostlensApplyFix",
"Effect": "Allow",
"Action": [
"ec2:DeleteVolume",
"ec2:DeleteSnapshot",
"ec2:TerminateInstances",
"ec2:ModifyVolume",
"ec2:ModifyInstanceAttribute",
"ec2:StopInstances",
"ec2:StartInstances",
"ec2:ReleaseAddress",
"ec2:CreateTags",
"ssm:SendCommand",
"ssm:GetCommandInvocation",
"rds:DeleteDBInstance",
"rds:StopDBInstance",
"rds:StartDBInstance",
"rds:AddTagsToResource",
"scheduler:CreateSchedule",
"scheduler:CreateScheduleGroup",
"scheduler:GetScheduleGroup",
"iam:GetRole",
"iam:CreateRole",
"iam:PutRolePolicy",
"iam:PassRole",
"logs:PutRetentionPolicy",
"logs:DescribeLogGroups"
],
"Resource": "*"
}]
}What each permission enables:
ec2:DeleteVolume / DeleteSnapshot— remove unused EBS volumes & snapshotsec2:TerminateInstances— terminate long-stopped EC2 instancesec2:StopInstances / StartInstances / ModifyInstanceAttribute— schedule & rightsize EC2 instancesec2:ModifyVolume + ssm:*— expand full EBS volumes live (no downtime)ec2:ReleaseAddress— release unattached Elastic IPsrds:DeleteDBInstance— delete idle RDS databasesrds:StopDBInstance / StartDBInstance— schedule RDS stop-startscheduler:* + iam:*— create EventBridge schedules for automated stop-startlogs:PutRetentionPolicy / DescribeLogGroups— set 30-day retention on CloudWatch Log Groups
Step 4 — Name the role and create it
Name the role CostLensAccessRole (the same name CloudFormation would have used — CostLens assumes this name by default, so using it means you don't have to paste the ARN back). Verify the Trusted entities section shows CostLens's account ID and your External ID condition, then click Create role.
Step 5 — Paste into CostLens
Back in the CostLens wizard's manual-entry step, enter your 12-digit AWS account ID. Leave IAM role ARN blank (CostLens assumes CostLensAccessRole in that account) — or paste the full ARN if you used a different role name. Click Connect account.
Additional billing source: Cost & Usage Reports (optional)
Once an AWS account is connected via IAM Role, its account card shows a Billing Data Source panel where you can optionally layer on Cost & Usage Reports (CUR) — a more granular, resource-level billing export than Cost Explorer provides. This reuses the same CostLensAccessRole you already created (just add s3:GetObject/s3:ListBucket on the CUR bucket to its policy) — no separate role. See the dedicated Cost & Usage Reports guide for the full setup.
Kubernetes (EKS) cost & optimization
The ReadOnlyAccess policy attached above already covers everything CostLens needs for EKS — eks:List*/Describe*, Auto Scaling, EC2 and CloudWatch reads for the node-pool checks, plus Cost Explorer for Kubernetes cost. No extra IAM is required. Two capabilities depend on an AWS billing setting (not a permission):
Node-pool optimization — no setup needed
CostLens follows each EKS managed node group to its EC2 Auto Scaling Group and reads node CPU from CloudWatch. Idle / right-sizing / Spot node-pool recommendations appear on the Recommendations page automatically. See Kubernetes Optimization.
Per-cluster node cost — activate the cluster cost-allocation tag
In AWS Billing → Cost allocation tags, activate the AWS-generated aws:eks:cluster-name tag. AWS then tags each cluster's node compute (EC2 / EBS / networking) so CostLens can total it per cluster in the Kubernetes panel on the Billing page.
Per-namespace & per-workload cost — enable Split Cost Allocation Data
In AWS Cost Management → Cost allocation tags, enable Split Cost Allocation Data for EKS, then activate the aws:eks:namespace (and aws:eks:workload-name for workload-level) tags. AWS splits each node's cost across its pods and tags the result, which CostLens reads via Cost Explorer. Data appears within ~24 hours. See Kubernetes Costs.
No agent, no cluster access
CostLens reads EKS cost and utilisation entirely from Cost Explorer and CloudWatch — there is nothing to install in the cluster and no Kubernetes API access is required. Cost Explorer bills $0.01 per request on your account; CostLens caches Kubernetes cost queries for 6 hours and records the namespace trend only once a month, so it adds only a few cents.
Adding Apply Fix permissions later
Connected with Read-Only and want Auto-Fix later? Open your CostLensAccessRole IAM role in AWS → Add permissions → Create inline policy → JSON and paste the CostlensApplyFix JSON from the manual-setup section above.
Without the Apply Fix policy, the "Apply Fix" button on recommendations is disabled. Scanning and recommendations work fully with Read-Only access alone.
First sync phases
After connecting, a first-sync progress panel appears. It runs three phases in sequence:
| Phase | Duration |
|---|---|
| Fetching billing data | 10 s – 2 min — pulls monthly and daily cost history from AWS Cost Explorer |
| Running optimisation checks | 30 s – 3 min — scans EC2, EBS, RDS, networking, Lambda, and CloudWatch for waste |
| Generating AI explanations | 20 s – 1 min — Aevi writes plain-English explanations and savings estimates |
The panel auto-dismisses after completion. The account card then shows In sync and a last-synced timestamp.
Managing connected accounts
| Action | Who can do it | Description |
|---|---|---|
| Sync Now | Operators, Admins | Triggers an immediate billing sync |
| Test Connection | Operators, Admins | Re-validates the role without changing anything |
| Edit Credentials | Admins only | Update the account name, or swap in a different Role ARN |
| Remove Account | Admins only | Disconnects and permanently deletes all associated data — cannot be undone. CostLens remembers the role/External ID even after removal, so reconnecting the same account later can skip CloudFormation entirely (see "Automatic reuse" above). |
Sync status reference
| Status | Meaning |
|---|---|
| Not synced | Account has never been synced |
| Syncing… | A sync is in progress |
| In sync | Last sync completed successfully |
| Sync failed | The sync encountered an error — expand the card to see details and a Try again button |
Common errors and fixes
| Error | Fix |
|---|---|
Resource of type 'AWS::IAM::Role'... already exists (in the AWS Console, during Quick-Create) | This AWS account already has a CostLensAccessRole from an earlier connection. Close the error and use Reconnect / update existing on the Review screen instead of Create/Authorize — see "Reconnecting, or connecting a second AWS account" above. |
| "Found and verified your existing connection" appears unexpectedly | CostLens detected a working role from a previous connection for your organization and is offering to skip CloudFormation — this is expected when reconnecting a removed account. Click Continue, or close the wizard and use Add Account again if you actually meant to add a different AWS account. |
| Stack finishes but CostLens doesn't detect it | Auto-detection can occasionally miss a network hiccup or take longer than expected — CostLens automatically retries for a few minutes if the role validation itself is the holdup. If it's still not connected after that, enter your 12-digit AWS account ID in the manual-fallback field on the same screen. |
AccessDenied: not authorized to assume role / IAM_ROLE_NOT_TRUSTED | The External ID in the role's trust policy doesn't match, or the role was deleted. Open the role in AWS → Trust relationships → verify sts:ExternalId matches the value CostLens shows you exactly. |
| AWS Cost Explorer not enabled | Go to AWS Console → Cost Explorer → Enable Cost Explorer. It can take up to 24 hours for data to appear. Alternatively, use Cost & Usage Reports as a billing data source — CUR does not require Cost Explorer. |
| The requested resource does not exist (role ARN) | Double-check the Role ARN is copied exactly as shown in the AWS Console, including the correct 12-digit account number. |
| Sync stuck in one phase for more than 10 minutes | Click Force retry or click Sync Now on the account card to restart. |