# CronJob

> CronJobs create Jobs on a cron expression, so cost is a burst of pod time per firing. ZopNight stores schedule, concurrencyPolicy, suspension flag, and lastScheduleTime, treats suspensions on CronJobs older than 48 hours as forgotten pauses, and scales its never-fired check with cadence: 8 days weekly, 32 monthly, 366 yearly.

Source: https://zop.dev/integrations/kubernetes/cronjob
Updated: 2026-08-19

---

A CronJob creates Jobs on a cron expression. Its cost arrives as bursts, a slice of pod time per firing, which makes the interesting questions temporal: is it firing when it should, is it still firing in a namespace nobody uses, and was it paused on purpose?

## Cost as bursts, not a steady line

Discovery stores the `schedule`, the `concurrencyPolicy`, the suspension flag, the count of currently active Jobs, and `lastScheduleTime`, plus the container specs each firing will run. No replica count is recorded, because the type has none. A CronJob's footprint is its schedule times the resources of the Job it stamps out, and an aggressive schedule on a heavy Job is a steady drain wearing a batch costume.

## Suspended is worth an alarm, eventually

Setting `suspend: true` maps the resource to a `suspended` status, and the Suspended CronJob rule (RC-1733 / RC-1833 / RC-1933, low severity) treats it as a governance finding, not a cost one: a suspended CronJob runs nothing and bills nothing, but a pause that outlives its reason is usually a forgotten decision. The rule waits until the CronJob is at least 48 hours old so deploy-window and maintenance pauses never alarm.

## A never-fired check that respects the calendar

A separate rule catches CronJobs that have never scheduled at all, with no `lastScheduleTime` despite not being suspended. Its age gate scales with the cron expression so infrequent schedules are not flagged before their first legitimate fire: a 48-hour floor for daily and sub-daily schedules, about 8 days for weekly, 32 days for monthly, and 366 days for yearly or month-pinned expressions. Unparseable schedules fall back to the 48-hour floor.

```bash
kubectl get cronjobs -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,SCHEDULE:.spec.schedule,SUSPEND:.spec.suspend,LAST:.status.lastScheduleTime
```

## What the namespace schedule does with cron work

During scheduled off-hours, ZopNight suspends CronJobs rather than deleting them, and clears the suspension at resume. The distinction matters: the schedule, history, and configuration survive untouched, and a batch window that overlaps working hours simply picks back up at the next firing after resume.
