> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ubiquex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Timeouts and ignore_changes

> Override provider-default wait times and suppress drift on externally-managed attributes.

Cloud providers set sensible default timeouts for resource operations, but production infrastructure regularly exceeds them. A large RDS instance can take 45 minutes to provision. An EKS cluster routinely needs 20–30 minutes. When Pulumi's default timeout expires before the resource is ready, the apply fails — even though the resource would have succeeded with more time. The `timeouts` sub-block lets you override these provider defaults per operation (create, update, delete). Paired with `ignore_changes`, which prevents Pulumi from resetting attributes managed externally — passwords rotated by a secrets manager, tags applied by a cost allocation tool, scaling counts adjusted by an autoscaler — you have precise control over how Pulumi interacts with slow or partially-external resources.

## What you'll learn

* How `timeouts` overrides provider-default operation wait times
* How `ignore_changes` prevents drift from triggering unwanted updates
* When to combine both on the same resource

***

## Why this matters

<Info>
  Timeout failures are apply-time surprises — the plan succeeds, then the apply hangs and times out. Setting explicit timeouts in your `.iac` source means CI pipelines and operators see consistent, predictable behaviour rather than intermittent failures on slow resources.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  # timeouts override provider-default wait times per operation.
  # Useful for slow resources: large RDS instances, EKS clusters, NAT gateways.
  unit "aws_rds_instance" "db" {
    identifier          = "myapp-${input.env}"
    allocated_storage   = 50
    engine              = "postgres"
    engine_version      = "15"
    instance_class      = "db.r6g.xlarge"
    username            = "admin"
    password            = "placeholder"
    skip_final_snapshot = true

    # Suppress drift on password — rotated externally by secrets manager.
    lifecycle {
      ignore_changes = ["password"]
    }

    timeouts {
      create = "60m"
      update = "30m"
      delete = "20m"
    }
  }

  # EKS clusters routinely take 20-30 minutes — extend the default.
  unit "aws_eks_cluster" "main" {
    name     = "myapp-${input.env}"
    role_arn = "arn:aws:iam::123456789012:role/eks-role"

    vpc_config = {
      subnet_ids = ["subnet-abc123", "subnet-def456"]
    }

    lifecycle {
      ignore_changes = ["tags"]
    }

    timeouts {
      create = "30m"
      delete = "20m"
    }
  }
  ```

  ```hcl inputs.iac theme={"theme":"css-variables"}
  input "env" {
    type    = "string"
    default = "dev"
  }
  ```

  ```hcl outputs.iac theme={"theme":"css-variables"}
  output "cluster_endpoint" {
    value = unit.aws_eks_cluster.main.endpoint
  }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "timeouts-and-ignore-changes"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]
  }

  backend "local" {
    path = ".ubx/state"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="Timeouts are passed to the Pulumi resource options">
    The `timeouts` sub-block compiles to Pulumi's `CustomTimeouts` resource option. Each duration string (`"60m"`, `"30m"`) overrides the provider's built-in default for that operation. Pulumi waits up to that duration before failing the apply.
  </Step>

  <Step title="ignore_changes is passed as a resource option too">
    The list of attribute names in `ignore_changes` compiles to Pulumi's `ignoreChanges` resource option. On every subsequent apply, Pulumi reads the live state for those attributes but does not include them in the diff — changes to them are silently accepted.
  </Step>

  <Step title="Both can appear on the same resource">
    `lifecycle` and `timeouts` are independent sub-blocks. A slow resource with externally-managed attributes — like a large RDS instance whose password is rotated by a secrets manager — benefits from both simultaneously.
  </Step>
</Steps>

***

## What ubx generates

<CodeGroup>
  ```typescript index.ts theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  import * as pulumi from "@pulumi/pulumi";
  import * as aws from "@pulumi/aws";

  const config = new pulumi.Config();
  const env = config.get("env") || "dev";

  const db = new aws.rds.Instance("db", {
      identifier: `myapp-${env}`,
      allocatedStorage: 50,
      engine: "postgres",
      engineVersion: "15",
      instanceClass: "db.r6g.xlarge",
      username: "admin",
      password: "placeholder",
      skipFinalSnapshot: true,
  }, {
      ignoreChanges: ["password"],
      customTimeouts: { create: "60m", update: "30m", delete: "20m" },
  });

  const main = new aws.eks.Cluster("main", {
      name: `myapp-${env}`,
      roleArn: "arn:aws:iam::123456789012:role/eks-role",
      vpcConfig: { subnetIds: ["subnet-abc123", "subnet-def456"] },
  }, {
      ignoreChanges: ["tags"],
      customTimeouts: { create: "30m", delete: "20m" },
  });

  export const clusterEndpoint = main.endpoint;
  ```

  ```python __main__.py theme={"theme":"css-variables"}
  # Generated by ubx — do not edit
  import pulumi
  import pulumi_aws as aws

  config = pulumi.Config()
  env = config.get("env") or "dev"

  db = aws.rds.Instance("db",
      identifier=f"myapp-{env}",
      allocated_storage=50,
      engine="postgres",
      engine_version="15",
      instance_class="db.r6g.xlarge",
      username="admin",
      password="placeholder",
      skip_final_snapshot=True,
      opts=pulumi.ResourceOptions(
          ignore_changes=["password"],
          custom_timeouts=pulumi.CustomTimeouts(create="60m", update="30m", delete="20m"),
      ),
  )

  main = aws.eks.Cluster("main",
      name=f"myapp-{env}",
      role_arn="arn:aws:iam::123456789012:role/eks-role",
      vpc_config={"subnet_ids": ["subnet-abc123", "subnet-def456"]},
      opts=pulumi.ResourceOptions(
          ignore_changes=["tags"],
          custom_timeouts=pulumi.CustomTimeouts(create="30m", delete="20m"),
      ),
  )

  pulumi.export("cluster_endpoint", main.endpoint)
  ```

  ```go main.go theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  package main

  import (
      "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/eks"
      "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/rds"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
  )

  func main() {
      pulumi.Run(func(ctx *pulumi.Context) error {
          cfg := config.New(ctx, "")
          env := cfg.Get("env")
          if env == "" { env = "dev" }

          _, err := rds.NewInstance(ctx, "db", &rds.InstanceArgs{
              Identifier: pulumi.Sprintf("myapp-%s", env),
              AllocatedStorage: pulumi.Int(50),
              Engine: pulumi.String("postgres"),
              EngineVersion: pulumi.String("15"),
              InstanceClass: pulumi.String("db.r6g.xlarge"),
              Username: pulumi.String("admin"),
              Password: pulumi.String("placeholder"),
              SkipFinalSnapshot: pulumi.Bool(true),
          }, pulumi.IgnoreChanges([]string{"password"}),
             pulumi.Timeouts(&pulumi.CustomTimeouts{Create: "60m", Update: "30m", Delete: "20m"}))
          if err != nil { return err }

          main, err := eks.NewCluster(ctx, "main", &eks.ClusterArgs{
              Name: pulumi.Sprintf("myapp-%s", env),
              RoleArn: pulumi.String("arn:aws:iam::123456789012:role/eks-role"),
              VpcConfig: &eks.ClusterVpcConfigArgs{SubnetIds: pulumi.StringArray{pulumi.String("subnet-abc123"), pulumi.String("subnet-def456")}},
          }, pulumi.IgnoreChanges([]string{"tags"}),
             pulumi.Timeouts(&pulumi.CustomTimeouts{Create: "30m", Delete: "20m"}))
          if err != nil { return err }

          ctx.Export("clusterEndpoint", main.Endpoint)
          return nil
      })
  }
  ```
</CodeGroup>

***

## Common mistakes

<Warning>
  Timeout strings must be valid Go duration format: `"60m"`, `"2h"`, `"90s"`. An invalid string like `"1 hour"` or `"60 minutes"` will cause a runtime error. Use the abbreviated forms: `s` for seconds, `m` for minutes, `h` for hours.
</Warning>

<Tip>
  Attribute names in `ignore_changes` use the Pulumi camelCase SDK name, not the `.iac` snake\_case name. `password` stays `password`, but `desired_capacity` becomes `desiredCapacity` in the generated Pulumi option. Check the provider SDK docs if you're unsure of the correct name.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
ubx validate
ubx plan   # requires AWS credentials
ubx apply  # EKS and RDS creation may take 20-60 minutes
```

***

## What you learned

<Check>`timeouts` overrides the provider default wait time per operation (create, update, delete)</Check>
<Check>`ignore_changes` prevents Pulumi from resetting externally-managed attributes on apply</Check>
<Check>Both can appear on the same resource — they compile to independent Pulumi resource options</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Dynamic blocks" href="/v1/tutorials/12-dynamic-blocks">
    Generate repeated nested blocks from a collection
  </Card>

  <Card title="Lifecycle block" href="/v1/tutorials/10-lifecycle-block">
    prevent\_destroy and create\_before\_destroy
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/11-timeouts-and-ignore-changes](https://github.com/ubiquex/ubx-examples/tree/main/11-timeouts-and-ignore-changes)
</Info>
