API-First Cron Automation: Why I Built Velora
The story behind Velora, an API-first cron automation platform. Why scheduler infrastructure shouldn't be your problem and how the SDK makes it trivial.
Every project I shipped in the last two years needed scheduled jobs. Send a daily digest. Sync inventory at 2am. Retry failed payments every 15 minutes. Each time, I reached for the same solution: a cron entry on a server, a node-schedule call inside the app, or a cloud function triggered by EventBridge. Each of those solutions is fine in isolation and painful in aggregate.
The problem with in-process schedulers
node-schedule and similar libraries run inside your application process. That means the scheduler dies when the process restarts, jobs run twice when you scale horizontally, and there is no visibility into what ran, what failed, and what is queued. You end up building a half-baked job system around a library that was supposed to save you from building a job system.
If your scheduler lives inside your app, your app is now a scheduler that also does other things. That is a bad deal.
Velora's shape
Velora is API-first. You create jobs with a POST request. You define a schedule in standard cron syntax, a target URL, and a payload. Velora stores the job, computes the next run time, and fires an HTTP request to your target when the schedule hits. Your app does not need to know about scheduling at all. It just needs an endpoint that does the work.
import { Velora } from "velora-sdk";
const velora = new Velora(process.env.VELORA_API_KEY);
await velora.jobs.create({
name: "daily-digest",
schedule: "0 8 * * *",
method: "POST",
url: "https://api.example.com/jobs/digest",
payload: { timezone: "Asia/Phnom_Penh" },
});Why a TypeScript SDK
The platform is HTTP. Any language can call it. But the people I ship products with use TypeScript, so a typed SDK removes the friction of reading API docs for every call. The SDK handles auth, retries on 5xx, and pagination. It also exports types for every job shape, so a misnamed field is a compile error, not a 4am incident.
What I learned shipping it
The biggest surprise was how many users wanted webhooks back into their app for job status. I shipped Velora assuming people would poll. Almost nobody does. The moment I added job.status webhook delivery, engagement jumped. If you build a scheduler, ship status webhooks on day one.