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

# Drain notices

> The six things Lua emails your admins about when a drain is in trouble, how often, and what a notice never contains

A drain exists so you hear about your agents. A drain that breaks quietly reproduces the silent-outage problem one level up: the pipeline you installed to be told things stops telling you anything, and nothing says so.

**Drain notices** close that. They are Lua telling your organization's admins that *Lua's delivery to your destination* is in trouble — not alerting on your agents, which is what the drain itself is for.

<Info>
  **Rolling out.** Notices are switched on per deployment and are off by default, so a healthy drain today may simply be on a deployment where this has not been enabled yet. Nothing about your drains changes either way: the health states still transition and the quota ladder still degrades whether or not anyone is told. Ask [support@heylua.ai](mailto:support@heylua.ai) if you expect notices and are not getting them.
</Info>

## The six triggers

| Trigger                | Fires when                                                                                          |
| ---------------------- | --------------------------------------------------------------------------------------------------- |
| `failing`              | The drain enters `failing` — 15 minutes without a successful delivery                               |
| `paused_auto`          | `failing` becomes `paused` — 24 hours without a success                                             |
| `paused_quota`         | The [quota ladder](/drains/delivery-guarantees#quota-degradation) reaches 150% and pauses the drain |
| `quota_warning`        | The daily allowance **crosses** 80%, once per window                                                |
| `dropped`              | The first drop report after a clean period — the buffer cap, or the 6-hour horizon                  |
| `verification_pending` | The drain is still `pending_verification` 24 hours after it was created                             |

Everything else is **deliberately silent**: recovery, a pause you asked for, enabling or disabling a drain, changing its endpoint. An inbox that announces good news stops being read.

`quota_warning` hangs on the **crossing**, not on a reading — it fires once as usage passes 80%, and not again in that window however long you sit above it.

## At most one an hour

**One notice per (organization, drain, trigger) per hour.** That is the guarantee, and it holds across the whole platform rather than per process, so a restart does not reset it and two workers cannot both send.

A flapping drain therefore contributes **one** notice an hour per trigger, not sixty. A drain that is failing *and* over quota can produce two in an hour — they are different triggers.

<Note>
  A notice is counted against the hour even if the message itself could not be sent. The alternative — releasing the slot on a failed send — turns a transient fault into a mail storm, which is the failure mode this whole feature exists to prevent.
</Note>

## Who is told

The drain's **creator** first, when a person created it, then your organization's **active admins and owners**, deduplicated and capped at **20 recipients**.

The creator is first on purpose: they are the most likely to know what changed at the destination, and an organization with twenty admins must not squeeze them out.

Each recipient gets up to two things:

* **A notification in the product**, one card per drain per person, which moves forward in place — an incident updates the card rather than stacking a row per notice.
* **An email**, sent only when the card genuinely moved, and only to a **validated** address. An admin whose address has never been validated gets the in-product card and no mail.

## What a notice never contains

A notice is built field by field from an allow-list, never by deleting keys off a drain. That direction matters: a secret-bearing field added to a drain next quarter is **absent from every notice** until somebody deliberately adds it to the allow-list.

| In                                                                         | Out                                                                                 |
| -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| The drain's id, name, type, and state                                      | The **endpoint** — a vendor intake legitimately carries a token in its query string |
| `pauseReason`                                                              | The `site`                                                                          |
| `lastError` — an error class and a short reason, clamped to 200 characters | Every **header**: names, `last4`, and references alike                              |
| `lastStatusCode`, `lastSuccessAt`, `lastFailureAt`                         | The **signing secret**, its last four, and its rotation state                       |
| The 24-hour delivered / dropped / rejected counters                        | Your **scrub rules**                                                                |
| The backlog                                                                | The drain's **selectors**                                                           |
| The quota ratio and when it resets                                         | The verification **response excerpt**                                               |
| A link to the drain's health page                                          | **Every record body, always**                                                       |

`lastError` is the only string a notice carries that your *destination* wrote. It gets its own paragraph in the email so you can tell what Lua says from what your vendor says.

The audit entry each delivered notice writes — `logs.drain.notified` in your organization's ordinary audit stream — carries the trigger and the channel, and never the copy or a recipient's address. An append-only stream nobody rotates is the wrong place for a list of email addresses.

## Digest mode

An organization can be switched to **daily** instead of per-event: one message a day summarising what happened, rather than one message per trigger.

Notices are still subject to the hourly limit before they are queued, so a flapping drain contributes one entry an hour to the digest, not sixty. The queue holds the **newest 50** entries; an organization that generated more than fifty notices in a day is told about the last fifty.

The first digest lands 24 hours after that organization's first notice, not at a fixed hour of the day, and keeps that cadence from there.

## Turning notices down

Two settings exist per organization: the **mode** (`immediate` or `daily`), and a list of triggers to **unsubscribe** from. An unsubscribed trigger is not sent, not queued, and does not spend the hour's slot.

<Warning>
  **There is no self-serve control surface for either setting yet.** No route, no `lua drains` flag, and no field on the drain writes them; they are honoured in full by the notifier, but only an operator can set them today.

  To switch your organization to a daily digest, or to unsubscribe from a trigger, ask [support@heylua.ai](mailto:support@heylua.ai) with your organization id and what you want. A self-serve surface is additive to what shipped and is expected to follow.
</Warning>

Until one is set, every organization is `immediate` with nothing unsubscribed.

## If you are getting nothing

<AccordionGroup>
  <Accordion title="A drain is failing and nobody was told">
    Check the trigger first: `failing` needs a **transition** into `failing`. A drain that was already failing when notices were switched on for your deployment never transitions again and so never fires. Five of the six triggers are edge-triggered that way; `verification_pending` is the exception and sweeps on age.
  </Accordion>

  <Accordion title="Some admins get mail and others do not">
    Email goes only to validated addresses, and the audience is capped at 20. The in-product card reaches everyone in the audience regardless.
  </Accordion>

  <Accordion title="We got one notice for an incident that lasted all afternoon">
    That is the hourly limit working. Check the drain's own history with `lua drains status <id> --json` and `lua drains deliveries <id>` for what happened between notices — a notice is a prompt to look, not the record.
  </Accordion>

  <Accordion title="Nothing at all, ever">
    Either notices are not enabled on your deployment yet, or your organization is unsubscribed. The audit stream settles it: look for `logs.drain.notified`. Entries there with no mail arriving means the in-product card worked and the address was not validated.
  </Accordion>
</AccordionGroup>

## Next steps

<Columns cols={2}>
  <Card title="Delivery guarantees" href="/drains/delivery-guarantees">The health states and the quota ladder the triggers fire on.</Card>
  <Card title="Usage and plan quotas" href="/drains/usage-and-quotas">What the 80% warning is measured against.</Card>
  <Card title="Protecting your destination" href="/drains/protecting-your-destination">Why a notice can never carry a credential.</Card>
  <Card title="lua drains" href="/reference/cli/drains">Reading a drain's health yourself.</Card>
</Columns>
