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

# Cost Alerts

> Get a Slack message when a day's, week's or month's cost goes above a threshold, for the whole cluster, namespaces or workloads.

A cost alert is a rule: a threshold, a period, a cost source and an optional
scope. The Thoras worker checks every rule hourly and posts to your Slack
webhook when a period's cost goes above the rule's threshold. You manage rules
on the dashboard's **Alerts** tab.

Cost alerts are off by default.

> [!NOTE]
>
> Requires chart version `5.8.2` (platform `4.129.1`).

## Turn on cost alerts

Turn on the feature flag and give Thoras a Slack
[incoming webhook](https://api.slack.com/messaging/webhooks):

```yaml theme={null}
featureFlags:
  enableCostAlerts: true

slackWebhookUrl: https://hooks.slack.com/services/T000/B000/XXXX # your webhook
```

To keep the webhook out of your values, store it in a Secret in the namespace
you installed Thoras into (`thoras` below), and reference it instead of setting
`slackWebhookUrl`:

```bash theme={null}
kubectl create secret generic thoras-slack-webhook --namespace thoras \
  --from-literal=url=https://hooks.slack.com/services/T000/B000/XXXX
```

```yaml theme={null}
slackWebhookUrlSecretRefName: thoras-slack-webhook
slackWebhookUrlSecretRefKey: url
```

Then `helm upgrade` your release. The worker checks the rules once at startup,
then hourly. Thoras uses the same webhook for its other Slack notifications,
such as errors when `slackErrorsEnabled` is on.

With `thorasDashboard.read_only` set, the **Alerts** tab lists the rules but
can't create, change or delete them. The rules keep running.

## Create an alert

Open **Cost analysis -> Alerts** and select **New alert**:

* **Name** — shown in the table and in the Slack message.
* **Threshold** — in US dollars for estimated cost, or in your billing currency
  for billed cost.
* **Cost source** — **Estimated** or **Billed**. See
  [Cost sources](#cost-sources). The choice appears only when the `billed_cost`
  dashboard extra is on; otherwise every rule uses estimated cost. Before chart
  `5.13.0`, the extra is `cluster_daily_cost`; see
  [Deprecations](https://docs.thoras.ai/deprecations.md).
* **Period** — **Daily**, **Weekly** or **Monthly**. See
  [When an alert is sent](#when-an-alert-is-sent).
* **Edit scope** — the namespaces and workloads the rule covers. With no scope,
  an estimated rule covers all managed workloads, and a billed rule covers the
  whole cluster.

Each row in the table has buttons to turn the rule off or on, edit it, send a
test alert, and delete it.

You can also list, create, change and delete rules from an AI assistant through
the [MCP server](https://docs.thoras.ai/guides/mcp-server.md) in `read-write` mode, from platform
`4.132.0`.

## Cost sources

| Source | What it adds up | Currency | Needs |
| - | - | - | - |
| Estimated | The requests of the workloads Thoras manages, priced from node pricing, as described in [Cost Estimates](https://docs.thoras.ai/guides/cost-estimates.md) | US dollars | Nothing more |
| Billed, whole cluster | The cluster's bill from [AWS Cost Explorer](https://docs.thoras.ai/guides/aws-cost-explorer.md) | Your billing currency | Cost Explorer collection and the `billed_cost` dashboard extra |
| Billed, with a scope | What AWS billed the scope's pods, from the [AWS Cost and Usage Report](https://docs.thoras.ai/guides/aws-cost-and-usage-report.md), the same cost as the **Billed (CUR)** graph. Until the report is usable, the bill split by the scope's share of requested CPU and memory | Your billing currency | The cost and usage report, or Cost Explorer collection until the report is usable, and the `billed_cost` dashboard extra |

The cost and usage report is usable once the worker has read it and found your
cluster's pods in it, the same rule the **Billed cost** tab follows. Like the
graph, a scoped billed rule then counts only workloads that an AIScaleTarget
covers.

> [!NOTE]
>
> Scoped billed rules read the cost and usage report from chart version `5.14.0`
> (platform `4.133.0`). Earlier versions always split the cluster's bill for a
> scope, which needs Cost Explorer collection.

Billed cost usually arrives within a day, so a billed rule alerts later than an
estimated one for the same day.

## When an alert is sent

Periods are in UTC, and only completed days count:

* **Daily** — a completed day.
* **Weekly** — Monday to Sunday, through yesterday.
* **Monthly** — the calendar month, through yesterday.

A rule alerts when its period's cost goes above the threshold, at most once per
period. A weekly or monthly rule can alert partway through its period, as soon
as its completed days add up to more than the threshold. Today's cost counts
once the day is over.

Cost that arrives late still counts. A daily rule checks each of the last 7
completed days, and a weekly or monthly rule keeps checking its period for 2
days after it ends. A new rule covers periods from the day before you created
it, so a rule set up in the morning covers the day that just ended.

Changing a rule's threshold, period, scope or source starts it over: it can
alert again for a period it already alerted on. Renaming it, or turning it off
and on, doesn't.

A scoped billed rule that reads the cost and usage report adds up each period
through the last day the report covers, and adds later days as the report
delivers them. Each month's report is read on its own, so a day counts only once
its own month's report covers it. If the report stops updating, the rule records
an error and still alerts on the days it covers.

## The Slack message

An alert posts a message titled **Budget alert: \<rule name>** with:

* The cost, the threshold and the overage, for example `$661.57`, `$500.00` and
  `$161.57 (32%)`.
* **Scope** and **Period**, for example `Monthly · November 2026`.
* **Cost through**, when the cost covers only part of the period so far.
* A note on where the cost comes from:
  * "Estimated from requests and node pricing"
  * "Billed by your cloud provider, before commitments"
  * "Billed by AWS: each pod's share of its node's cost, from your cost and
    usage report"
* "Not included: N days with no allocation data", when a split bill has days it
  couldn't split for the scope, or "Not included: N days the cost and usage
  report doesn't cover", when the report starts partway through the period or is
  missing days in it.
* "Incomplete pricing: …", when some pods could not be priced. See
  [Missing or Partial Pricing](https://docs.thoras.ai/guides/cost-estimates.md#missing-or-partial-pricing).

The test button posts a **Test alert: \<rule name>** message with the current
period's cost against the threshold, whether or not it's over and whether or not
the rule is on. A test doesn't count as the period's alert.

## Rule status

The **Status** column shows the result of the rule's last check. Hover over the
icon next to it for details.

| Status | Meaning |
| - | - |
| Not checked yet | The worker hasn't checked the rule since it was created or changed. Rules are checked hourly |
| Below threshold | The latest period's cost is at or under the threshold |
| Alerted for \<period> | The period went over the threshold and the alert was sent. The tooltip says when |
| No cost data for \<period> | There's no cost for the period yet. Billed cost usually arrives within a day |
| Error: \<message> | The last check failed. See [Troubleshooting](#troubleshooting) |
| Off | The rule is turned off and isn't checked |

The **Latest cost** column shows the cost of the latest period the rule checked.

## Troubleshooting

**No Alerts tab** — `featureFlags.enableCostAlerts` is off. Turn it on and
`helm upgrade`.

**No Cost source choice** — the `billed_cost` dashboard extra is off, so every
rule uses estimated cost. Turn on
[Cost Explorer collection](https://docs.thoras.ai/guides/aws-cost-explorer.md) or the
[cost and usage report](https://docs.thoras.ai/guides/aws-cost-and-usage-report.md), and the extra.

**"Error: billed cost is not being collected; enable the cost and usage
collector or switch the rule to estimated cost"** — the rule needs Cost Explorer
collection. Before chart `5.14.0`, every billed rule does. From `5.14.0`, a rule
with no scope does, and so does a rule with a scope until the cost and usage
report is usable. Turn on `thorasWorker.enableCostAndUsageCollector`, set up the
cost and usage report for a scoped rule on `5.14.0` or later, or switch the rule
to estimated cost.

**"Error: no Slack webhook is configured"** — set `slackWebhookUrl`, or
`slackWebhookUrlSecretRefName` and `slackWebhookUrlSecretRefKey`, as in
[Turn on cost alerts](#turn-on-cost-alerts).

**"Error: posting to the Slack webhook: …"** — Slack refused the message or
couldn't be reached. Check that the webhook is still active, and that the worker
can reach `hooks.slack.com` if a network policy limits its egress.

**"Error: the cost and usage report is not updating: …"** — a scoped billed rule
reads the cost and usage report, but the worker hasn't read it for two days, or
it has no cost stored for the cluster. The rule still alerts on the days the
report covers. Check the worker logs and the
[cost and usage report troubleshooting](https://docs.thoras.ai/guides/aws-cost-and-usage-report.md#troubleshooting).

**"Error: estimated cost is incomplete: …"** — some pods in the period could not
be priced, so the cost covers the priced pods only. See
[Missing or Partial Pricing](https://docs.thoras.ai/guides/cost-estimates.md#missing-or-partial-pricing).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.