Dev and test VMs running around the clock with no schedule
What does ZopNight detect here?
Dev/test GCE instances commonly sit idle overnight and on weekends yet bill for 168 hours a week. ZopNight builds a weekly usage heatmap per VM, prices only the hours the suggested cron actually removes, and vetoes production, DR/standby, and stateful database VMs before ever proposing a stop.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-110 |
| Category | schedule |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | scheduling_vm.go |
Where it applies
168 hours billed, 45 used
A development VM used weekdays 9-to-6 is busy about 45 of the 168 hours it bills each week. The rest is pure idle spend, and unlike rightsizing there is nothing to migrate. Stopping and starting on a schedule recovers it with the machine unchanged. Candidates are running instances whose name or environment label reads dev, test, qa, staging, or sandbox; the env label is read from the nested labels object the GCP discoverer stamps, since GCP resources carry no separate tag sink.
Four vetoes run before any math
Production wins over everything: a prod name or an env=prod label ends evaluation
immediately. So does a critical-role name (DR, standby, backup, failover, replica),
because a standby stopped overnight is a standby that fails its one job. Stateful
data-service VMs (self-managed databases, Kafka, Elasticsearch, Redis) are vetoed too; a
forced stop of a single-replica stateful service is an outage, not a saving. Finally, a
schedule label on the VM is an explicit customer opt-out the rule honours silently.
Priced on the prescription, not the diagnosis
The saving is not “idle percentage times cost”. The heatmap yields a concrete cron
window, and the rule prices only the currently-running hours that window would actually
remove. Hours the team already keeps the box off contribute nothing, and a near-100%
idle VM is refused outright because that is an idle/delete case wearing a schedule
costume. Stops and starts execute through compute.instances.stop and
compute.instances.start in roles/compute.instanceAdmin.v1.
Spot the always-on dev fleet
gcloud compute instances list \ --filter="status=RUNNING AND name~'(dev|test|qa|staging|sandbox)'" \ --format="table(name,zone,machineType.basename(),labels.schedule)"Anything listed with an empty schedule column is what this rule evaluates.
What produces no schedule
Terminated instances, any veto above, unknown or zero pricing, a VM with no heatmap-derived idle measurement, an empty cron in the derived window, or a measured idle fraction at the near-total ceiling. The old fixed ~67% assumption is gone; every percentage shown was measured on that specific machine.