KUBERNETES GUIDE

Kubernetes CronJob
Schedule Examples

15+ real CronJob schedule examples with full YAML specs. Covers timeZone, concurrencyPolicy, startingDeadlineSeconds, suspend, and production troubleshooting.

Kubernetes CronJob Basics

A Kubernetes CronJob creates Jobs on a repeating schedule using standard 5-field cron syntax. Unlike AWS EventBridge, Kubernetes uses the traditional Linux cron format — 5 fields, 0-indexed weekdays (Sunday=0).

apiVersion: batch/v1
kind: CronJob
metadata:
  name: my-scheduled-job
  namespace: default
spec:
  schedule: "0 9 * * 1-5"          # 9 AM UTC, weekdays
  timeZone: "America/New_York"      # Kubernetes 1.27+ only
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 200
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  suspend: false
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: job
            image: my-image:latest
            resources:
              requests:
                memory: "128Mi"
                cpu: "100m"
              limits:
                memory: "256Mi"
                cpu: "200m"

15+ CronJob Schedule Examples

Frequent intervals

Every minute
schedule: "* * * * *"
Only for development/testing — creates a Job every minute
Every 5 minutes
schedule: "*/5 * * * *"
Health checks, queue processors, near-real-time sync
Every 15 minutes
schedule: "*/15 * * * *"
Data aggregation, cache warming, polling jobs
Every hour
schedule: "0 * * * *"
Hourly report generation, index rebuilds

Daily schedules

Daily at midnight UTC
schedule: "0 0 * * *"
Database cleanup, daily snapshots, log rotation
Daily at 2 AM UTC
schedule: "0 2 * * *"
Off-peak maintenance, heavy compute jobs
Every day at 6 AM and 6 PM
schedule: "0 6,18 * * *"
Twice-daily syncs, morning and evening processing

Weekday schedules

Weekdays at 9 AM UTC
schedule: "0 9 * * 1-5"
Business-hours jobs, weekday report delivery
Every 30 min, Mon–Fri 9–17
schedule: "*/30 9-17 * * 1-5"
Business hours processing windows
Monday only at 8 AM
schedule: "0 8 * * 1"
Weekly kickoff, Monday morning digests
Weekends at noon
schedule: "0 12 * * 0,6"
Weekend maintenance, low-traffic window jobs

Monthly schedules

First of every month at midnight
schedule: "0 0 1 * *"
Monthly billing, subscription processing
1st and 15th at 9 AM
schedule: "0 9 1,15 * *"
Semi-monthly payroll, bi-monthly reports
Specific months only (Q1 quarterly)
schedule: "0 0 1 1,4,7,10 *"
Quarterly jobs: January, April, July, October 1st
Once a year — Jan 1st
schedule: "0 0 1 1 *"
Annual resets, yearly archiving

timeZone Field (Kubernetes 1.27+)

Before Kubernetes 1.27, all CronJob schedules ran in the timezone of the kube-controller-manager — typically UTC. This required manually calculating UTC offsets for every schedule.

From Kubernetes 1.27, you can specify a timezone directly:

spec:
  schedule: "0 9 * * 1-5"
  timeZone: "America/New_York"   # Runs at 9 AM Eastern, not 9 AM UTC
⚠ Check your cluster version: timeZone requires Kubernetes 1.27+ with the CronJobTimeZone feature gate enabled (enabled by default in 1.27). On older clusters, the field is silently ignored.

Valid values are IANA timezone names from the IANA timezone database — the same format used by Linux systems: America/New_York, Europe/London, Asia/Kolkata, UTC.


concurrencyPolicy Explained

What happens when the next scheduled run fires but the previous one is still running? concurrencyPolicy controls this:

PolicyBehaviourBest for
Allow (default)New job starts alongside existing oneIndependent idempotent jobs
ForbidSkips the new run if previous is still activeJobs that must not overlap (DB migrations, file processing)
ReplaceCancels the running job and starts a new oneJobs where only the latest run matters
spec:
  schedule: "*/10 * * * *"
  concurrencyPolicy: Forbid      # Safe for jobs longer than 10 minutes

startingDeadlineSeconds

If the kube-controller-manager is down and misses scheduled runs, startingDeadlineSeconds controls how late a job can start. If the deadline is exceeded, the run is skipped entirely.

spec:
  schedule: "0 3 * * *"
  startingDeadlineSeconds: 3600   # Start up to 1 hour late
⚠ 100-run rule: If Kubernetes misses more than 100 scheduled runs within the startingDeadlineSeconds window (or the last 10 minutes if unset), the CronJob will not fire and logs "too many missed start times". Set startingDeadlineSeconds explicitly to a value smaller than your interval.

Full Production CronJob Example

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nightly-report
  namespace: production
  labels:
    app: reports
    team: data-engineering
spec:
  schedule: "0 2 * * *"
  timeZone: "UTC"
  concurrencyPolicy: Forbid
  startingDeadlineSeconds: 600
  successfulJobsHistoryLimit: 7
  failedJobsHistoryLimit: 3
  suspend: false
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 3600   # Kill job after 1 hour
      template:
        metadata:
          labels:
            app: reports
        spec:
          serviceAccountName: report-runner
          restartPolicy: OnFailure
          containers:
          - name: report-generator
            image: myregistry.io/reports:v2.4.1
            imagePullPolicy: IfNotPresent
            command: ["python", "-m", "reports.generate", "--type=nightly"]
            env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-secrets
                  key: url
            - name: REPORT_DATE
              value: "yesterday"
            resources:
              requests:
                memory: "512Mi"
                cpu: "250m"
              limits:
                memory: "1Gi"
                cpu: "500m"

Troubleshooting

CronJob not running

kubectl describe cronjob my-cronjob         # Check events and status
kubectl get jobs --selector=job-name=...    # See created jobs
kubectl get events --sort-by='.lastTimestamp' | grep CronJob

Run a CronJob immediately for testing

kubectl create job manual-test --from=cronjob/my-cronjob

Suspend and resume a CronJob

kubectl patch cronjob my-cronjob -p '{"spec":{"suspend":true}}'   # Suspend
kubectl patch cronjob my-cronjob -p '{"spec":{"suspend":false}}'  # Resume

Common issues checklist


Frequently Asked Questions

What timezone does Kubernetes CronJob use by default?
By default, the timezone of the kube-controller-manager — usually UTC. From Kubernetes 1.27+, you can set timeZone: "America/New_York" in the spec to use any IANA timezone.
What is concurrencyPolicy in Kubernetes CronJob?
Allow (default): concurrent runs are permitted. Forbid: skip new run if previous is still running. Replace: cancel the running job and start fresh. Use Forbid for most production jobs to prevent overlap.
Why is my Kubernetes CronJob not running?
Check these in order: 1) Is suspend: true? 2) Did the controller miss more than 100 runs? 3) Is the image pulling correctly? 4) Are RBAC permissions correct? 5) Is the schedule valid? Use kubectl describe cronjob NAME and kubectl get events.
How do I test a CronJob without waiting for the schedule?
Run kubectl create job test --from=cronjob/my-cronjob. This creates an immediate Job from the CronJob's template without modifying the schedule.
How many old jobs does Kubernetes keep by default?
3 successful jobs and 1 failed job. Override with successfulJobsHistoryLimit and failedJobsHistoryLimit. Set them based on how many runs you want available for debugging.
⚡ Validate Your CronJob Schedule

🔧 Other Free Developer Tools

⏱ Cron Generator 🕐 Timestamp Converter 🔑 JWT Decoder 📄 YAML ↔ JSON 🔤 Base64 Encoder 🗄 SQL Explainer