Reliable background jobs, simplified.
Ship production-ready cron workflows in under 10 minutes. Zero configuration, full async support, and native TypeScript definitions.
View SDK Reference npm installGet CronFlow into your project
Add the official SDK via your preferred package manager. The package includes pre-built binaries for Linux, macOS, and Windows, plus full ESM and CommonJS support.
Run the command below in your terminal. CronFlow requires Node.js 18.0 or higher and automatically detects your environment to configure retry queues and dead-letter routing.
npm
npm install @cronflow/node-sdk
yarn
yarn add @cronflow/node-sdk
pnpm
pnpm add @cronflow/node-sdk
Initialize and schedule your first job
Connect to the CronFlow control plane using your workspace token. The SDK handles connection pooling, heartbeat monitoring, and graceful shutdowns automatically.
The following snippet demonstrates a standard Express integration that triggers a data synchronization job every 15 minutes. Replace cf_prod_8x9k2m with your actual API key from the dashboard.
Express Setup
import { CronFlow } from '@cronflow/node-sdk'; const client = new CronFlow({ token: process.env.CF_TOKEN }); await client.connect(); app.listen(3000, () => client.startScheduler());
Fastify Adapter
fastify.register(cronflowPlugin, { token: process.env.CF_TOKEN, queue: 'billing-sync', concurrency: 4 });
Master async/await patterns
CronFlow treats every scheduled task as a promise. Unhandled rejections are automatically caught, logged to your observability stack, and retried with exponential backoff.
Define your job handlers using native async functions. The SDK injects a context object containing job metadata, attempt counts, and a cancellation signal. If your handler takes longer than 30 seconds, CronFlow automatically extends the execution window and notifies your webhook endpoint.
Job Definition
client.defineJob('process-invoices', { cron: '*/15 * * * *' }, async (ctx) => { const batch = await ctx.fetchQueue('pending'); for (const item of batch) { await ctx.run(item.id, { timeout: 120000 }); } });
Error Recovery
client.on('job.failed', (error, ctx) => { if (ctx.attempt > 3) { ctx.moveToDeadLetter(); } else { ctx.retry({ delay: 2 ** ctx.attempt * 1000 }); } });