# How to run scheduled and cron jobs on Ownkube

> Deploy a scheduled job on Ownkube: set a cron expression, time zone, retries, and overlap handling, then trigger and watch runs from the Runs tab.

- **Published:** 2026-09-08
- **Author:** Ownkube team
- **Category:** How-To
- **Tags:** cron, scheduled-jobs, jobs, tutorial, ownkube-compute
- **Canonical URL:** https://ownkube.io/blog/run-scheduled-cron-jobs
- **Cover:** https://ownkube.io/blog/run-scheduled-cron-jobs.png

---
A nightly cleanup script, a report that emails itself every Monday, a cache warmer that runs every five minutes: all of it needs somewhere to run on a schedule without you leaving a laptop open. Ownkube runs these as a first-class deployment type, a scheduled job, with the same git-push deploy as any [web app](/blog/deploy-a-web-app-in-under-a-minute).

This guide deploys a scheduled job on Ownkube Compute, walks through every setting on its Schedule and Execution tabs, and shows how to watch and control runs from the Runs tab.

**TL;DR**

- A scheduled job is its own deployment type (`job`), built from a repo or image the same way a web app is, but with no port and no public URL.
- The Schedule section sets the [cron expression](https://crontab.guru/), an optional time zone, and how overlapping runs are handled (skip, allow, or replace).
- The Execution section sets retry limit, run timeout, parallel task count, completions, and how long to keep finished runs around.
- The Runs tab shows live and past runs with duration and pod-level failure detail, plus a Run now button and a per-run cancel.
- Jobs run on the same [metered wallet](/pricing) as everything else on Ownkube Compute, so a job that finishes in ten seconds barely costs anything.

## Deploy the job

1. From your dashboard, click New (or press Cmd+K) and choose Scheduled job as the deployment type.
2. Connect the GitHub or GitLab repository that has the script, or point at an existing image. A Dockerfile is optional: if the repo has one, Ownkube builds from it; if not, Ownkube detects the language and builds automatically.
3. Set the command and arguments the job runs, for example `python` and `send_report.py`. Leave both empty to use the image's own entrypoint.
4. Deploy. The job is created paused by default until you set a schedule in the next step.

## Set the schedule

Open the job's Settings tab and go to the Schedule section.

- **Cron expression**: standard [5-field cron](https://man7.org/linux/man-pages/man5/crontab.5.html) (`*/5 * * * *`) or a shorthand like `@hourly`. The field validates as you type, so an invalid expression blocks save.
- **Time zone** (optional): an IANA name like `America/New_York` or `UTC`. Leave it blank to run in the cluster's default time zone.
- **Overlapping runs**: choose what happens if a run is still going when the next one is due.
  - *Skip if running* (the default): the new run is skipped while the previous one finishes.
  - *Allow overlap*: runs can stack if one is slow.
  - *Replace running*: the in-progress run is canceled and the new one starts immediately.
- **Start deadline**: skip a run entirely if it can't start within this many seconds of its scheduled time (useful if the cluster was briefly busy).
- **Keep successful / failed runs**: how many finished runs of each kind stay in history before Ownkube prunes them.

The Active/Paused switch at the top of the card pauses the schedule without deleting the job, handy for maintenance windows.

```text
# Every day at 2:00 AM UTC
0 2 * * *

# Every 15 minutes
*/15 * * * *

# Every Monday at 9:00 AM, in America/New_York
0 9 * * 1
```

## Configure execution behavior

The Execution section controls what happens inside each run:

- **On failure**: *Never* leaves a failed pod in place for inspection and lets the job retry with a fresh one; *On failure* restarts the same pod in place.
- **Retry limit**: how many times a failed run retries before it's marked failed for good.
- **Run timeout (seconds)**: cancels a run that's still going after this long, so a hung script doesn't run (and meter) forever.
- **Clean up after (seconds)**: automatically removes a finished run's records after this window.
- **Parallel tasks** and **Completions**: run more than one copy of the task at once, and require a number of successful completions before the run counts as done. Most jobs leave both at 1.

You can also override resource limits for the job on its Resources tab, separate from any web or worker deployment in the same project.

## Trigger and monitor runs

The Runs tab is the operational view once the schedule is live.

- A **Schedule** summary card shows whether the job is active or paused, the cron expression, its time zone, and the last run and last successful run timestamps.
- **Run now** fires an off-schedule run immediately, useful for testing a new script or manually catching up a report.
- Each row in **Recent runs** shows status (running, succeeded, failed, or pending), a live duration for runs in progress, and a **cancel** action while a run is in flight.
- A failed run expands to show which pod failed, its exit code, and the failure reason, so you don't have to open the Logs tab just to see why a run went red.

```bash
# From the CLI: list a job's run history
okctl deploy job-runs list <deployment-id>

# Trigger an off-schedule run
okctl deploy job-runs trigger <deployment-id>

# Cancel a run that's stuck
okctl deploy job-runs cancel <deployment-id> <job-name>
```

## What it costs

Scheduled jobs run on the same prepaid wallet as the rest of Ownkube Compute: both CPU and memory meter on actual per-minute usage, so a job that runs for ten seconds every hour costs close to nothing, and a report script that runs for two minutes once a night is barely a rounding error against your monthly plan credit. If you're also running the same account's web app on a reserved box for predictable pricing, our guide to [metered versus reserved pricing](/blog/metered-vs-reserved-pricing) walks through when each model makes sense. And because the same job definition moves with the app if you later connect your own AWS account, see our [comparison of Railway, Render, and Northflank](/blog/railway-vs-render-vs-northflank-2026) for how those platforms handle scheduled work by comparison.

## FAQ

### What cron syntax does Ownkube support?

Standard 5-field cron (minute, hour, day of month, month, day of week), plus shorthands like `@hourly` and `@daily`. The Schedule field validates your expression before it lets you save.

### Can I run a job on demand without waiting for its schedule?

Yes. The Runs tab has a Run now button that fires an off-schedule run immediately, and the same action is available from the CLI as `okctl deploy job-runs trigger <deployment-id>`.

### What happens if a job is still running when the next scheduled run is due?

It depends on the Overlapping runs setting: Skip if running (the default) waits for the current run to finish, Allow overlap lets both run at once, and Replace running cancels the current run and starts the new one.

### Does a scheduled job have a public URL?

No. A job deployment has no port and no public address; it runs, does its work, and exits. If you need an HTTP endpoint on a schedule or event instead, look at Ownkube's beta Functions, which support cron and interval triggers directly.

### How much does a scheduled job cost?

Jobs meter the same as any other Ownkube Compute workload: CPU and memory bill per minute of actual usage against your prepaid wallet. A short-lived job that runs a few times a day costs a small fraction of your monthly plan credit.

## Where Ownkube fits

If your app needs a nightly cleanup, a recurring report, or a periodic cache warm without spinning up a separate scheduler service, a scheduled job on Ownkube gets you a cron expression, retry and timeout controls, and a live Runs tab in the same dashboard as the rest of your deployments. [Deploy your first app](https://app.ownkube.io/login).