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

# Auto-reconcile policy

> Automatically re-apply a stack's declared state at a fixed interval, undoing drift.

An auto-reconcile policy re-applies a stack's declared state on a schedule, without you running `apply` yourself. It's how you keep a stack pinned to its declared state continuously, instead of only at the moment you happen to deploy it.

## How it works

After each successful reconcile, formae records the resulting state. At the configured interval, it compares the stack's current state against that recorded state. If it finds any deviation, it automatically runs a [hard reconcile](/documentation/concepts/apply-modes#hard-vs-soft-reconcile): declared state wins, and any drift is overwritten.

The interval timer restarts after each reconcile completes, so reconciliations stay evenly spaced regardless of how long any single one takes.

## Configuration

| Property   | Type     | Description                                        |
| ---------- | -------- | -------------------------------------------------- |
| `interval` | Duration | How often to reconcile, for example `5.min`, `1.h` |

## Relationship to synchronization

[Synchronization](/documentation/concepts/synchronization) is what detects drift: changes made through the cloud console, another tool, or a formae [patch](/documentation/concepts/apply-modes). Without auto-reconcile, that drift just sits there until your next `apply`, and [soft reconcile](/documentation/concepts/apply-modes#hard-vs-soft-reconcile) will stop you to review it.

Auto-reconcile skips that pause: it applies a hard reconcile automatically on every interval, so drift never survives longer than one cycle.

<Tip>
  Auto-reconcile suits production stacks where configuration consistency matters more than allowing manual experimentation. For a dev environment where you want room to poke at things through the console, leave it off.
</Tip>

## Examples

**Inline auto-reconcile policy:**

```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
amends "@formae/forma.pkl"

import "@formae/formae.pkl"
import "@aws/aws.pkl"
import "@aws/ec2/securitygroup.pkl"

local prodTarget = new formae.Target {
  label = "prod-target"
  config = new aws.Config {
    region = "us-east-1"
  }
}

forma {
  prodTarget

  new formae.Stack {
    label = "production-networking"
    description = "Production network security - auto-enforced"
    policies = new Listing {
      new formae.AutoReconcilePolicy {
        interval = 5.min  // Re-enforce every 5 minutes
      }
    }
  }

  new securitygroup.SecurityGroup {
    label = "api-sg"
    stack = "production-networking"
    target = prodTarget.res
    groupDescription = "API security group - managed by formae"
    securityGroupIngress = new Listing {
      new {
        ipProtocol = "tcp"
        fromPort = 443
        toPort = 443
        cidrIp = "0.0.0.0/0"
      }
    }
  }
}
```

**Reusable auto-reconcile policy**, shared across every production stack:

```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
amends "@formae/forma.pkl"

import "@formae/formae.pkl"
import "@aws/aws.pkl"
import "@aws/s3/bucket.pkl"

local prodReconcile = new formae.AutoReconcilePolicy {
  label = "prod-reconcile-5m"
  interval = 5.min
}

local prodTarget = new formae.Target {
  label = "prod-target"
  config = new aws.Config {
    region = "us-east-1"
  }
}

forma {
  prodReconcile
  prodTarget

  new formae.Stack {
    label = "prod-storage"
    description = "Production storage infrastructure"
    policies = new Listing { prodReconcile.res }
  }

  new bucket.Bucket {
    label = "prod-data"
    stack = "prod-storage"
    target = prodTarget.res
    bucketName = "company-prod-data"
  }

  new formae.Stack {
    label = "prod-logging"
    description = "Production logging infrastructure"
    policies = new Listing { prodReconcile.res }
  }

  new bucket.Bucket {
    label = "prod-logs"
    stack = "prod-logging"
    target = prodTarget.res
    bucketName = "company-prod-logs"
  }
}
```

**Combining with a TTL policy**, for a staging stack that stays enforced while it lives, then expires:

```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
new formae.Stack {
  label = "staging-environment"
  description = "Staging env - auto-reconciled, expires in 7 days"
  policies = new Listing {
    new formae.AutoReconcilePolicy {
      interval = 1.h
    }
    new formae.TTLPolicy {
      ttl = 7.d
      onDependents = "cascade"
    }
  }
}
```

## Use cases

* **Security compliance**: security groups and IAM policies always match declared configuration; unauthorized changes get reverted automatically.
* **Production stability**: desired state holds in critical infrastructure without manual intervention.
* **Multi-team environments**: when several teams can reach the same infrastructure, auto-reconcile reverts changes made outside version-controlled IaC.

## Monitoring

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
formae inventory stacks
```

Shows which stacks have an auto-reconcile policy and its interval. Reconcile runs triggered by the policy show up in your regular command history:

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
formae status --query='stack:production-networking'
```

## Considerations

**Interval selection.** Balance responsiveness against cloud provider rate limits; very short intervals (under a minute) risk being throttled.

**Emergency changes.** If you need a change to persist, either update your infrastructure code before the next cycle, or temporarily remove the policy.

**Interaction with patches.** Auto-reconcile reverts patch-mode changes too. If you apply an urgent [patch](/documentation/concepts/apply-modes), the next auto-reconcile cycle undoes it unless you also update the declared state.

## See also

* [Policy](/documentation/concepts/policy): inline vs. reusable policies, and how to query them.
* [TTL policy](/documentation/concepts/policies/ttl): expire a stack instead of enforcing it. The two can be combined on the same stack.
* [Synchronization](/documentation/concepts/synchronization): how formae detects the drift auto-reconcile undoes.
* [Apply modes](/documentation/concepts/apply-modes): soft vs. hard reconcile, and what auto-reconcile automates.
