# Gyro Containers: scheduled jobs (cron)

https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-scheduled-jobs

- **What you will learn**: how to put a service command or a URL (HTTP call) on a schedule: a nightly report, a queue cleanup every 15 minutes or a single run at a set time.
- **Time**: 5 minutes

## 1. How it works

- A **schedule** is one of three kinds: a **cron expression** (`minute hour day month weekday`, e.g. `0 3 * * *`; `@daily`, `@hourly` work too), **every N minutes**, or **once** (a date and time).
- Times follow the **time zone** you choose; the default is `Europe/Istanbul`. For users abroad pick e.g. `UTC` or `Europe/Berlin`.
- With a **service command** every run starts as a [one-off job](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-one-off-jobs): the image of the service's **version running at that moment**, its variables and secrets. After you deploy a new version, the next run uses it.
- With an **HTTP call** a request is sent from inside your environment (GET, POST, PUT, PATCH, DELETE, HEAD). Headers and body are kept secret and never shown again. A response code of 400 or above fails the run; redirects are not followed. You can call your own service by its internal address: `http://<service>.<namespace>.svc.cluster.local`. Private and platform addresses cannot be reached.
- **No overlapping runs:** while the previous run of a schedule is still going, a new one does not start; it shows as *Skipped* in the history.
- **Retries:** a failed run is tried again 30 s, 60 s, 90 s apart, at most 3 times (your choice, default 0).

## 2. Adding one in the panel

1. Open the **Jobs** tab of your service and press **Scheduled** at the top.
2. Press **Add schedule** and enter a **name** (e.g. `nightly-report`).
3. Under **When** choose *Cron expression*, *Every N minutes* or *Once*. The preset buttons (`0 3 * * *`, `*/15 * * * *` …) help; the **Next runs** line shows the expression in the chosen time zone.
4. Under **What runs** choose *Service command* (service + command + time limit) or *HTTP call* (method + URL + headers + body).
5. Optionally set **Retries** and press **Save**.
6. The list shows the next and the last run of every schedule. **Run now**, **History** (last 20 runs with their output), **Pause / Resume**, **Edit** and **Delete** are at the end of the row.

## 3. With the CLI, API, Terraform and AI assistants

```
# every night at 03:00 (Istanbul), retried twice
gyro container schedule create 12345 nightly-report --cron "0 3 * * *" --service api --retries 2 -- npm run report

# call your own endpoint every 15 minutes
gyro container schedule create 12345 queue-tick --every 15m --url https://api.example.com/cron --method POST --header "Authorization: Bearer $TOKEN"

# once on 1 December at 09:00
gyro container schedule create 12345 campaign --at 2026-12-01T09:00 --service api -- node send.js

gyro container schedule list 12345
gyro container schedule run-now 12345 nightly-report
gyro container schedule pause 12345 nightly-report
gyro container schedule preview 12345 --cron "0 9 * * 1-5" --timezone UTC
```

API: `POST /cloud/containers/{id}/schedules` with `{"name":"nightly-report","cron":"0 3 * * *","service":"api","command":["npm","run","report"],"retries":2}`; list `GET .../schedules`, details and history `GET .../schedules/{name}`, change `PATCH`, delete `DELETE`, `POST .../pause|resume|run`, preview `POST .../schedules/preview`.

Terraform:

```
resource "gyro_container_schedule" "report" {
  environment_id = 12345
  name           = "nightly-report"
  cron           = "0 3 * * *"
  timezone       = "Europe/Istanbul"
  service        = "api"
  command        = ["npm", "run", "report"]
  retries        = 2
}
```

Gyro MCP tools: `list_container_schedules`, `get_container_schedule`, `preview_container_schedule`, `create_container_schedule`, `update_container_schedule`, `pause_container_schedule`, `resume_container_schedule`, `run_container_schedule_now`, `delete_container_schedule`.

## 4. Notifications

- **schedule_failed:** the run still failed after its retries.
- **schedule_missed:** the run could not start at its planned time (e.g. platform maintenance); the next run follows the schedule.
- They go to the channels on your **Notifications** tab (e-mail, SMS, Telegram, signed webhook). So that a frequent schedule that keeps failing does not flood you, at most one message per schedule is sent per cooldown (default 30 minutes); all of them are kept in the history.

## 5. Limits and price

|  | Node plans | Serverless |
| --- | --- | --- |
| Schedules per environment | 5 on plans up to 2 vCPU, 10 otherwise | 5 |
| Shortest interval | 1 minute | 5 minutes |
| Price | No extra charge (runs on your nodes) | Each run billed like a task, per vCPU-second / GB-second |

- Scheduled runs count against the parallel job limit ([one-off jobs](https://www.gyrohosting.com/en/knowledgebase/article/gyro-containers-one-off-jobs)); when it is full the run fails and you are notified.
- Limits can be raised with a support ticket (`gyro limits` shows them).
- Nothing runs while the environment is suspended; deleting the environment deletes its schedules.

## 6. Frequently asked questions

**What happens when I change the time zone?**

The next run is recalculated in the new time zone right away.

**Does the job run on every copy of my service?**

No. However many copies your service has, a schedule starts one job, and never while its previous run is still going.

**Where do I see the output?**

In the schedule's **History** or in Jobs > One-off; with the CLI `gyro container job logs 12345 <job>`.

**Is a missed run made up?**

No. It is recorded as *Missed* and you are notified; the next run follows the schedule. After pause and resume the next run is also counted from that moment.

**Day of month and day of week in one expression?**

As in classic cron, it runs when either matches (e.g. `0 0 13 * 5` = the 13th or every Friday).
