Skip to main content

Cost Tracking

Last Updated: 2026-03-06 Source: innovation-sandbox-on-aws-costs Captured SHA: c8f0523

Executive Summary

The ISB Cost Tracking service automatically collects billing data when Innovation Sandbox leases terminate, generating per-lease CSV cost reports stored in S3 with presigned download URLs. It operates as an event-driven satellite that listens for LeaseTerminated events, delays collection by a configurable window (default 8 hours with padding up to 168 hours) to allow AWS billing data to settle, then queries Cost Explorer cross-account in the Organization Management account and emits LeaseCostsGenerated events for downstream consumers.

Architecture Overview

The system uses a two-Lambda pipeline: a Scheduler Lambda creates one-shot EventBridge Scheduler entries on lease termination, and a Cost Collector Lambda executes the actual cost collection after the delay. Both deploy to the Hub account (us-west-2) via CDK, with a separate role stack deployed to the Organization Management account for cross-account Cost Explorer access.

Component Architecture

Event Flow

Core Components

Scheduler Lambda

Triggered by LeaseTerminated events on the ISB EventBridge bus. Creates a one-shot EventBridge Scheduler entry with a configurable delay (default 8 hours, controlled by BILLING_PADDING_HOURS). The schedule is configured with ActionAfterCompletion=DELETE for automatic cleanup.

Source: src/lambdas/scheduler-handler.ts

Cost Collector Lambda

The main processing function, triggered by EventBridge Scheduler after the billing delay. Executes a 10-step pipeline:

  1. Validate Payload: Zod schema validation of scheduler payload
  2. Get Lease Details: ISB API call with JWT authentication
  3. Assume Role: Cross-account STS AssumeRole for Cost Explorer access
  4. Calculate Billing Window: Lease start/end with configurable padding
  5. Query Cost Explorer: GetCostAndUsage with pagination, grouped by SERVICE and resource
  6. Generate CSV: Structured cost report with service-level breakdown
  7. Upload to S3: With SHA256 checksum verification
  8. Generate Presigned URL: 7-day valid download link
  9. Emit Event: LeaseCostsGenerated to ISB EventBridge bus
  10. Emit Metrics: Custom CloudWatch business metrics (TotalCost, ResourceCount, ProcessingDuration)

Source: src/lambdas/cost-collector-handler.ts

Cleanup Lambda

Daily maintenance function that identifies and removes orphaned schedules in the scheduler group. Handles edge cases where schedule auto-deletion fails.

Source: src/lambdas/cleanup-handler.ts

Supporting Libraries

ModulePurposeSource
cost-explorer.tsCost Explorer query with paginationsrc/lib/cost-explorer.ts
csv-generator.tsCSV report generationsrc/report-generator.ts
s3-uploader.tsS3 upload with checksum + presigned URLssrc/lib/s3-uploader.ts
event-emitter.tsEventBridge event emissionsrc/lib/event-emitter.ts
assume-role.tsCross-account STS role assumptionsrc/lib/assume-role.ts
isb-api-client.tsISB API calls with JWT authsrc/lib/isb-api-client.ts
date-utils.tsBilling window calculationsrc/lib/date-utils.ts
schemas.tsZod schemas for validationsrc/lib/schemas.ts

Event Schemas

Input: LeaseTerminated

{
"detail-type": "LeaseTerminated",
"source": "isb",
"detail": {
"leaseId": { "userEmail": "user@example.com", "uuid": "550e8400-..." },
"accountId": "123456789012",
"reason": { "type": "Expired" }
}
}

Output: LeaseCostsGenerated

{
"detail-type": "LeaseCostsGenerated",
"source": "isb-costs",
"detail": {
"leaseId": "550e8400-...",
"accountId": "123456789012",
"totalCost": 150.50,
"currency": "USD",
"startDate": "2026-01-15",
"endDate": "2026-02-03",
"csvUrl": "https://bucket.s3.amazonaws.com/lease.csv?signature=...",
"urlExpiresAt": "2026-02-10T12:00:00.000Z"
}
}

Infrastructure (CDK)

The infrastructure is organized into L3 constructs within the infra/ directory:

Source: infra/lib/cost-collection-stack.ts, infra/lib/cost-explorer-role-stack.ts

CostCollectionStack (Hub Account, us-west-2)

ConstructResources
LeaseCostsStorageS3 bucket (3-year lifecycle), bucket policy
CostCollectorFunctionScheduler Lambda, Cost Collector Lambda, Cost Collector DLQ, IAM roles
LeaseCostsObservabilityCloudWatch alarms, SNS topic, alarm actions
Stack-levelEventBridge rule, rule DLQ, scheduler group

CostExplorerRoleStack (Org Management Account, us-east-1)

Deploys a single IAM role (IsbCostExplorerAccess) with ce:GetCostAndUsage permission, trusting the Cost Collector Lambda's execution role in the Hub account.

Cross-Account Architecture

Cost Explorer data lives in the Organization Management account (where billing is consolidated), not in the Hub account. The Cost Collector Lambda assumes a cross-account role to query costs:

Cost Collector Lambda (Hub, us-west-2)
-> STS AssumeRole -> IsbCostExplorerAccess (OrgMgmt, us-east-1)
-> ce:GetCostAndUsage (read-only)

The role ARN is validated at module load time with a regex check to fail fast on deployment order errors.

Technology Stack

ComponentTechnology
RuntimeNode.js (TypeScript, ESM)
InfrastructureAWS CDK v2.240+ with L3 constructs
TestingVitest with coverage, performance tests
ValidationZod v4 schemas
Precisiondecimal.js for financial calculations
TracingAWS X-Ray SDK (aws-xray-sdk-core)
ISB Client@co-cddo/isb-client v2.0.0
CLICommander.js for local execution
CI/CDGitHub Actions

Observability

  • X-Ray Tracing: Subsegments for ISB API, Cost Explorer, CSV Generation, S3 Upload
  • Custom Metrics (ISBLeaseCosts namespace): TotalCost, ResourceCount, ProcessingDuration with AccountId dimension
  • CloudWatch Alarms: Lambda errors, DLQ messages, high Lambda duration, EventBridge rule delivery failures
  • Structured Logging: JSON with component, leaseId, accountId, elapsed time at each step
  • S3 Integrity: SHA256 checksums on upload with verification

Storage and Retention

  • S3 Bucket: isb-lease-costs-{account} with 3-year lifecycle policy
  • CSV Format: Per-lease cost reports with service-level breakdown
  • Presigned URLs: 7-day valid download links emitted in LeaseCostsGenerated events
  • Schedule Cleanup: Automatic via ActionAfterCompletion=DELETE, fallback manual deletion, daily cleanup Lambda for orphans

Generated from source analysis of innovation-sandbox-on-aws-costs at SHA cf659bb. See 00-repo-inventory.md for full inventory. Cross-references: 10-isb-core-architecture.md, 21-billing-separator.md.