Skip to main content
Your progress
0 of 4 lessons complete0%
T2 / M2.14 / L1 OF 4 / Engineer TIER / 9 min

When to write a watch policy

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.


TierEngineer
JTBD”Catch the waste pattern that is specific to our estate and that no shipped rule looks for.”
PersonasPlatform Engineer · FinOps Lead · SRE
PrerequisitesM2.1 (the rule library) · M2.2 (reading evidence)
Time9 minutes
Bloom verbDecide (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.

Terminal window
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 tab

They 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

Terminal window
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-of
OUTCOME idle / schedule / rightsize / custom
+ a severity you declare

That is the whole language. It is deliberately small.

When a watch policy is right

Terminal window
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

Terminal window
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

Terminal window
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:

Terminal window
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)

Terminal window
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.

Terminal window
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.


Glossary terms touched

Watch policy · User-Defined tab · custom_recommendation · Metric catalog


Start with the bill.

Foundations takes about five hours. The first lesson is nine minutes.

Open curriculum. No login. No paywall. 290 lessons across 7 courses, three publicly verifiable credentials. Read it on the train, take the exam on a Saturday, list the credential on your résumé Monday.

5h median time to finish Foundations
0 logins, paywalls, or marketing forms
open curriculum, public credential verifier
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·