Scheduled jobs
Cron for a project: the platform requests a path on your site on a schedule. Built for server runtimes — a due job wakes a scaled-to-zero instance, runs your handler, and records the outcome.
How a run works
When a job is due, the platform sends a request to https://<project>.slew.cloud<path> using the job's method (GET or POST), with two headers:
| Header | Value |
|---|---|
X-Slew-Cron |
1 |
X-Slew-Cron-Secret |
the job's secret |
- The request times out after 60 seconds.
- A run wakes a scaled-to-zero instance — the job doesn't need the server to already be running.
- No retries. A failed or timed-out run is recorded, and the next attempt is simply the next scheduled time.
lastRunAtandlastStatuson the job record the outcome (slew cron listshows them).
The path is a normal URL on your site, reachable by anyone — verify the secret in the handler. The secret is in the cron object (slew cron list); put it in a runtime env var and compare:
app.post('/tasks/daily-digest', (req, res) => {
if (req.get('x-slew-cron-secret') !== process.env.CRON_SECRET) {
return res.sendStatus(401)
}
// do the work
res.sendStatus(204)
})
Schedules
Standard 5-field cron expressions (minute hour day-of-month month day-of-week), evaluated in UTC, minute granularity:
| Expression | Runs |
|---|---|
*/15 * * * * |
Every 15 minutes |
0 3 * * * |
Daily at 03:00 UTC |
0 9 * * 1 |
Mondays at 09:00 UTC |
A project holds at most 5 jobs.
Console
The console's Runtime tab has a Scheduled jobs section: the project's jobs with their schedule, path, method, paused state and last run's outcome, a reveal-on-demand secret per job, pause/resume/delete, and a form to add one.
CLI
slew cron add "0 3 * * *" /tasks/daily-digest --method POST
| Command | Effect |
|---|---|
slew cron list |
The project's jobs: schedule, path, method, state, last run |
slew cron add "<schedule>" <path> [--method POST] |
Create a job; the method defaults to GET |
slew cron rm <id> |
Delete a job |
slew cron enable <id> / slew cron disable <id> |
Turn a job on or off without deleting it |
HTTP API
Bearer auth, like everything else:
| Method | Path | Description |
|---|---|---|
GET |
/projects/:name/crons |
List the project's jobs |
POST |
/projects/:name/crons |
Create a job — { "schedule", "path", "method"? } (GET or POST, default GET) |
PATCH |
/projects/:name/crons/:id |
Update a job — enable/disable is { "enabled": true | false } |
DELETE |
/projects/:name/crons/:id |
Delete a job |
A cron object:
| Field | Meaning |
|---|---|
id |
Job id |
schedule |
The 5-field cron expression (UTC) |
path |
Request path on the project's site |
method |
GET or POST |
secret |
Sent with every run as X-Slew-Cron-Secret — verify it in your handler |
enabled |
A disabled job stays configured but never runs |
lastRunAt, lastStatus |
When the job last ran and how it went |
createdAt |
When the job was created |
Errors:
| Code | Meaning |
|---|---|
invalid_schedule |
Not a valid 5-field cron expression |
invalid_path |
Not a valid request path |
cron_limit_reached |
The project already has 5 jobs |