How Resources Behave
A resource block is a promise: "this thing should exist, like this." Every time you plan, Terraform checks that promise against what it built before and picks an action for each resource. There are only four, and you can predict all of them.
The rule
Only in config: create. Only in state: destroy. Changed: update, or replace if it cannot bend.
Crumb's two resources:
resource "aws_s3_bucket" "assets" {
bucket = "crumb-prod-assets"
}
resource "aws_instance" "web" {
ami = "ami-0123456789abcdef0"
instance_type = "t3.micro"
}Each resource has an address, aws_instance.web, made of its type and local name. The address is how state remembers which real object belongs to which block. The type's prefix, aws_, tells Terraform which provider manages it.
For each address, Terraform compares configuration with state (refreshed from the real cloud):
| Situation | Action |
|---|---|
| In configuration, not in state | create |
| In state, not in configuration | destroy |
| In both, an updatable argument differs | update in place |
| In both, an argument differs that cannot change on a live object | replace: destroy, then create |
| In both, no difference | nothing |
Whether an argument can be updated is decided by the provider. Changing instance_type can be done on an existing server; changing its ami cannot, so the plan marks that argument with # forces replacement.
Resources also expose attributes you did not set, such as id or public_ip, which the provider fills in after creation.
One surprise: renaming the local name, from web to server, changes the address. Terraform sees one address vanish and a new one appear, so it plans destroy and create. A moved block tells Terraform it is the same object under a new name.
The shortcut
Ask two questions per resource: "Where does it exist: config, state, or both?" and, if both, "Can the changed argument bend?"
New bucket block for logs
Config only. Create.
The trap: assuming every edit is an in-place update. Always look for forces replacement before you apply, because replacing a server loses anything stored only on it.
Drills
Answer fast — trust the rule.
A resource is in state but its block was deleted from the configuration. What does the plan do?
What decides whether a changed argument is updated in place or forces replacement?
You rename resource "aws_instance" "web" to "server" and change nothing else. What does the plan show, without a moved block?
Which of these is an attribute the provider fills in rather than an argument you set?
Remember
- Config only: create. State only: destroy. Both and changed: update, or replace if it cannot bend.
- Shortcut: where does it exist, and can the change bend?
- Trap: renaming a block changes its address; look out for
forces replacement.
