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

# Version Cooldown

> Learn how to use version cooldown rules to batch frequent releases and prevent rapid sequential deployments.

**Version cooldown rules** prevent rapid sequential deployments by requiring a
minimum time period to pass since the currently deployed (or in-progress)
version was created before allowing another deployment. This helps batch
frequent upstream releases into periodic deployments, reducing deployment churn
and infrastructure load.

## Why Use Version Cooldown?

Version cooldown helps you:

* **Reduce deployment frequency** - Batch multiple rapid releases into fewer
  deployments
* **Decrease infrastructure load** - Avoid constant rolling updates from CI/CD
  pipelines
* **Improve stability** - Give each deployment time to prove itself before the
  next
* **Save resources** - Reduce compute spent on deployment overhead

## Configuration

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "ctrlplane_policy" "batch_deployments" {
      name     = "Batch Deployments"
      selector = "environment.name == 'production'"

      version_cooldown {
        duration = "1h"
      }
    }
    ```

    The Terraform provider accepts a Go duration string for `duration` (e.g.,
    `"1h"`, `"30m"`, `"90s"`). This is converted to seconds internally.
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    curl -X POST https://api.ctrlplane.com/v1/workspaces/{workspaceId}/policies \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Batch Deployments",
        "selector": "environment.name == '\''production'\''",
        "rules": [
          {
            "versionCooldown": {
              "intervalSeconds": 3600
            }
          }
        ]
      }'
    ```

    The API accepts `intervalSeconds` as an integer representing the minimum seconds
    that must pass.
  </Tab>
</Tabs>

## Properties

<ParamField path="versionCooldown.intervalSeconds" type="integer" required>
  Minimum seconds that must pass since the currently deployed (or in-progress)
  version was created before allowing another deployment. Set to `0` to disable.
</ParamField>

## How It Works

Version cooldown checks if enough **time has elapsed** since the currently
deployed (or in-progress) version was created, not the time gap between version
creation times:

1. **Find reference version**: The currently deployed or in-progress version
   (in-progress takes precedence)
2. **Calculate elapsed time**: Time since the reference version was created
   (using current time)
3. **Apply cooldown**: If elapsed time >= interval, allow any version;
   otherwise, deny

### Example Timeline

```
Version Created:  v1.0 ────── v1.1 ── v1.2 ── v1.3 ────── v1.4
                  12:00       12:15   12:20   12:25       13:00

With intervalSeconds: 3600 (1 hour)
Currently deployed: v1.0 (created 12:00)

At 12:30 (30min elapsed since v1.0):
  Candidate v1.3 (created 12:25): DENIED - only 30min elapsed (need 60min)
  Candidate v1.2 (created 12:20): DENIED - only 30min elapsed
  Candidate v1.1 (created 12:15): DENIED - only 30min elapsed

At 13:05 (65min elapsed since v1.0):
  Candidate v1.3 (created 12:25): ALLOWED - 65min elapsed (>= 60min)
  Candidate v1.2 (created 12:20): ALLOWED - 65min elapsed
  Candidate v1.1 (created 12:15): ALLOWED - 65min elapsed
  Candidate v1.4 (created 13:00): ALLOWED - 65min elapsed
```

Once the cooldown period has elapsed, **any** version can be deployed,
regardless of when it was created. This enables batching rapid releases.

## Common Patterns

### Hourly Batching

