Documentation Index
Fetch the complete documentation index at: https://mintlify.com/motiadev/motia/llms.txt
Use this file to discover all available pages before exploring further.
Cron triggers allow you to schedule workflows to run at specific times or intervals using standard cron expressions.
Basic usage
import { step, cron } from 'motia'
export const config = step({
name: 'daily-report',
triggers: [cron('0 9 * * *')], // Every day at 9 AM
})
export const handler = async (input, ctx) => {
ctx.logger.info('Generating daily report')
const report = await generateReport()
ctx.logger.info('Report generated', { records: report.length })
}
from motia import step, cron
config = step(
name='daily-report',
triggers=[cron('0 9 * * *')], # Every day at 9 AM
)
async def handler(input, ctx):
ctx.logger.info('Generating daily report')
report = await generate_report()
ctx.logger.info('Report generated', {'records': len(report)})
Cron expression syntax
Cron expressions use five fields:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
* * * * *
Common patterns
Every minute
import { step, cron } from 'motia'
export const config = step({
name: 'health-check',
triggers: [cron('* * * * *')],
})
export const handler = async (input, ctx) => {
await performHealthCheck()
}
from motia import step, cron
config = step(
name='health-check',
triggers=[cron('* * * * *')],
)
async def handler(input, ctx):
await perform_health_check()
Every hour
export const config = step({
name: 'hourly-sync',
triggers: [cron('0 * * * *')],
})
config = step(
name='hourly-sync',
triggers=[cron('0 * * * *')],
)
Every day at specific time
export const config = step({
name: 'daily-backup',
triggers: [cron('0 2 * * *')], // 2 AM every day
})
config = step(
name='daily-backup',
triggers=[cron('0 2 * * *')], # 2 AM every day
)
Every weekday
export const config = step({
name: 'weekday-report',
triggers: [cron('0 9 * * 1-5')], // 9 AM Monday-Friday
})
config = step(
name='weekday-report',
triggers=[cron('0 9 * * 1-5')], # 9 AM Monday-Friday
)
First day of month
export const config = step({
name: 'monthly-invoice',
triggers: [cron('0 0 1 * *')], // Midnight on the 1st
})
config = step(
name='monthly-invoice',
triggers=[cron('0 0 1 * *')], # Midnight on the 1st
)
Every 15 minutes
export const config = step({
name: 'frequent-poll',
triggers: [cron('*/15 * * * *')],
})
config = step(
name='frequent-poll',
triggers=[cron('*/15 * * * *')],
)
Conditional execution
Use conditions to skip executions based on runtime logic:
import { step, cron } from 'motia'
export const config = step({
name: 'conditional-task',
triggers: [
cron('0 * * * *', async (input, ctx) => {
const hour = new Date().getHours()
// Only run during business hours
return hour >= 9 && hour <= 17
}),
],
})
export const handler = async (input, ctx) => {
ctx.logger.info('Running during business hours')
}
from motia import step, cron
from datetime import datetime
async def business_hours_condition(input, ctx):
hour = datetime.now().hour
# Only run during business hours
return 9 <= hour <= 17
config = step(
name='conditional-task',
triggers=[
cron('0 * * * *', condition=business_hours_condition),
],
)
async def handler(input, ctx):
ctx.logger.info('Running during business hours')
Enqueuing from cron
Trigger async workflows from scheduled jobs:
import { step, cron } from 'motia'
export const config = step({
name: 'schedule-reports',
triggers: [cron('0 6 * * *')], // 6 AM daily
enqueues: ['generate-report'],
})
export const handler = async (input, ctx) => {
const users = await getActiveUsers()
for (const user of users) {
await ctx.enqueue({
topic: 'generate-report',
data: { userId: user.id },
})
}
ctx.logger.info('Queued reports', { count: users.length })
}
from motia import step, cron
config = step(
name='schedule-reports',
triggers=[cron('0 6 * * *')], # 6 AM daily
enqueues=['generate-report'],
)
async def handler(input, ctx):
users = await get_active_users()
for user in users:
await ctx.enqueue({
'topic': 'generate-report',
'data': {'userId': user['id']},
})
ctx.logger.info('Queued reports', {'count': len(users)})
Configuration options
Standard cron expression with five fields:
- Minute (0-59)
- Hour (0-23)
- Day of month (1-31)
- Month (1-12)
- Day of week (0-6, Sunday-Saturday)
Supports:
* for any value
, for lists (e.g., 1,15,30)
- for ranges (e.g., 1-5)
/ for steps (e.g., */15)
Optional function (input, ctx) => boolean to conditionally execute the handler
Use cases
Daily data sync
Sync data from external systems:
import { step, cron } from 'motia'
export const config = step({
name: 'sync-users',
triggers: [cron('0 3 * * *')], // 3 AM daily
})
export const handler = async (input, ctx) => {
ctx.logger.info('Starting user sync')
const externalUsers = await fetchExternalUsers()
const updates = await syncToDatabase(externalUsers)
ctx.logger.info('User sync complete', {
fetched: externalUsers.length,
updated: updates.length,
})
}
Weekly cleanup
Clean up old data:
import { step, cron } from 'motia'
export const config = step({
name: 'cleanup-old-data',
triggers: [cron('0 0 * * 0')], // Sunday midnight
})
export const handler = async (input, ctx) => {
const thirtyDaysAgo = new Date()
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30)
const deleted = await deleteOldRecords(thirtyDaysAgo)
ctx.logger.info('Cleanup complete', { deleted })
}
Monitoring and alerts
Regular health checks:
import { step, cron } from 'motia'
export const config = step({
name: 'system-monitor',
triggers: [cron('*/5 * * * *')], // Every 5 minutes
})
export const handler = async (input, ctx) => {
const metrics = await collectMetrics()
if (metrics.errorRate > 0.05) {
ctx.logger.error('High error rate detected', {
errorRate: metrics.errorRate,
})
await sendAlert('High error rate', metrics)
}
}
Report generation
Generate periodic reports:
import { step, cron } from 'motia'
export const config = step({
name: 'weekly-analytics',
triggers: [cron('0 8 * * 1')], // Monday 8 AM
})
export const handler = async (input, ctx) => {
const startDate = getLastWeekStart()
const endDate = getLastWeekEnd()
const analytics = await generateAnalytics(startDate, endDate)
const report = await formatReport(analytics)
await sendReport(report)
ctx.logger.info('Weekly report sent')
}
Cache warming
Pre-populate caches:
import { step, cron } from 'motia'
export const config = step({
name: 'warm-cache',
triggers: [cron('0 */6 * * *')], // Every 6 hours
})
export const handler = async (input, ctx) => {
const popularItems = await getPopularItems()
for (const item of popularItems) {
await cacheItem(item)
}
ctx.logger.info('Cache warmed', { items: popularItems.length })
}