Skip to content
cronix

cronix

Cron jobs as code. Your handler IS the schedule. One manifest, five backends, one CLI to keep them in sync.

The problem

Today, “I need a scheduled job” has three answers — none of them give you the whole picture.

In-app queue · BullMQ / Agenda

Redis-backed queue plus a worker. Needs Redis ops. Repeats stack on every restart. Schedule lives in code and in Redis.

In-process · node-cron / cron

Stops the moment the process exits. Each replica fires it — N pods → N runs. No audit log, no retries, no concurrency guard.

Host scheduler · crontab + systemd + k8s

Per-machine install. ssh-edit drift across hosts. No who-changed-what audit. Silent failures — did it actually run?

Whichever you pick, you can’t answer: “Is this running anywhere right now? Who changed the schedule? Did the last run succeed?”


The flip

Cronix puts the schedule next to the handler. Your code is the truth. git log is your audit log.

import { createCron } from "@awbx/cronix-sdk";
import { Hono } from "hono";
const cron = createCron({
app: "billing-service",
baseUrl: "https://billing.example.com",
secret: process.env.CRON_SECRET!,
});
cron.register({
name: "reconcile-payments",
schedule: "*/15 * * * *", // ← lives next to the handler
handler: async (ctx) => {
await reconcilePayments();
return { ok: true };
},
});
const app = new Hono();
app.all("/.well-known/cron-manifest", (c) => cron.handle(c.req.raw));
app.all("/api/v1/scheduled/:name", (c) => cron.handle(c.req.raw));

Then, from your laptop or CI:

Terminal window
cronix apply --manifest https://billing.example.com/.well-known/cron-manifest \
--backend crontab --crontab-path /etc/crontab \
--trigger-bin /usr/local/bin/cronix --secret-ref env:CRON_SECRET

Reviewers see schedule changes in the same diff as the code change.


Why it’s different

Schedule lives with the handler

The cron expression is a property of the function it triggers, not a row in some other system. Reviewers see the schedule change in the same diff as the code change.

Your app is the source of truth

cronix reads your manifest at apply time and reconciles the host scheduler to match. Drift between declared and installed is one command away.

Native scheduler does the firing

No background process, no broker, no Redis. cron, systemd-timer, kubelet, EventBridge — whatever the host already runs — does the work.

HMAC-signed every fire

Stripe-style signatures (timestamp + sha256) on every request. Constant-time verify. Multiple secrets supported for zero-downtime rotation.

Multi-backend, one contract

crontab, systemd-timer, Kubernetes CronJob, AWS EventBridge Scheduler, Vercel Cron — same manifest, same signing contract, swap with one flag.

Polyglot from day one

TypeScript SDK + Go SDK conformance-tested against shared spec vectors. Python, Ruby, and others welcome — the protocol is the product.


Pick a backend


Install in one line

Terminal window
brew install awbx/cronix/cronix

Full install matrix → Install


Status