Deploy at most once per hour:

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "ctrlplane_policy" "hourly_deployments" {
      name     = "Hourly Deployments"
      selector = "environment.name == 'production'"

      version_cooldown {
        duration = "1h"
      }
    }
    ```
  </Tab>

  <Tab title="API">
    ```json theme={null}
    {
      "name": "Hourly Deployments",
      "selector": "environment.name == 'production'",
      "rules": [
        { "versionCooldown": { "intervalSeconds": 3600 } }
      ]
    }
    ```
  </Tab>
</Tabs>

### Per-Environment Cooldown

Different intervals for different environments:

<Tabs>
  <Tab title="Terraform">
    ```hcl theme={null}
    resource "ctrlplane_policy" "staging_cooldown" {
      name     = "Staging Cooldown"
      selector = "environment.name == 'staging'"

      version_cooldown {
        duration = "15m"
      }
    }

    resource "ctrlplane_policy" "production_cooldown" {
      name     = "Production Cooldown"
      selector = "environment.name == 'production'"

      version_cooldown {
        duration = "1h"
      }
    }
    ```
  </Tab>

  <Tab title="API">
    ```json theme={null}
    [
      {
        "name": "Staging Cooldown",
        "selector": "environment.name == 'staging'",
        "rules": [
          { "versionCooldown": { "intervalSeconds": 900 } }
        ]
      },
      {
        "name": "Production Cooldown",
        "selector": "environment.name == 'production'",
        "rules": [
          { "versionCooldown": { "intervalSeconds": 3600 } }
        ]
      }
    ]
    ```
  </Tab>
</Tabs>

### Combined with Other Rules

Use cooldown alongside other policy rules:

```hcl theme={null}
resource "ctrlplane_policy" "production_controlled_release" {
  name     = "Production Controlled Release"
  selector = "environment.name == 'production'"

  version_cooldown {
    duration = "30m"
  }

  any_approval {
    min_approvals = 1
  }

  gradual_rollout {
    rollout_type        = "linear"
    time_scale_interval = 300
  }
}
```

### With Deployment Windows

Combine cooldown with deployment windows for comprehensive control:

```hcl theme={null}
resource "ctrlplane_policy" "controlled_production" {
  name     = "Controlled Production"
  selector = "environment.name == 'production'"

  deployment_window {
    rrule            = "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0"
    duration_minutes = 480
    timezone         = "America/New_York"
  }

  version_cooldown {
    duration = "2h"
  }
}
```

### Weekly Scheduled Deployments

Deploy updates on a specific day (e.g., every Monday):

```hcl theme={null}
resource "ctrlplane_policy" "monday_deployments" {
  name     = "Monday Deployments"
  selector = "deployment.name == 'datadog-agent'"

  deployment_window {
    rrule            = "FREQ=WEEKLY;BYDAY=MO;BYHOUR=0;BYMINUTE=0"
    duration_minutes = 1440
    timezone         = "America/New_York"
    allow_window     = true
  }

  version_cooldown {
    duration = "120h"
  }

  gradual_rollout {
    rollout_type        = "linear-normalized"
    time_scale_interval = 82800
  }
}
```

## Behavior Details

### Version Selection

When a candidate version fails cooldown:

1. Ctrlplane tries the next older version
2. This continues until a qualifying version is found
3. If no versions qualify, the release target waits

### Same Version Redeploys

Redeploying the currently deployed version is always allowed, regardless of
cooldown settings. This enables:

* Manual re-runs of failed deployments
* Rollback-and-redeploy workflows
* **Configuration-only changes** - Deploy the same version with updated
  configuration immediately, bypassing cooldown

### Urgent Deployments

For urgent deployments that need to bypass cooldown (e.g., security patches,
critical fixes):

* **Same-version redeploy**: If the urgent change uses the same version ID, it
  automatically bypasses cooldown
* **Policy Skip**: Create a PolicySkip to bypass cooldown for a specific
  version. This allows urgent deployments while maintaining cooldown for regular
  releases

### In-Progress Deployments

If a deployment is in progress, the cooldown uses that version as the reference:

* Prevents deploying a newer version while one is still rolling out
* Ensures sequential deployments respect the interval

## Best Practices

### Interval Guidelines

| Use Case             | Suggested Interval | Notes                      |
| -------------------- | ------------------ | -------------------------- |
| High-frequency CI/CD | 15-30 minutes      | Balance freshness vs churn |
| Standard services    | 1-2 hours          | Reasonable batching        |
| Stable/low-priority  | 4-24 hours         | Significant batching       |
| Development/staging  | 5-15 minutes       | Faster feedback loops      |

### Recommendations

* ✅ Start with shorter intervals and increase as needed
* ✅ Use longer intervals for production vs staging
* ✅ Combine with gradual rollouts for safer deployments
* ✅ Monitor deployment frequency to tune intervals
* ✅ Use same-version redeploys for urgent configuration changes
* ✅ Use PolicySkip for urgent deployments that need to bypass cooldown
* ❌ Don't set intervals so long that critical fixes are delayed
* ❌ Don't use cooldown on environments that need immediate updates
* ⚠️ Ensure deployment windows are long enough for gradual rollouts to complete

## Next Steps

* [Policies Overview](./overview) - Learn about policy structure
* [Gradual Rollouts](./gradual-rollouts) - Control deployment pace
* [Deployment Window](./deployment-window) - Time-based deployment control
