| Tested on | Rocky Linux 10.2 (Red Quartz) workstation |
|---|---|
| Package | kubectl 1.36.3 |
| Applies to | Any host with kubectl configured; any Kubernetes cluster |
| Cert prep | CKA · CKAD |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user (no sudo required on the workstation) |
| Scope | Job versus CronJob comparison, one-time versus scheduled batch work, selection scenarios, misunderstandings, and a decision checklist. Does not cover full Job or CronJob YAML, cron syntax depth, parallelism, retry tuning, concurrencyPolicy configuration, time zones, or troubleshooting walkthroughs. |
| Related guides | Kubernetes Pods and Pod Lifecycle Deployments and rolling updates |
Batch work in Kubernetes ends in Pods that exit when the task finishes. The choice is whether you create one finite batch execution directly as a Job, or let a CronJob create those Jobs on a schedule. This page compares the two controllers so you can pick the right one, then open the dedicated tutorials for manifests and operations.
Job vs CronJob Comparison
| Feature | Job | CronJob |
|---|---|---|
| Execution | Represents one finite batch execution | Creates Jobs on a schedule |
| Trigger | Created manually, on demand, or by another controller | Triggered by a cron schedule |
| Recurrence | One Job object does not recur on a schedule | Recurring Job creation |
| Resource relationship | Job creates one or more Pods | CronJob creates Jobs over time; each Job creates one or more Pods |
| Main configuration | Completions, parallelism, retries, deadline | Schedule, concurrency, suspension, time zone |
| Timing guarantee | Begins creating and reconciling Pods after creation unless spec.suspend: true |
Schedule is approximate; under some conditions a scheduled Job can be missed or created more than once |
| Idempotency | Strongly recommended because Pod attempts can repeat | Strongly recommended because both Pod attempts and scheduled Job creation can occasionally repeat |
| Typical use | Migration or on-demand processing | Backup or periodic cleanup |
Controller chains:
Job → one or more PodsCronJob → Jobs over time → one or more Pods per Job
Suspending an active Job also deletes its active Pods.
CronJob scheduling is approximate rather than exactly-once. Kubernetes can occasionally create two Jobs for one scheduled time or fail to create one, so scheduled tasks should be designed to be idempotent. Kubernetes recommends idempotent CronJob workloads because scheduled Jobs can occasionally be duplicated or missed, but idempotency is not an API validation requirement.
How Jobs and CronJobs Work
Kubernetes Job
A Job manages Pods that perform a finite task. It tracks how many Pods must complete successfully, can retry failed attempts, and finishes when the required work is done or the Job fails.
Use a Job for one finite batch execution started directly or on demand — whether you create it manually, from CI/CD, or from another controller. A single Job can still require multiple successful Pod completions or parallel workers.
For YAML, completions, parallelism, backoffLimit, activeDeadlineSeconds, and ttlSecondsAfterFinished, see Kubernetes Jobs with examples.
Kubernetes CronJob
A CronJob creates Jobs according to a recurring schedule. Each scheduled execution is a separate Job object with its own Pods.
CronJobs control scheduling and whether Jobs created by the same CronJob may overlap. They also manage suspension, schedule time zones, and how many finished Jobs to keep in history.
For cron syntax, concurrencyPolicy, suspend, startingDeadlineSeconds, timeZone, and history limits, see Kubernetes CronJob scheduler.
Controller hierarchy
A CronJob does not execute the container directly. For each scheduled execution, it creates a Job, and that Job creates one or more Pods.
A nightly backup CronJob still runs finite Jobs. Each Job still creates Pods that start, run the script, and exit. Retry settings such as backoffLimit belong to each generated Job, not to the CronJob object itself.
When to Use Job or CronJob
One-time and on-demand work
Choose a Job for:
- Database migrations
- One-time data imports or exports
- Manual backup tasks
- Batch processing started on demand
- Administrative or maintenance scripts
- Tasks started by a CI/CD pipeline
Scheduled work
Choose a CronJob for:
- Nightly backups
- Periodic cleanup
- Scheduled reports
- Certificate or data checks
- Regular synchronization
- Recurring maintenance tasks
Common selection scenarios
| Scenario | Recommended resource | Reason |
|---|---|---|
| Run a database migration during deployment | Job | One finite batch execution |
| Back up a database every night | CronJob | Requires recurring execution |
| Generate a report manually | Job | Started on demand |
| Generate a report every Monday | CronJob | Runs on a schedule |
| Run a one-time batch task with Pod retries | Job | Retry settings belong to the Job |
| Retry Pod failures during every scheduled run | CronJob | Configure retry settings under jobTemplate.spec |
| Prevent overlapping scheduled backups | CronJob | concurrencyPolicy controls overlap for that CronJob |
| Run a continuously available API | Neither | Use a Deployment |
Retry, Concurrency, and Suspension
Job retry ownership
backoffLimit, activeDeadlineSeconds, and related execution controls belong to the Job. They govern how many times failed Pods are retried and how long the Job may stay active.
Once a Job reaches Failed, Kubernetes does not restart the same Job automatically. A new execution requires another Job object — either the next CronJob schedule or a manually created Job from the template.
CronJob concurrency
concurrencyPolicy affects only Jobs created by that CronJob. It does not prevent Jobs from different CronJobs from running simultaneously. Allow, Forbid, and Replace are evaluated per CronJob.
Job suspension vs CronJob suspension
Both resources support spec.suspend, but the behavior differs:
| Suspension behavior | Job | CronJob |
|---|---|---|
spec.suspend: true |
Stops Job execution and terminates active, incomplete Pods | Prevents future scheduled Jobs from being created; already-started Jobs continue |
Suspending a Job terminates its active incomplete Pods, whereas suspending a CronJob does not affect Jobs it already created.
Missed and duplicate schedules
CronJob scheduling is approximate. Missed executions can occur when the control plane is unavailable, when startingDeadlineSeconds expires, or while the CronJob is suspended. Suspended schedule occurrences count as missed.
When a CronJob is resumed without a startingDeadlineSeconds limit, missed Jobs may be created immediately. Kubernetes can also occasionally create two Jobs for one scheduled time, so scheduled tasks should be designed to be idempotent.
Run a CronJob Task Manually
Create a one-time Job from an existing CronJob template when you need to test the task, run it before the next schedule, or repeat work without waiting for the calendar:
kubectl create job manual-backup --from=cronjob/nightly-backup -n batchSample output:
job.batch/manual-backup createdThis creates a separate one-time Job from the CronJob's current jobTemplate. It does not change the CronJob schedule or count as one of its scheduled executions.
For namespace setup, naming, and follow-up inspection, see the manual-run section in Kubernetes CronJob scheduler.
Common Misunderstandings
| Misunderstanding | Correction |
|---|---|
| A CronJob is a long-running process | A CronJob creates finite Jobs at scheduled times; each Job runs Pods that exit when the task completes |
| A Job reruns on a calendar | A Job starts after it is created; Kubernetes does not reschedule the same Job object |
| CronJob retry settings live on the CronJob | backoffLimit and activeDeadlineSeconds belong under jobTemplate.spec on each generated Job |
| Suspending a CronJob stops active Jobs | Suspension blocks future Job creation; running Jobs continue |
| Suspending a Job pauses scheduling | Suspending a Job stops execution and terminates active, incomplete Pods |
| Updating a CronJob updates existing Jobs | Changes affect Jobs created after the update; Jobs and Pods already running keep their original configuration |
CronJobs are templates for future Jobs; they do not revise Jobs already started.
Decision Checklist
- Is this one finite batch execution started directly or on demand? → Job
- Should Kubernetes create the same batch work on a schedule? → CronJob
- Must the process stay running continuously? → Deployment, not Job or CronJob
- Do retries, deadlines, or completions matter for each run? → Put Job settings in the CronJob
jobTemplatewhen using a CronJob
For DaemonSet, Deployment, StatefulSet, and bare Pod choices, see choose a Kubernetes workload resource.
What's Next
- Kubernetes Volumes with Practical Examples
- Kubernetes subPath Volume Mounts with Examples
- Kubernetes PersistentVolume and PVC with Examples
References
Summary
A Job represents one finite batch execution and creates one or more Pods to complete it. A CronJob repeats that pattern by creating Jobs over time on a schedule, so the chain is always CronJob → Jobs → Pods. Pick a Job for migrations, on-demand exports, and pipeline-triggered batch work. Pick a CronJob for nightly backups, periodic cleanup, and scheduled reports.
CronJob settings such as timeZone and concurrencyPolicy answer when and how often Jobs are created. Job settings inside jobTemplate, including backoffLimit and activeDeadlineSeconds, answer how each run retries and how long it may stay active. Scheduling is approximate — design scheduled tasks to be idempotent, and remember that suspending a CronJob blocks future runs while suspending a Job terminates active incomplete Pods.
Neither controller replaces a Deployment for an API or web tier that must stay up. After you choose, use the dedicated Job and CronJob scheduler tutorials for manifests, retries, schedules, and concurrency settings.

