Scheduled tasks
Generate and email a weekday analytics report on a cron schedule.
Runlane schedules are defined beside a task. Maintenance turns each due occurrence into a normal queued run.
Send a weekday report
The Runlane schedule and steps below are real. The marked metric, analysis, and email calls are pseudocode for your application and providers:
import { task } from '@runlane/core'
import * as z from 'zod'
const metricsSchema = z.object({ values: z.array(z.object({ name: z.string(), value: z.number() })) })
const reportSchema = z.object({
anomalies: z.array(z.string()),
insights: z.array(z.string()),
recommendations: z.array(z.string()),
})
const dailyReportResultSchema = z.object({ insights: z.number().int(), sent: z.boolean() })
export const dailyReport = task({
id: 'reports.daily',
schema: z.object({ accountId: z.string() }),
output: dailyReportResultSchema,
schedule: {
id: 'reports.weekdays.account-123',
cron: '0 9 * * 1-5',
payload: { accountId: 'account-123' },
timeZone: 'America/New_York',
},
async run({ accountId }, context) {
const metrics = await context.step.run('load-metrics', { output: metricsSchema }, async () => {
//////////////////////////////////
// MAKE YOUR API CALLS HERE
//////////////////////////////////
const result = await loadPreviousDayMetrics({ accountId, signal: context.signal })
return metricsSchema.parse(result)
})
const report = await context.step.run('analyze-metrics', { output: reportSchema }, async () => {
//////////////////////////////////
// MAKE YOUR API CALLS HERE
//////////////////////////////////
const result = await analyzeMetrics({ metrics, signal: context.signal })
return reportSchema.parse(result)
})
await context.step.run('send-report', { output: z.object({ sent: z.literal(true) }) }, async ({ token }) => {
//////////////////////////////////
// MAKE YOUR API CALLS HERE
//////////////////////////////////
await sendDailyReport({ idempotencyKey: token, metrics, report, signal: context.signal })
return { sent: true }
})
return { insights: report.insights.length, sent: true }
},
})This schedule runs at 9:00 AM on weekdays in America/New_York. The task loads the previous day’s metrics, generates structured findings, sends the report once through a durable step, and returns a small result.
A schedule accepts exactly one cadence:
runAtfor one occurrence;everyfor a fixed interval;cronfor cron occurrences.
Know the boundary
Schedules are static task registration, not a dynamic CRUD service. For customer-created schedules, store them in your application and use an application scheduler to call trigger().
Maintenance creates the run; a worker executes it. Running only one of those processes is not enough.
Before production
- Give maintenance a clear deployment owner.
- Use stable schedule and provider idempotency keys.
- Test a due occurrence with a controlled clock.
- Confirm overlapping maintenance calls do not create duplicate occurrences.
- Monitor schedules that are due but not materialized.
Read the complete schedule tasks guide and maintenance guide.