What I understood from the question is that example_dependency.dependency_b is planned to be replaced, while example_resource.main is planned to be updated. Terraform then breaks the “replace” into separate “delete” and “create” steps, and so you’re observing the following order:
- Delete the old
example_dependency.dependency_b
- Create the new
example_dependency.dependency_b
- Update
example_resource.main to refer to the new example_dependency.dependency_b
Terraform cannot update example_resource.main until it knows the new value of example_dependency.dependency_b, and in the “delete then create” replace ordering the delete must happen before the create, and so this seems like the only workable order of these operations.
You mentioned that you were able to get the behavior you wanted by using create_before_destroy, and so I assume (but haven’t checked) that’s causing Terraform to use the following order instead:
- Create the new
example_dependency.dependency_b
- Update
example_resource.main to refer to the new example_dependency.dependency_b
- Delete the old
example_dependency.dependency_b
In this case the new value of example_dependency.dependency_b.id can be known before the old example_dependency.dependency_b has been destroyed.
Another different way to do it would be to configure example_resource.main with replace_triggered_by = [example_dependency.dependency_b.id], which should then force example_resource.main to also get replaced in this case, leading to the following order (as long as you aren’t also using create_before_destroy):
- Delete the old
example_resource.main
- Delete the old
example_dependency.dependency_b
- Create the new
example_dependency.dependency_b
- Create the new
example_resource.main, referring to the new example_dependency.dependency_b
or, if you use both replace_triggered_by and create_before_destroy together:
- Create the new
example_dependency.dependency_b
- Create the new
example_resource.main, referring to the new example_dependency.dependency_b
- Delete the old
example_resource.main
- Delete the old
example_resource.main
I think the crux of the problem is that the object associated with example_resource.main cannot exist without the object associated with example_dependency.dependency_b, and so updating example_resource.main in-place isn’t actually a viable plan in this case but Terraform does not have enough information to conclude that itself. Using replace_triggered_by is how you can tell Terraform about the stronger dependency relationship between these objects to make it plan a workable order of operations.
Allowing providers to give Terraform more information to automatically resolve this situation was one of the motivations for my proposal in issue #22094, but with the currently-defined provider protocol there just isn’t any way for Terraform to infer this extra requirement automatically.
(When I say “stronger dependency” above I mean that a normal dependency in Terraform just means “actions for this must happen before actions for that”, but it doesn’t directly affect which actions are planned. replace_triggered_by expresses a different kind of dependency: “this becomes invalid if that is deleted”, or as I called it in that proposal on GitHub: “containment”.)