Ignore Autoscaling Changes
Adds ignore_changes = [read_capacity, write_capacity] to DynamoDB tables. Prevents Terraform from reverting autoscaler adjustments.
When to use this rule
Use this when: Your DynamoDB tables use Application Auto Scaling for read/write capacity, and every terraform plan shows capacity diffs.
Do not use this when: Your DynamoDB tables use PAY_PER_REQUEST (on-demand) billing mode, which has no read/write capacity attributes. Or you manually manage provisioned capacity without auto scaling.
Why this rule exists
DynamoDB tables with auto scaling enabled have their read and write capacity adjusted continuously by AWS Application Auto Scaling. Terraform sees these changes on every plan and proposes reverting them.
The fix is straightforward (add ignore_changes) but requires modifying every DynamoDB resource in every module. With upstream terraform-aws-modules, you cannot add this without forking.
Related Terraform and OpenTofu issues
| Repository | Issue | Title |
|---|---|---|
| hashicorp/terraform | #27360 | A method to override configuration and meta arguments within a module |
Limitations this rule answers
Per-module pages under Workarounds where this rule is the answer, each with the native workaround first and the diff the rule makes:
Affected resources
| Resource | Service | Why |
|---|---|---|
aws_dynamodb_table | Amazon DynamoDB | Capacity attributes managed by Application Auto Scaling |
What this rule does
Adds a lifecycle { ignore_changes = [...] } block to each matching resource. Terraform and OpenTofu will ignore external changes to the listed attributes on subsequent plans.
Ignored attributes: read_capacity, write_capacity
Before and after
Before (upstream module):
resource "aws_dynamodb_table" "this" {
# ... resource configuration ...
tags = var.tags
}After (with Ignore Autoscaling Changes applied):
resource "aws_dynamodb_table" "this" {
# ... resource configuration ...
tags = var.tags
lifecycle {
ignore_changes = [read_capacity, write_capacity]
}
}The only change is the rule transformation. All existing arguments, outputs, and module behavior remain identical.
Real-world scenario
A DynamoDB table with auto scaling adjusted read capacity from 5 to 50 during a traffic spike. The next terraform plan proposed reverting capacity back to 5, which would have caused throttling during peak hours.
The example above is illustrative. To see this rule run for real, open it in the
Rules Playground β it applies lifecycle_ignore_autoscaling_changes to a
reviewed upstream module that actually declares the resources this rule targets,
and shows the diff the registry would serve. No account needed.
Known limits
- Only affects
aws_dynamodb_table. Does not coveraws_dynamodb_global_tableor other DynamoDB resources. - Does not ignore changes to other auto-scaled attributes like GSI capacity.
- Only
.tfand.tofufiles are read. Modules written in JSON syntax (.tf.json,.tofu.json) are left untouched. - Only the module's own directory and its first-level
modules/*submodules are processed. Modules that this module calls by source URL are separate downloads and are handled on their own request.
Default configuration
These are the values the rule ships with. They are not settable from a module source URL: ?rules= carries rule names only, so a per-request enable uses exactly the defaults below. Your organization sets them per rule, in its Baseline or in a ruleset, from the Operational Rules page; see Baseline rules and rulesets.
| Parameter | Type | Default | Description |
|---|---|---|---|
ignore_changes | list(string) | ["read_capacity", "write_capacity"] | Lifecycle attributes to ignore |
resource_types | list(string) | ["aws_dynamodb_table"] | Target resource type patterns |
The rule's definition
The HCL this rule is written in - its parameters, their shipped defaults, and the transformers it runs - is published at lifecycle_ignore_autoscaling_changes, alongside every other selectable rule.
How to enable
On a framework host, per request:
Add ?rules=lifecycle_ignore_autoscaling_changes to your HTTPS module source, using the id exactly as written.
module "example" {
source = "https://soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws?version=5.0.0&rules=lifecycle_ignore_autoscaling_changes"
}A ?rules= list is either all bare names, which replace your organization's rules for that download, or all - prefixed names, which subtract from them. Mixing the two is refused with a 400 rather than silently treated as a replacement. To add this rule on top of your organization's rules instead, use ?add_rules=lifecycle_ignore_autoscaling_changes; a bare ?rules= list cannot be combined with it, because a bare list already replaced the set there was something to add to.
The + add prefix was removed. It reached the registry only when written %2B, and a literal + in a query string decodes to a space everywhere, so ?rules=+lifecycle_ignore_autoscaling_changes arrived as a bare name with a leading space β one step from silently replacing your organization's rules. Any +, in either spelling, is now a 400 naming ?add_rules=.
On your organization's host:
Add the rule to the organization's Baseline, which applies to every module served from the bare organization form <alias>.compliance.tf/<namespace>/<name>/<provider>, or to a named ruleset that one module selects with ?ruleset=<name> on the HTTPS form of that address. A project environment (<alias>.compliance.tf/<project>/<env>/<module>) serves the rules frozen in its bound snapshot instead: there the rule goes into the config draft and reaches the environment by promotion. On both organization forms ?rules= and ?add_rules= are refused with a 400 β including the subtractive - prefix β rather than dropped, so you cannot mistake an ignored override for an applied one. Change the configuration, not the URL. See Baseline rules and rulesets for the configuration flow, and registry resolution for how the address forms differ.
Failure modes
| Scenario | Result |
|---|---|
| Applied to a PAY_PER_REQUEST table | The lifecycle block is still added, and the configuration stays valid. On-demand tables set no provisioned capacity, so there is nothing for the rule to suppress. |
| You switch from PROVISIONED to PAY_PER_REQUEST | The ignore_changes block has no effect on PAY_PER_REQUEST tables. No action needed. |
Terraform and OpenTofu compatible
This rule works with both Terraform (1.x+) and OpenTofu (1.6+). It reads ordinary HCL, and anything it changes stays ordinary HCL, so the module behaves the same under either tool.
Help us improve this page
Operational Rules are a new feature. We'd love your feedback on this rule page β what's useful, what's missing, what's confusing. Share feedback.