Terraform
Migrating attribute ForceNew triggers
This page explains how to migrate ForceNew triggers from SDKv2 to the framework.
Background
In Terraform, sometimes a resource must be replaced when the value of an
attribute changes. To do this in SDKv2, you use the ForceNew field. To do this
in the framework, implement the same behavior with a RequiresReplace plan
modifier. Refer to Plan Modification - Attribute Plan
Modification
in the framework documentation for more details about plan modifiers.
Migrating ForceNew triggers
In SDKv2, when you set the ForceNew field on an attribute's schema.Schema
it triggers a replace, such as a destroy-create cycle, whenever the attribute's value
is changed.
In the framework, you implement the same behavior using the
resource.RequiresReplace plan modifier on your attribute's schema.Attribute
implementation.
The following code block shows a resource attribute with the ForceNew field
set to true with SDKv2.
SDKv2
func resourceExample() *schema.Resource {
    return &schema.Resource{
        /* ... */
        Schema: map[string]*schema.Schema{
            "attribute_example": {
                ForceNew:    true
                /* ... */
The following shows the same section of provider code after the migration.
Framework
func (r *ThingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
    resp.Schema = schema.Schema{
        /* ... */
        Attributes: map[string]schema.Attribute{
            "attribute_example": schema.StringAttribute{
                PlanModifiers: []planmodifier.String{
                    stringplanmodifier.RequiresReplace(),
                    /* ... */
Migration Notes
Remember the following differences between SDKv2 and the framework when completing the migration.
- In both SDKv2 and framework, ForceNewandRequiresReplace, respectively, only trigger a replace if the attribute is not computed. In the framework, if an attribute which is computed requires that the resource be replaced when it is changed, implement a plan modifier that triggers the replacement. Refer to RequiresReplacePlanModifier for an example, but remember that each implementation requires different logic and you may need to detect whether the plan has already been modified.
Examples
Migrate a resource attribute
The following example shows the implementation of the ForceNew field of the
exampleResource resource's example_attribute attribute with SDKv2.
SDKv2
func exampleResource() *schema.Resource {
    return &schema.Resource{
        Schema: map[string]*schema.Schema{
            "example_attribute": {
                ForceNew: true,
                Type:     schema.TypeMap,
                /* ... */
            },
            /* ... */
        },
        /* ... */
    }
}
The following shows the same section of provider code after the migration.
This code forces the replacement of a exampleResource resource when the value
of the example_attribute attribute is changed. The example does this using the
PlanModifiers field within the exampleResource attribute's schema.
Framework
func (r *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
    resp.Schema = schema.Schema{
        Attributes: map[string]schema.Attribute{
            "example_attribute": schema.MapAttribute{
                PlanModifiers: []planmodifier.Map{
                    mapplanmodifier.RequiresReplace(),
                },
                /* ... */
            },
            /* ... */
        },
    }
}