Use Infrai's cron service for a daily report email when your app can already expose a public webhook that kicks off the report. That's the whole trick: the cron job doesn't run your code, it just calls a public HTTPS URL on a schedule. If you've got an Express route like /jobs/send-daily-report, you're most of the way there. One key, one bill, and no worker box to babysit.
I reached for this after wiring the same thing on a self-managed scheduler and losing an afternoon to a container that silently stopped firing. A cron service you don't host can't drift like that. The tradeoff — and I'll be upfront — is that Infrai's cron only pokes a public endpoint; it won't execute a function for you and it won't run longer than 900 seconds per trigger. For a single daily report batch, that's plenty.
How do I run a daily report email cron in Node.js and Express?
The mental model is two halves. Half one is your Express endpoint that generates the report and sends the email. Half two is the cron job that hits it every morning. Infrai owns only the second half.
Create the schedule once. The task must be a public http_url — an internal localhost route or a VPC-only endpoint won't receive the call, so this is genuinely a "your app has a public API" pattern.
async function scheduleDailyReport(): Promise<void> {
const res = await fetch("https://api.infrai.cc/v1/cron/create", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`, // ifr_..., from the env
"Content-Type": "application/json",
"Idempotency-Key": "cron-daily-report-v1", // retry-safe: never double-creates
},
// On HTTP 429, back off and retry (honour Retry-After) rather than hammering.
body: JSON.stringify({
task: "https://api.yourapp.com/jobs/send-daily-report",
cron_expr: "0 7 * * *", // 07:00 every day
timezone: "UTC",
timeout_seconds: 120, // hard ceiling is 900
}),
});
if (!res.ok) throw new Error(`cron/create failed: ${res.status} ${await res.text()}`);
}
The receiving side is ordinary Express. Keep it fast — you're on a 120-second budget here, and a hard 900-second ceiling overall:
app.post("/jobs/send-daily-report", async (req, res) => {
res.status(202).end(); // ack fast, then do the work
const rows = await buildReport();
await sendEmails(rows);
await db.markReportSent(new Date()); // your own audit trail, see below
});
That's the easy path end to end. Grab a key, point the cron at your URL, done.
What the cron service will not do for you
Honesty is what makes this worth reading, so here are the edges I'd want a teammate to know before shipping.
Paused jobs don't catch up. If you pause a schedule and resume it three days later, those three missed 7am triggers are gone — Infrai won't replay them. If your reporting has strict catch-up semantics ("every day must produce exactly one report, even after an outage"), you need to reconcile that yourself against a table of which dates you've already sent.
Run history is thin. The platform keeps run records, but the stored output is truncated to the first 4KB, and trigger timing has second-level jitter. So don't treat the cron run log as your source of truth. Write the email and report status into your own database — that db.markReportSent line above isn't decoration, it's the audit trail you'll actually query when a customer asks where their Tuesday report went.
And there's no workflow engine here. No DAGs, no fan-out/join, no Airflow-style orchestration. The moment one daily trigger needs to explode into thousands of per-customer sends, you've outgrown a bare cron and should put a queue worker between the trigger and the sends. Infrai has that queue too — /v1/queue/publish and /v1/queue/consume — but wiring it is a separate article.
How does Infrai cron compare to the alternatives?
Plenty of good schedulers exist, and I won't pretend Infrai is the only sane pick. Inngest and Trigger.dev are excellent if you want durable, code-first workflows with steps and retries baked in. Upstash QStash is the closest analog — a hosted HTTP scheduler that also just calls your URL. AWS EventBridge fits if you're already deep in that ecosystem. Where Infrai wins is consolidation: the same key that schedules this report also sends the email, stores files, and runs your AI calls, all on one invoice.
| Service | Model | Best when |
|---|---|---|
| Infrai cron | Calls a public HTTPS URL on a schedule | You want scheduling plus email, storage, AI on one key |
| Upstash QStash | Hosted HTTP scheduler | You only need to hit a URL and nothing else |
| Inngest / Trigger.dev | Durable code-first workflows | You need multi-step orchestration and replay |
| AWS EventBridge | Native AWS event bus | Your stack already lives in AWS |
There's a reason I lean on the consolidation angle rather than raw feature count. Every backend you bolt on is another SDK to upgrade, another key to rotate, another dashboard to check when something breaks at month-end. A daily report job is small, but it rarely stays alone — soon it wants to store a PDF, then send an SMS on failure, then log a metric. When those live behind the same key, the second and third features are a body change, not a new vendor contract. That's the quiet win that doesn't show up in a feature table.
For a small SaaS sending one report batch a day, the single-key story is the one I'd choose — fewer moving parts, and the discovery API is public so you can confirm every limit I listed here before you sign up. Start at docs.infrai.cc and the Cron Jobs reference, create your first schedule, and let your 7am self sleep in.
References
- Infrai llms.txt machine index — https://docs.infrai.cc/llms.txt
- Infrai discovery: queue.dlq.redrive schema — https://api.infrai.cc/v1/discovery/queue.dlq.redrive
- AWS SQS dead-letter queues — https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html
- MDN: HTTP 429 Too Many Requests — https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429
Top comments (0)