Immediate Tasks
Run tasks in background
Delayed Tasks
Schedule for later
Cron Tasks
Recurring schedules
Auto Retry
Exponential backoff
Overview
The Tasks SDK lets you define typed background tasks and trigger them asynchronously. Perfect for sending emails, processing data, generating reports, or any work that shouldn't block your main request. Tasks support durable steps, automatic retries, cron scheduling, and full type safety.
Define a Task
Define a task with task() and expose it via a route handler using serve():
import { task } from '@sylphx/sdk/tasks'
import { mailer } from '@/lib/mailer'
export const sendEmail = task({
id: 'send-email',
run: async ({ to, template }: { to: string; template: string }) => {
await mailer.send({ to, template })
return { sent: true }
},
})import { serve } from '@sylphx/sdk/tasks'
import { sendEmail } from '@/tasks/send-email'
// Expose GET (health) and POST (dispatch) handlers
export const { GET, POST } = serve({ tasks: [sendEmail] })Trigger a Task
Trigger a task from any server-side code — fully type-safe:
import { sendEmail } from '@/tasks/send-email'
// Fire-and-forget — returns immediately with a RunHandle
const handle = await sendEmail.trigger({
to: user.email,
template: 'welcome',
})
console.log(handle.id) // Task run ID for tracking
// Delayed trigger — run after 1 hour
await sendEmail.trigger(
{ to: user.email, template: 'follow-up' },
{ delay: '1h' },
)Wait for a Result
Use triggerAndWait to dispatch and block until the task completes:
import { sendEmail } from '@/tasks/send-email'
// Dispatch and wait for the result (type-safe)
const result = await sendEmail.triggerAndWait({
to: user.email,
template: 'welcome',
})
console.log(result.sent) // trueDurable Steps
Use step.run() and step.sleep() to make your task durable — steps are cached on completion and replayed instantly on retry:
import { task } from '@sylphx/sdk/tasks'
export const sendEmail = task({
id: 'send-email',
run: async ({ to, subject }, { step }) => {
// Each step is cached — safe to retry
const validated = await step.run('validate', () => validateEmail(to))
await step.sleep('cooldown', '1 minute')
return step.run('send', () => mailer.send(validated, subject))
},
})Recurring Tasks (Cron)
Schedule recurring tasks with cron expressions:
import { createCron } from '@sylphx/sdk/tasks'
const config = {
secretKey: process.env.SYLPHX_SECRET_KEY!,
ref: process.env.SYLPHX_PROJECT_REF!,
}
// Run every day at 9am UTC
await createCron(config, {
name: 'daily-report',
cron: '0 9 * * *',
callbackUrl: 'https://myapp.com/api/tasks',
payload: { type: 'daily' },
})
// Run every hour
await createCron(config, {
name: 'hourly-cleanup',
cron: '0 * * * *',
callbackUrl: 'https://myapp.com/api/tasks',
})| Property | Type | Description |
|---|---|---|
* * * * * | pattern | Every minute |
0 * * * * | pattern | Every hour |
0 0 * * * | pattern | Every day at midnight |
0 9 * * 1-5 | pattern | Weekdays at 9am |
0 0 1 * * | pattern | First of every month |
Task Status
Check the status of a triggered task:
import { getTask } from '@sylphx/sdk/tasks'
const config = {
secretKey: process.env.SYLPHX_SECRET_KEY!,
ref: process.env.SYLPHX_PROJECT_REF!,
}
const status = await getTask(config, taskRunId)
console.log(status)
// {
// id: 'run_abc123',
// status: 'completed', // 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'
// createdAt: '2024-01-15T10:00:00Z',
// startedAt: '2024-01-15T10:00:01Z',
// completedAt: '2024-01-15T10:00:05Z',
// result: { sent: true },
// }Cancel Tasks
Cancel a pending task:
import { cancelTask } from '@sylphx/sdk/tasks'
const config = {
secretKey: process.env.SYLPHX_SECRET_KEY!,
ref: process.env.SYLPHX_PROJECT_REF!,
}
// Cancel a specific task run
await cancelTask(config, taskRunId)Retries
Configure automatic retries for failed tasks:
import { task } from '@sylphx/sdk/tasks'
export const processOrder = task({
id: 'process-order',
retry: {
maxAttempts: 3,
backoff: 'exponential',
},
run: async ({ orderId }) => {
await chargeAndFulfill(orderId)
},
})Retry Behavior
step.run() inside your task to make individual steps durable — completed steps are not re-executed on retry.Batch Trigger
Dispatch multiple runs in parallel:
import { sendEmail } from '@/tasks/send-email'
// Dispatch N runs in parallel
const batch = await sendEmail.batchTrigger([
{ to: '[email protected]', template: 'welcome' },
{ to: '[email protected]', template: 'welcome' },
{ to: '[email protected]', template: 'welcome' },
])
// Wait for all to complete
const results = await Promise.all(batch.runs.map(h => h.waitForCompletion()))Common Use Cases
Email sending
Queue emails instead of blocking requests
Data processing
Process uploads in the background
Report generation
Generate PDFs or exports async
Webhooks
Reliable webhook delivery with retries
Scheduled tasks
Daily cleanups, weekly reports
Notifications
Send notifications without blocking