The Lifecycle of a Resource
Every resource in a provider must implement four operations that map to the standard CRUD (Create, Read, Update, Delete) lifecycle. Terraform Core calls these operations at specific points during the plan/apply cycle.
1. Create
- When called: Resource exists in config but not in state (first terraform apply).
- Input: req.Plan — what the user declared in HCL.
- Action: POST to the API to create the resource.
- Output: resp.State — the complete resource state including all computed values (IDs, timestamps, defaults).
- Critical: You must save all attributes to state, including ones the API computed. If you omit an attribute, Terraform will treat it as null on the next plan.
2. Read
- When called: terraform refresh, terraform plan (to detect drift), and before every terraform apply.
- Input: req.State — the last known state (contains the resource ID).
- Action: GET from the API using the stored ID.
- Output: resp.State — the current real-world state of the resource.
- Critical: If the API returns a 404 (resource was deleted outside Terraform), you must call resp.State.RemoveResource(ctx). This signals to Core that the resource no longer exists, and Core will plan to recreate it. Failing to handle 404 causes an infinite error loop.
3. Update
- When called: Resource exists in both config and state, but they differ.
- Input: req.Plan (desired state) and req.State (current state).
- Action: PUT or PATCH to the API with the changed attributes.
- Output: resp.State — the new state after the update.
- Important: Some APIs do not support in-place updates for certain attributes (e.g., you cannot rename a server — you must destroy and recreate it). Mark such attributes with PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()} in the schema. Terraform will then plan a destroy+create instead of an update.
4. Delete
- When called: Resource exists in state but not in config (terraform destroy or resource removed from .tf file).
- Input: req.State — the current state (contains the ID to delete).
- Action: DELETE to the API.
- Output: Nothing — if successful, Core automatically removes the resource from state.
- Important: If the API returns 404 during delete (resource already gone), treat this as success, not an error. Idempotent deletes prevent failures during partial cleanup scenarios.