Blog · 2026-07-20

Scheduled jobs without cron infrastructure

Run scheduled jobs on DenkOps with an in-process scheduler. setInterval or APScheduler in an always-on slot, no cron service, no cold starts.

You do not need cron infrastructure to run scheduled jobs on DenkOps. Your app runs in an always-on slot, the process never stops, so a plain in-process scheduler, setInterval in Bun or APScheduler in Python, fires on time every time. There is no platform cron primitive because a long-lived process makes one unnecessary.

Why does an always-on slot replace cron?

Cron services exist to solve one problem: your code is not running when the schedule fires, so something external has to wake it up. Serverless platforms make this worse, every tick cold-starts a fresh function with no memory of the last run, capped at a few minutes of runtime.

A slot is a process, not a function. It stays up between requests, which means a timer you start at boot keeps ticking indefinitely. No trigger configuration, no separate service, no timeout on how long a job may run.

What does a scheduled job look like in Bun?

A timer next to your routes, in the same file you already deploy:

import { Hono } from "hono";
import denkops from "@denkopsai/sdk";

const app = new Hono();

function nightlyReport() {
  const last = denkops.store.get("report:last-run");
  console.log("running nightly report, last run:", last);
  // ... do the work ...
  denkops.store.set("report:last-run", new Date().toISOString());
}

// fire once a day from inside the long-lived process
setInterval(nightlyReport, 24 * 60 * 60 * 1000);

app.get("/health", (c) => c.json({ ok: true }));

export default { port: 3000, fetch: app.fetch };

In Python the same shape works with APScheduler inside FastAPI: add a job in the lifespan hook, start the scheduler, done. The FastAPI cron guide has the full snippet, and the Express version shows node-cron if you want cron-expression syntax instead of a fixed interval.

What happens to my schedule on a redeploy?

The timer is in-memory, so a redeploy restarts it with the fresh process. That is why the example above checkpoints to denkops.store: the KV store lives on the durable /persist disk and survives redeploys. The pattern is simple:

  • Write a checkpoint when a run finishes: a timestamp, a cursor, the last processed ID.
  • Read it at the start of each run and continue from there.
  • If a redeploy lands mid-run, the next tick picks up from the last checkpoint instead of starting over or double-processing.

For a nightly job the worst case after a redeploy is that the first tick fires up to one interval later than usual. If the exact hour matters, check the clock inside a shorter interval: run setInterval every minute, compare against the checkpoint, and do the work only when the target hour arrives and the last run is stale.

When would I still want external scheduling?

If nothing else about your app needs a server, a scheduled job alone may feel heavy. But in practice scheduled work rarely lives alone: the same process usually serves an API, a webhook, or an MCP endpoint, and the scheduler rides along for free. One deploy, one URL, one place to read logs, and state shared in memory between your routes and your jobs.

FAQ

Does DenkOps have a cron feature?

No, and it does not need one. Apps run in an always-on slot, so an in-process scheduler like setInterval in Bun, or APScheduler or node-cron in other runtimes, fires reliably without any external trigger infrastructure.

Do scheduled jobs survive a redeploy?

The timer restarts with the new process, so checkpoint progress to denkops.store. It writes to the durable /persist disk, so a timestamp or cursor saved after each run survives redeploys and the next tick resumes cleanly.

Is there a time limit on a scheduled job?

No. Unlike a serverless cron function capped at a few minutes, a job inside your slot runs as long as it needs, because it is just code executing in your own long-lived process.

Ship it yourself: bunx denkops deploy or say "deploy on DenkOps" from your coding agent.

Start on DenkOps →

← Team workspaces for agent backends