Repository navigation
feat: add reserved-instances-check workflow - #214
Merged
Merged
Conversation
Weekly check of the RDS and ElastiCache capacity in service against the active reservations, in size-flexible units per pool (reservation product and instance family). Posts to Slack when some capacity is uncovered or when a reservation ends within 60 days. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
HarmonicTons
requested review from
PetitLepton
and
a balanced review from Copilot
October 22, 2026 13:00
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved coverage-accounting and inventory-handling errors can suppress alerts or abort monitoring, while notification logic can generate false alarms.
8 open issues
Add missing RDS instance size normalization weights · New Skip Aurora Serverless instances before size normalization · New Use product-aware units for ElastiCache coverage · New Include billable RDS rebooting and upgrading states · New Include rebooting ElastiCache clusters in inventory · New Require a positive uncovered gap before alerting · New Suppress expired-exemption alerts when capacity is covered · New Grant caller job OIDC and contents permissions · New
What changed in this PR
Adds a reusable reservation-monitoring workflow to detect uncovered RDS and ElastiCache capacity and warn about upcoming reservation expirations.
Changes:
- Adds a Python checker with pooled capacity accounting, grace periods, dated exemptions, and offline fixture support.
- Adds a composite action and reusable workflow for AWS access and conditional Slack notifications.
- Documents the required IAM policy and a scheduled caller example.
| File | Description |
|---|---|
| README.md | Documents reservation monitoring and caller configuration. |
| actions/reserved-instances-check/check.py | Collects inventory, evaluates coverage, and generates reports. |
| actions/reserved-instances-check/action.yml | Exposes checker inputs and report outputs. |
| .github/workflows/reserved-instances-check-v1.yml | Configures AWS credentials and conditional Slack notifications. |
Review effort: Balanced
…s and transient statuses Unknown or non-reservable instance sizes (db.serverless, 32xlarge and above) are skipped and listed instead of aborting the run. Instances in billable transient statuses such as rebooting or upgrading now count as capacity; only non-billed statuses are excluded. A pool is reported only on a positive gap, and an expired exemption alone no longer notifies. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Product-specific reservation accounting can incorrectly report full coverage and suppress alerts for on-demand charges.
2 open issues
8 resolved since last review
Use product-aware units for ElastiCache coverage Skip Aurora Serverless instances before size normalization Add missing RDS instance size normalization weights Suppress expired-exemption alerts when capacity is covered Require a positive uncovered gap before alerting Include rebooting ElastiCache clusters in inventory Include billable RDS rebooting and upgrading states Grant caller job OIDC and contents permissions
Review effort: Balanced
…match SQL Server exactly AWS applies reservations to the instances of an I/O-Optimized Aurora cluster at 1.3 normalized units per standard unit, and SQL Server reservations are not size-flexible. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ions on the exact class Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



AI;DR
Ajoute un workflow pour controller que nos DB + Elasticache tournent bien sur des instances réservées et pas on-demand. Pour éviter de payer pour rien, comme en ce moment depuis début septembre. Poste une message sur #ops quand une instance problématique est détectée.
What
New reusable workflow
reserved-instances-check-v1and composite actionreserved-instances-check: compare the RDS and ElastiCache capacity in service with the active reservations, in size-flexible units per pool (reservation product + instance family, Multi-AZ counts double, the way AWS applies reservations), and post to Slack#opswhen some capacity is not covered or when a reservation ends withinexpiry_warning_days. Nothing is posted when everything is covered, unlessalways_notifyis set.Resources created less than
grace_daysago are ignored, and a resource meant to run without reservation for a while carries the tagreservation-exempt-until=YYYY-MM-DD: it is listed as exempted until that date, then reported again. The thresholdmin_uncovered_unitsapplies to the pool, not to the instance, so a fleet of small instances is reported as a whole.Context: the MySQL and PostgreSQL reservations expired on 2026-09-29 and nobody was told. Run offline against a copy of the account's current state (
check.py --fixture-dir), the check reports exactly that:mysql / db.m6g16 units uncovered,mysql / db.t4g1 unit,postgresql / db.t4g21.5 units, while Aurora and ElastiCache (renewed on 2026-10-08) are covered. The plan is to merge this, run the check from infra-ci to see the alert, then buy the reservations and see it clear.The script only needs Python 3 and the AWS CLI, both present on the GitHub runners. The CI role needs the
common_reservations_read_onlypolicy, added in sencrop/infra-ci together with the scheduled caller.yamllint and actionlint pass.
🤖 Generated with Claude Code