terraform apply Succeeded but AWS Did Not Change — ElastiCache Pending Modifications and the "No changes" Trap Since Provider 6.58
The replica came up at once, but automatic failover was pushed to Sunday. I planned the same state with provider 6.57 and 6.58, and settled on what "done" should mean
Sometimes terraform apply finishes green and the setting on AWS hasn't moved. I hit this while turning on automatic failover for ElastiCache. After reading this you'll know why it happens (AWS pending modifications), why plan looks completely different depending on the AWS provider version, and the one command that tells you whether the change is really live.
ElastiCache is AWS's managed Redis (Valkey). A pending modification is a change AWS has accepted but parked: "got it, I'll apply it in the maintenance window."
What happened
We added a replica to a single-node Redis and enabled automatic failover. In terraform that's two lines.
num_cache_clusters = 2 # 1 → 2
automatic_failover_enabled = true # false → true
apply succeeded, and the replica started coming up right away. Automatic failover, though, was still off.
AutomaticFailover disabled
PendingModifiedValues { AutomaticFailoverStatus: enabled }
On ElastiCache, ModifyReplicationGroup has ApplyImmediately defaulting to false (API docs). With false, some changes don't go in right away. They sit in PendingModifiedValues until maintenance. That cluster's window was on Sunday, and we applied on Thursday. We nearly spent three days believing failover was on.
Why did the replica come up immediately?
Same apply, one change immediate, one parked. That looked odd, so I read the provider source (terraform-provider-aws main, 2026-11-13).
The reason is simple. Raising num_cache_clusters calls the IncreaseReplicaCount API on its own, and that call hard-codes ApplyImmediately: true. Everything else is batched into one ModifyReplicationGroup call, and only that call carries your apply_immediately value.
So within one resource, whether a change is immediate or parked depends on which API that attribute goes through. Remembering it per resource ("ElastiCache defers things") will mislead you.
From provider 6.58, plan says "No changes"
This is the real trap.
When we hit it, plan kept showing automatic_failover_enabled = false -> true. apply had succeeded but the diff wouldn't go away, which at least told us something was off.
Provider 6.58.0 (2026-08-05) changed that. #48246: "Fix perpetual diff when changes are pending for the next maintenance window." Read now copies the values from PendingModifiedValues into state. A pending enabled is treated as already on.
To see it for myself I pulled provider 6.57.1 and 6.58.0 into OpenTofu 1.12.6. A local fake endpoint stood in for AWS and returned the pending state above, and I ran import, then plan.
6.57.1 ~ automatic_failover_enabled = false -> true (Plan: 0 to add, 1 to change)
6.58.0 No changes. Your infrastructure matches the configuration.
AWS still says disabled, and 6.58.0 calls it clean. When the fake endpoint returned the settled state (enabled, nothing pending), both said No changes. From 6.58 on, a clean plan does not mean the change is live.
We have no record of which provider version we were on. Since plan kept the diff, I assume it was older than 6.58.
Flipping only apply_immediately does nothing (from 6.58)
We fixed it by setting apply_immediately = true and applying again. Replaying that with 6.57.1, this is the request that goes out.
Action=ModifyReplicationGroup
ApplyImmediately=true
AutomaticFailoverEnabled=true
automatic_failover_enabled still has a diff, so the value is sent again, this time applied immediately.
Do the same on 6.58.0 and plan shows one line, + apply_immediately = true, and apply ends with "1 changed". But the fake endpoint logged zero Modify calls. In the source, ModifyReplicationGroup only runs when some other attribute has a diff, and apply_immediately isn't on that list. State already thinks failover is on, so there's nothing to send.
I didn't try this against real AWS. It's from the fake endpoint and the source code. If something is already parked and you want it applied now, resending the same value with --apply-immediately from the CLI looks like the reliable route (my assumption; I haven't run it).
aws elasticache modify-replication-group --replication-group-id <id> --automatic-failover-enabled --apply-immediately
Decide "done" by asking AWS directly
Neither a successful apply nor a clean plan is the bar.
aws elasticache describe-replication-groups --replication-group-id <id> --query 'ReplicationGroups[0].{now:AutomaticFailover,pending:PendingModifiedValues}'
If pending is empty and now has the value you want, you're done. Against the fake endpoint above, this prints "now": "disabled" and "pending": {"AutomaticFailoverStatus": "enabled"}. The parked change is right there.
RDS works the same way. apply_immediately defaults to false, and deferred changes pile up in PendingModifiedValues from describe-db-instances (RDS docs). The provider's aws_db_instance still only special-cases a pending engine version. Its docs say other pending values can show up as a diff in plan. I didn't run the RDS side myself.
How to choose
The change has to go in now → set
apply_immediately = truefrom the start. Note that this applies not just this change but every modification already pending (API docs). Something that needs a restart, like a node type or engine version change, may be hiding in there, so look atPendingModifiedValuesfirstThe change can wait for the window → leave it false and write "goes live in Sunday's window" in the PR or work log
Either way, the last check is that
PendingModifiedValuesis empty. Even more so after upgrading the provider to 6.58 or later
If "it said done but it wasn't" keeps happening on your terraform-managed AWS, ask us at https://www.negabaro.com/contact. Setting up checks like this together is part of what we do.
How It Works
ElastiCache and RDS default apply_immediately to false; some changes wait in PendingModifiedValues until maintenance
It differs per API even within one resource: the provider always sends replica increases (IncreaseReplicaCount) as immediate
From provider 6.58.0, pending values land in state and plan says No changes; a clean plan is not proof
From 6.58, flipping only apply_immediately to true makes zero ModifyReplicationGroup calls (checked with a fake endpoint)
Call it done only when describe-replication-groups shows PendingModifiedValues empty
Use Cases
References
- AWS — ElastiCache ModifyReplicationGroup (ApplyImmediately)
- AWS — ReplicationGroupPendingModifiedValues
- AWS — Using the Apply Immediately setting in RDS (PendingModifiedValues)
- terraform-provider-aws #48246 — Fix perpetual diff with pending changes (6.58.0)
- terraform-provider-aws — replication_group.go
- Terraform Registry — aws_elasticache_replication_group