Skip to main content

Age Reports

Starter+Enterprise

Age Reports surfaces AWS resources that have outlived their useful life. Stale EBS snapshots, old S3 objects past their retention window, forgotten RDS automated backups, and unattached volumes all accumulate silently and drive up your cloud bill. Age Reports gives you pre-built, configurable reports for every major aging category — no custom SQL required.


How Age Reports Work

Calabi Cloud Query queries your live AWS resource inventory and computes an age for each resource based on its creation date, last modification date, or last access date depending on the resource type. Resources are then bucketed into configurable age tiers and surfaced in the Age Reports UI with counts, sizes, and direct links to the cloud console.


Built-in Report Types

ReportResourceAge fieldDefault thresholds
EC2 Snapshotsaws_ebs_snapshotstart_time30 / 60 / 90 / 180 days
RDS Snapshotsaws_rds_db_snapshotsnapshot_create_time30 / 60 / 90 days
EBS Volumes (unattached)aws_ebs_volumecreate_time30 / 60 / 90 days
S3 Objects by age tieraws_s3_objectlast_modified30 / 60 / 90 / 180 / 365 days
AMIs (unused)aws_ec2_amicreation_date60 / 180 / 365 days
CloudWatch Log Groupsaws_cloudwatch_log_groupcreation_time90 / 180 days
Secrets Manager secretsaws_secretsmanager_secretlast_accessed_date30 / 90 days
IAM Access Keysaws_iam_access_keycreate_date90 / 180 days

Each report can be run on demand or scheduled. Thresholds can be customised per report in the Configure sub-module.


Configuring Thresholds

Thresholds define the breakpoints between age tiers. Calabi ships with sensible defaults aligned to common cloud hygiene standards, but you can adjust them to match your organization's data lifecycle policy.

To change thresholds:

  1. Navigate to Cloud Operations > Configure.
  2. Under Age Report Settings, find the report you want to adjust.
  3. Edit the day values for each tier (Current, Aging, Stale, Expired).
  4. Click Save. The change takes effect on the next report run.

Recommended threshold guidelines:

Policy typeSnapshot thresholdS3 object threshold
Strict (finance / healthcare)30 / 60 / 90 days30 / 60 / 90 / 180 days
Standard30 / 60 / 90 / 180 days60 / 90 / 180 / 365 days
Relaxed60 / 90 / 180 / 365 days90 / 180 / 365 days

Reading an Age Report

Each built-in report displays a summary table with:

  • Count — number of resources in each age tier
  • Total size — storage consumed (GB or TB) per tier
  • Estimated monthly cost — based on AWS pricing for the resource type and region
  • Oldest resource — the single oldest resource and its creation date
  • Resource list — an expandable table of individual resources with creation date, size, region, and tags

The summary bar chart provides a quick visual of how resources are distributed across age tiers.


Exporting Report Results

Reports can be exported in two formats:

FormatContentsHow to export
CSVFull resource list with all columnsClick Export CSV on any report
JSONStructured resource data for programmatic useClick Export JSON on any report

Exports respect the current filter settings — if you have filtered the report to a specific region or tag, the export reflects that filter.


Alerting on Aging Resources

You can configure an alert to fire when any report tier exceeds a count or size threshold.

Example: alert the #cloud-ops Slack channel when unattached EBS volumes in the "Expired" tier (90+ days) exceed 10 volumes.

  1. Open Cloud Operations > Age Reports.
  2. Select the EBS Volumes (unattached) report.
  3. Click Set Alert.
  4. Set the condition: Expired tier count > 10.
  5. Choose the notification channel: Slack — #cloud-ops.
  6. Set the alert schedule: Daily at 09:00 UTC.
  7. Click Save Alert.

Example SQL for Aging Queries

The built-in reports are powered by Calabi Cloud Query. You can write your own aging queries in Query Resources for custom use cases.

EC2 snapshots older than 90 days

SELECT
snapshot_id,
volume_id,
volume_size,
region,
start_time,
DATE_PART('day', NOW() - start_time) AS age_days,
description,
tags ->> 'Name' AS name
FROM
aws_ebs_snapshot
WHERE
owner_id = '123456789012'
AND DATE_PART('day', NOW() - start_time) > 90
ORDER BY
age_days DESC;

S3 objects by age tier (last 12 months)

SELECT
bucket_name,
CASE
WHEN DATE_PART('day', NOW() - last_modified) <= 30 THEN '0-30 days'
WHEN DATE_PART('day', NOW() - last_modified) <= 90 THEN '31-90 days'
WHEN DATE_PART('day', NOW() - last_modified) <= 180 THEN '91-180 days'
ELSE '180+ days'
END AS age_tier,
COUNT(*) AS object_count,
ROUND(SUM(size) / 1073741824.0, 2) AS total_size_gb
FROM
aws_s3_object
WHERE
bucket_name = 'my-data-bucket'
GROUP BY
bucket_name, age_tier
ORDER BY
age_tier;

Unattached EBS volumes

SELECT
volume_id,
volume_type,
size AS size_gb,
region,
create_time,
DATE_PART('day', NOW() - create_time) AS age_days,
state
FROM
aws_ebs_volume
WHERE
state = 'available' -- 'available' = not attached
AND DATE_PART('day', NOW() - create_time) > 30
ORDER BY
age_days DESC;

IAM access keys older than 90 days

SELECT
u.name AS iam_user,
k.access_key_id,
k.create_date,
k.status,
DATE_PART('day', NOW() - k.create_date) AS key_age_days
FROM
aws_iam_access_key k
JOIN aws_iam_user u ON k.user_name = u.name
WHERE
k.status = 'Active'
AND DATE_PART('day', NOW() - k.create_date) > 90
ORDER BY
key_age_days DESC;

  • Query Resources — Write custom SQL against live AWS inventory
  • Cost Analytics — Understand the cost impact of aging and orphaned resources
  • Configure — Adjust thresholds and configure alert channels