> ## 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.

# cost_limit on Unit Blocks

> Enforce a monthly spend ceiling on individual resources at plan time.

Tutorial 24 covered `cost_limit` on `component` blocks — constraining the total cost of a component abstraction. The same attribute works on individual `unit` blocks, giving you per-resource cost governance without needing to wrap resources in components. A multi-AZ RDS instance with `cost_limit = 200` will block `ubx apply` if the AI estimates it will cost more than \$200/month. A Lambda function with `cost_limit = 20` catches the mistake of accidentally setting a very high memory allocation. Like the component variant, the limit is only enforced when `ubx plan --cost` is run with `UBX_AI_API_KEY` set — plain `ubx validate` always passes, ensuring cost governance doesn't break CI pipelines that don't have AI configured.

## What you'll learn

* How `cost_limit` on a `unit` block enforces a per-resource spend ceiling
* The three-tier behaviour: validate (always passes), plan (warns), apply (blocks)
* How to set different limits for different resource tiers

***

## Why this matters

<Info>
  Per-resource `cost_limit` is infrastructure budgeting at the source level. A `cost_limit = 200` on an RDS instance communicates the expected cost envelope to every engineer who reads the `.iac` file — and enforces it automatically when AI evaluation is enabled.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  # cost_limit sets a maximum monthly spend estimate for this resource.
  # Without --cost: stored as metadata, never evaluated.
  # With --cost + UBX_AI_API_KEY: warns on ubx plan, errors on ubx apply if exceeded.
  unit "aws_rds_instance" "db" {
    cost_limit = 200.00

    engine                  = "postgres"
    instance_class          = "db.t3.medium"
    identifier              = "myapp-${input.env}-db"
    storage_encrypted       = true
    backup_retention_period = 7
    multi_az                = true
  }

  # A smaller resource with a tighter ceiling.
  unit "aws_s3_bucket_v2" "logs" {
    cost_limit = 20.00

    bucket = "myapp-${input.env}-logs"
  }
  ```

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

  ```hcl outputs.iac theme={"theme":"css-variables"}
  output "db_endpoint" { value = unit.aws_rds_instance.db.endpoint }
  output "logs_bucket" { value = unit.aws_s3_bucket_v2.logs.bucket }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "cost-limit-constraint"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]

    ai {
      enabled  = true
      features = ["cost_estimate"]
    }
  }

  backend "s3" {
    bucket = "my-ubx-state"
    region = "us-east-1"
    key    = "${stack}/cost-limit-constraint.tfstate"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="cost_limit is parsed and stored as resource metadata">
    `cost_limit = 200.00` is recorded on the `IRUnit` node as a metadata field. It doesn't appear in the generated Pulumi code — it's a ubx-level constraint only.
  </Step>

  <Step title="ubx plan --cost evaluates each resource against its limit">
    With `UBX_AI_API_KEY` set, `ubx plan --cost` asks the AI to estimate the monthly cost of each resource that has a `cost_limit`. The estimate is compared to the limit and shown in the plan output with a pass/warn/fail indicator.
  </Step>

  <Step title="Exceeded limits block ubx apply">
    If the AI estimates a resource's cost exceeds its `cost_limit`, `ubx apply` is blocked. The apply fails before any resources are created or modified. Fix the configuration (reduce `instance_class`, disable `multi_az`, etc.) or raise the limit, then re-plan.
  </Step>
</Steps>

***

## Behaviour by command

| Command                           | cost\_limit behaviour                                       |
| --------------------------------- | ----------------------------------------------------------- |
| `ubx validate`                    | Parsed, stored as metadata — never evaluated, always passes |
| `ubx plan`                        | Parsed, stored — no AI call, no evaluation                  |
| `ubx plan --cost`                 | AI evaluates each resource, warns if `cost_limit` exceeded  |
| `ubx apply`                       | Blocked if a prior `--cost` check found any limit exceeded  |
| `ubx apply` (no prior cost check) | Runs normally — no cost enforcement without `--cost`        |

***

## Common mistakes

<Warning>
  Changing `instance_class = "db.t3.medium"` to `instance_class = "db.r6g.4xlarge"` will almost certainly exceed a `cost_limit = 200` limit. The AI estimate for an `r6g.4xlarge` multi-AZ RDS instance in us-east-1 is approximately \$1,200/month. Always run `ubx plan --cost` after changing instance types.
</Warning>

<Tip>
  Set `cost_limit` as self-documenting infrastructure budgeting — even if you never run `--cost` in CI. `cost_limit = 200` on a production database communicates the expected cost envelope to every engineer who reads the file. It's more informative than a comment and enforced when you need it.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
ubx validate                              # always passes — cost_limit not evaluated
ubx plan                                  # no cost evaluation
UBX_AI_API_KEY=xxx ubx plan --cost        # evaluates cost_limit for each resource
# Try exceeding a limit:
UBX_AI_API_KEY=xxx ubx plan --cost --var instance_class=db.r6g.4xlarge
```

***

## What you learned

<Check>`cost_limit` on a `unit` block sets a per-resource monthly spend ceiling</Check>
<Check>Without `--cost`, `cost_limit` is metadata only — `ubx validate` always passes</Check>
<Check>`ubx apply` is blocked if a prior `--cost` check found any limit exceeded</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Security scan" href="/v1/tutorials/50-security-scan-clean-project">
    Enforce security rules at validate time
  </Card>

  <Card title="AI plan summary" href="/v1/tutorials/48-ai-plan-summary-and-cost">
    Plain-English plan summaries and cost estimates
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/49-cost-limit-constraint](https://github.com/ubiquex/ubx-examples/tree/main/49-cost-limit-constraint)
</Info>
