Outcome
By the end of this lesson, you will be able to decide whether a cost pattern warrants a watch policy, explain how the separate watch engine relates to the built-in rule catalogue, and recognise the cases where a policy is the wrong tool.
| Tier | Engineer |
| JTBD | ”Catch the waste pattern that is specific to our estate and that no shipped rule looks for.” |
| Personas | Platform Engineer · FinOps Lead · SRE |
| Prerequisites | M2.1 (the rule library) · M2.2 (reading evidence) |
| Time | 9 minutes |
| Bloom verb | Decide (Evaluate), Explain (Understand), Recognise (Analyze) |
1. Concept
The 455-rule catalogue covers patterns that generalise across customers. It cannot cover the ones specific to your estate, because nobody outside your org knows them.
A watch policy is a metric-threshold recommendation that you author. It runs on a separate engine from the built-in RC-* rules, writes into its own table, and surfaces on the Recommendations User-Defined tab.
BUILT-IN RULES WATCH POLICIES─────────────────────────────────────────────────────────────Go rules under internal/rules A policy you author in Settings > Policy > Watch
Shipped by ZopNight Authored by you, stored in the config policy store (domain=watch)
Write to `recommendations` Write to `custom_recommendation`
Recommendations tab User-Defined tabThey are separate engines, not a plugin surface on the same one. What they share is the presentation and the discipline. A watch finding appears in the same drawer, prices savings the same way, and obeys the same permissions. It respects the same $5 floor below which nothing is reported, and offers the same Dismiss and Mark Resolved actions.
The shape of a policy
SCOPE which resources this applies to (a selector)SIGNALS one or more: "avg cpu < 5% over 14 days"DECISION combine the signals: all-of, or any-ofOUTCOME idle / schedule / rightsize / custom + a severity you declareThat is the whole language. It is deliberately small.
When a watch policy is right
YES: the threshold is ORG-SPECIFIC "Our batch nodes should never sit under 15% CPU for a fortnight, because our jobs are sized to fill them." No shipped rule knows your sizing convention.
YES: the resource type matters to you and not generally A queue depth that means something in your architecture and nothing in anyone else's.
YES: you want a TIGHTER threshold than the shipped rule The built-in idle rule fires at its own threshold. You want to know earlier.
YES: the combination is what matters Low CPU alone is normal here. Low CPU AND near-zero network is not.When it is the wrong tool
NO: a built-in rule already covers it Check first. A duplicate policy produces two findings on the same resource with two savings figures, and the cross-rec lever exclusivity that de-duplicates built-in rules does not span engines.
NO: you want an ALERT A watch policy produces a recommendation, which is a durable finding you triage. If you want to be paged when something crosses a line right now, that is an alerting policy or a budget threshold, not this.
NO: the signal is not a metric Policies read metrics. "Resources with no owner tag" is a tagging-policy question. "Resources violating a naming convention" is not expressible here at all.
NO: you want it to open a ticket Notify and Jira dispatch from a watch policy are deferred. Today it produces a recommendation and stops.The authoring surface protects you twice
1. THE WIZARD GREYS OUT what your scope cannot collect. It reads the aggregator's metric catalog, so a metric no resource in scope emits is not offered. This prevents the most common failure: a policy that can never fire because nothing produces its signal.
2. THE SERVER VALIDATES before save. The spec goes through a validation endpoint, so a policy that is structurally incapable of firing is rejected at the write boundary rather than saved and silently doing nothing.Both exist because the failure mode of a bad policy is silence, and silence is indistinguishable from “no findings”.
How a policy takes effect
Editing a policy publishes a change event, resolved asynchronously per edit. There is also an org-wide admin backfill for when a new policy should be evaluated against existing resources rather than only from now on.
So a new policy does not necessarily produce findings the instant you save it, and if you are testing one, that is the first thing to check before assuming the threshold is wrong.
2. Demo
A policy that earned its place, and one that did not:
POLICY A: "batch nodes under-filled" -> KEPT
WHY NO BUILT-IN RULE COVERS IT The shipped idle rules fire at a low threshold, which is right for general estates. This team sizes batch nodes to run at 60-80% by design, so anything under ~15% sustained means a job stopped feeding them, and that is invisible to a rule tuned for idleness.
SCOPE resource_group = batch-compute SIGNAL avg cpu lt 15% over 14 days DECISION all-of (single signal) OUTCOME rightsize, severity medium
RESULT 9 findings in the first pass. 6 were real: a decommissioned upstream feed nobody had noticed. ~$3,100/mo.
POLICY B: "unattached volumes" -> DELETED WITHIN A WEEK
WHAT WENT WRONG RC-002 already does this, and better: it carries the Safety Gate's orphan-evidence logic and knows about detached_since dwell.
The watch policy produced a SECOND finding on the same volumes with its own savings number. Cross-rec lever exclusivity de-duplicates overlapping BUILT-IN rules; it does not span the two engines, so both figures were reported and the estate's total was overstated.
THE LESSON Search the built-in catalogue before authoring. The duplicate did not just add noise, it corrupted the savings total.
POLICY C: "page us when spend spikes" -> NEVER BUILT
The team wanted an alert. A watch policy produces a durable finding you triage, not a page. This belongs in anomaly detection subscriptions or a budget threshold.3. Hands-on (6 min)
1. Name one waste pattern in your estate that you are confident no shipped rule catches: ______________________________________________
2. Search the built-in catalogue for it. Be honest: is there a rule that already covers it? Y / N If Y, stop. Tune that rule's severity instead.
3. Is your pattern expressible as a METRIC threshold? Y / N If N (tags, naming, configuration), it is not a watch policy. Where does it belong? ______________________________________________
4. Do the resources in your intended scope actually emit the metric? Open the wizard and check whether it is greyed out. available: Y / N
5. Decide the outcome type before writing anything: [ ] idle [ ] schedule [ ] rightsize [ ] custom L3 explains why this choice determines whether your finding can carry a dollar figure at all.Do it through MCP. The same task you just did in the console, asked in one sentence.
BEFORE A ZopNight account with one cloud connected. Resources with metrics flowing: EC2, Compute Engine or Azure Virtual Machines discovered at least a fortnight ago.ASK "Write a policy that flags any instance under 5% CPU for 14 days, and check it before saving."CHECK that validation passed first. A policy that never evaluates is worse than none, because it looks like cover.Tools behind it: validate_watch_policy (write, tier 1, metadata only), create_watch_policy (write, tier 2, reversible), list_watch_policies (read, Govern). The full catalogue is at zop.dev/learn/mcp-tools.
4. Knowledge check
Q1
A team authors a watch policy that duplicates what RC-002 already detects. The consequence:
A. The duplicate is de-duplicated automatically
B. The policy is rejected at save time
C. Two findings appear on the same resources with two savings figures, and the estate total is overstated
D. The built-in rule is suppressed entirely in favour of the newer watch policy that has been written
Show answer
Correct: C. Cross-rec lever exclusivity de-duplicates overlapping built-in rules, but it does not span the two engines: watch findings live in a separate table and surface on a separate tab. This is why “search the built-in catalogue first” is the load-bearing step. A duplicate policy does not merely add noise, it corrupts the savings total, and the built-in rule usually carries safety logic the policy cannot express.
Q2
Which of these is a legitimate case for a watch policy?
A. Finding resources with no cost-centre tag
B. Detecting batch nodes sustained under 15% CPU, where the org sizes nodes to run at 60-80% by design so the shipped idle threshold is far too low to catch it
C. Paging on-call when spend crosses a threshold today
D. Flagging any resources that violate the team’s own naming convention, which no shipped rule could possibly have been written to know about
Show answer
Correct: B. An org-specific threshold that no external rule could know is the canonical case. A is a tagging-policy question, C is alerting or budget thresholds, and D is not expressible as a metric threshold at all.
Q3
Why does the authoring wizard grey out metrics that resources in the chosen scope do not emit?
A. To reduce the size of the dropdown
B. Because unsupported metrics cause evaluation errors later on, which are hard to debug well after the fact
C. Because the metric catalog is provider-specific
D. Because the failure mode of a policy that can never fire is silence, and silence is indistinguishable from “no findings”
Show answer
Correct: D. Server-side validation before save exists for the same reason: a structurally incapable policy is rejected at the write boundary rather than saved and quietly doing nothing. Both protections address the same problem from different ends. If you are testing a new policy and it produces nothing, check whether the change event has resolved before assuming the threshold is wrong.
5. Apply
Before authoring anything, spend five minutes searching the built-in catalogue for your pattern. Most first-time watch policies duplicate a shipped rule, and the shipped rule is usually better because it carries safety and pricing logic the policy language cannot express.
When you do write one, start with a single signal and a scope narrow enough that you can check every finding by hand on the first pass.
Related lessons
- L2: The signal vocabulary (next)
- L3: Outcomes and the savings basis
- T2.M2.1.L1: The eight categories
- T2.M2.10.L1: The seven dimensions
Glossary terms touched
Watch policy · User-Defined tab · custom_recommendation · Metric catalog