CronJobs
What does zop.dev create for CronJobs?
zop.dev provisions cron jobs as zop-helm releases carrying everything a service accepts (probes, resources, secrets, alerts), plus 4 scheduling controls: schedule, suspend, concurrency_policy, and cronjob_failed_threshold. On GCP, each cron job additionally gets its own Pub/Sub editor service account, separate from services.
| Field | Value |
|---|---|
| Cloud | cross-provider |
CronJobs run containerized tasks on a schedule inside a namespace. zop.dev gives them the same deployment spec as services plus scheduling controls and failure alerting.
A zop-helm release with CronJob scheduling
A zop-helm cron job release with the full service spec plus Kubernetes CronJob scheduling.
The service spec plus schedule and concurrency
Everything a service accepts, plus schedule, suspend, concurrency_policy, and cronjob_failed_threshold.GCP cron jobs get their own Pub/Sub identity
On GCP, cron jobs get their own dedicated Pub/Sub editor service accounts, separate from services.
A service that runs on a timer
A cron job here is not a stripped-down pod spec. It takes the full service surface (image,
resources, env, config and secret mounts, alerts) and adds scheduling on top. That parity
matters operationally: the batch job that syncs invoices at 03:00 gets the same secret wiring,
resource limits, and alerting as the API it feeds, instead of the copy-pasted YAML that batch
workloads usually accumulate. cronjob_failed_threshold closes the loop. Repeated failures
page someone, rather than being discovered when downstream data goes stale.
Concurrency is the sharp edge
The classic cron failure: a job scheduled every 10 minutes starts taking 12, and now two
instances run at once against the same data. concurrency_policy is the control: allow
overlaps, forbid them (skip the new run while the old one lives), or replace the running one.
Which is correct depends entirely on whether the job is idempotent, and “forbid” is the safe
answer for anything that writes. Deciding this at provision time beats discovering the default
during an overlap incident.
suspend is the pause button
suspend stops future scheduling while keeping the job, its history, and its configuration in
place. That is the right tool during incidents and migrations, where the alternative is deleting the
job and trusting someone to remember to recreate it. A suspended job is also honest in audits:
it shows as deliberately paused rather than mysteriously absent.
Cost is the runtime, identity is per job
A cron job bills nothing between runs, because pods exist only while work happens, which makes this the cheapest workload shape on the platform. On GCP there is one standing artifact: a dedicated Pub/Sub editor service account per cron job, separate from the services’, so a job’s messaging credentials implicate only that job.