Terraform
ignore_changes
sub-blocks
infrastructure-as-code
DevOps

Terraform, ignore_changes and sub-blocks

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

ignore_changes helps when Terraform should provision a resource but should stop reconciling one specific field after creation. The confusing part is nested configuration: sub-blocks are exposed as attribute paths in state, so you need to think in terms of paths and indexes rather than raw block syntax.

Core Sections

What ignore_changes suppresses

Inside a resource lifecycle block, ignore_changes tells Terraform to skip update diffs for listed attributes. Terraform still refreshes real infrastructure from the provider, but it stops treating those selected differences as something to fix.

hcl
1resource "aws_autoscaling_group" "api" {
2  name             = "api-asg"
3  min_size         = 2
4  max_size         = 6
5  desired_capacity = 3
6
7  lifecycle {
8    ignore_changes = [desired_capacity]
9  }
10}

That example is valid when an external autoscaler changes desired_capacity during normal operation. Terraform still manages the group itself, but it no longer fights runtime scaling.

How sub-blocks are represented

Nested blocks are usually stored as lists of objects. Because of that, Terraform often expects an indexed attribute path when you want to ignore one nested field.

hcl
1resource "aws_eks_node_group" "workers" {
2  cluster_name    = "demo"
3  node_group_name = "workers"
4  node_role_arn   = "arn:aws:iam::123456789012:role/demo"
5  subnet_ids      = ["subnet-1", "subnet-2"]
6
7  scaling_config {
8    desired_size = 2
9    min_size     = 1
10    max_size     = 5
11  }
12
13  lifecycle {
14    ignore_changes = [
15      scaling_config[0].desired_size
16    ]
17  }
18}

The [0] is not cosmetic. It refers to the first instance of that nested block in Terraform's internal representation. If a provider uses a single nested block, you still often address it as a one-element list.

Ignoring one nested field versus a whole block

The safest rule is to ignore the narrowest path possible. If only desired_size changes outside Terraform, ignore that field and continue managing min_size and max_size.

Sometimes a provider schema makes fine-grained targeting awkward. In those cases, engineers are tempted to ignore the whole block. That works, but it increases the risk that real configuration drift goes unnoticed. As a rule, ignore a parent block only when the provider's data model makes a more precise path impractical.

Finding the correct path

When you are not sure what path to use, inspect the plan and state output. Terraform already shows you how the provider structures nested data.

bash
terraform plan
terraform state show aws_eks_node_group.workers

If the state shows a nested field under scaling_config.0.desired_size, the matching lifecycle path is usually scaling_config[0].desired_size. That translation is often the missing step when people say ignore_changes does not work on sub-blocks.

When ignore_changes is the wrong fix

ignore_changes is not a general-purpose way to silence noisy plans. If Terraform keeps detecting a change because the configuration is incomplete, the provider normalizes values, or the ordering of repeated blocks is unstable, ignoring the diff may hide a real design issue.

Use it only when the drift is intentional and documented. Good examples include:

  • a deployment controller updating image tags
  • an autoscaler changing a replica count
  • a policy engine appending metadata

Bad examples include:

  • masking a provider bug you have not diagnosed
  • hiding a block that Terraform should still own
  • suppressing drift during a migration and then forgetting to remove the rule

Common Pitfalls

  • Writing the nested block name without an index. Terraform usually needs a path such as scaling_config[0].desired_size.
  • Ignoring too much. If one nested value drifts, do not ignore the whole block unless you have to.
  • Assuming ignore_changes prevents replacement. It only suppresses update diffs, not recreation caused by other fields.
  • Skipping state inspection. Without checking plan or state output, it is easy to target the wrong path.
  • Failing to document external ownership. A later maintainer may remove the rule and reintroduce churn in production.

Summary

  • 'ignore_changes tells Terraform to stop reconciling selected attributes.'
  • Nested blocks are normally addressed as indexed attribute paths.
  • Prefer the smallest ignore rule that matches the real external drift.
  • Use terraform plan and terraform state show to confirm the correct path.
  • Treat ignore_changes as a precise exception, not as a way to hide unclear infrastructure behavior.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.