Clouzark

Cron jobs

Call a path on your production app on a schedule.

A cron job sends a request to a path on your app's production deployment on a schedule, for work like sending digest emails, syncing with another service, or cleaning up old data. Your app does the work in an ordinary route handler; Clouzark only calls it.

Declare jobs in clouzark.json

Add a crons array to clouzark.json in your project's root directory (the same directory as package.json):

clouzark.json
{
  "crons": [
    { "path": "/api/cron/cleanup", "schedule": "0 3 * * *" },
    { "path": "/api/cron/digest", "schedule": "0 8 * * 1", "timezone": "Europe/Berlin", "name": "weekly-digest" }
  ]
}

The jobs take effect when the deployment becomes production, and a rollback restores the jobs of the deployment you roll back to. Preview deployments never run cron jobs. If clouzark.json is invalid, the build fails and says why.

Field
pathrequiredPath on your app, starting with /. A query string is fine: /api/cron?task=cleanup
schedulerequired5-field cron expression (see Schedules)
nameUnique within the project. Defaults to one made from the path, e.g. api-cron-cleanup
timezoneIANA time zone the schedule is read in. Default UTC
methodGET (default) or POST
timeoutSeconds to wait for the response, 1 to 300. Default 60
retriesTimes to retry a failed request, 0 to 3. Default 0

Or add them with the CLI or dashboard

Jobs can also be added without a deploy, from the project's Cron Jobs page or the CLI:

clouzark crons add cleanup /api/cron/cleanup "0 3 * * *"
clouzark crons add digest /api/cron/digest "0 8 * * 1" --tz Europe/Berlin --method POST --retries 2
clouzark crons ls

Jobs from clouzark.json are kept in step with the file: you can't edit or delete them from the CLI or dashboard, only switch them off and on. A paused job stays paused across deploys.

A project can have up to 20 cron jobs in total.

Secure the endpoint

Your cron path is a public URL, so check that a request really comes from Clouzark. Add a CRON_SECRET environment variable to production with a long random value; every cron request then carries it as a bearer token:

app/api/cron/cleanup/route.ts
export async function GET(request: Request) {
  if (request.headers.get("authorization") !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response("Unauthorized", { status: 401 });
  }
  // ... do the work
  return Response.json({ ok: true });
}

Requests also send User-Agent: clouzark-cron/1.0. A new CRON_SECRET value is used from the next run; your app sees it after a redeploy.

Schedules

ScheduleRuns
*/15 * * * *Every 15 minutes
0 * * * *Every hour, on the hour
0 3 * * *Every day at 03:00
0 9 * * 1-5Weekdays at 09:00
0 0 1 * *The first of every month at midnight

Fields are minute, hour, day of month, month, and day of week. Schedules are read in UTC unless the job has a time zone; with one, a daily job stays at the same local time across daylight saving changes. The most often a job can run is once a minute.

How requests are made

  • To your production URL, https://<project>.<apps domain><path>. If the app is asleep, it's woken first.
  • A 2xx response is a success. Anything else is a failure, and the run records the status code and the start of the response body.
  • Redirects aren't followed. A 3xx response fails the run, so point the job at the final path.
  • Retries are for 5xx responses, timeouts, and network errors, a few seconds apart. A 4xx response isn't retried.
  • Never overlapping. If a job's previous run is still going when it's due again, the new run is skipped and recorded as skipped. Still, write handlers that are safe to run twice.

Check and change jobs

clouzark crons runs cleanup        # recent runs: status, HTTP code, duration, response
clouzark crons run cleanup         # call it now and wait for the response
clouzark crons disable cleanup     # stop scheduled runs; it can still be run by hand
clouzark crons enable cleanup
clouzark crons edit digest -s "0 9 * * 1"
clouzark crons rm digest

Each job keeps its last 100 runs. Jobs are addressed by name or id. The same operations are in the Management API and available to AI agents. To run SQL against a database on a schedule instead, see database cron jobs.

On this page