Cron Jobs
Schedule tasks with cronJobs() — interval, daily, weekly, cron
Gencow provides a built-in scheduler for cron jobs. Define scheduled tasks in gencow/crons.ts and they run automatically.
Setup
Create gencow/crons.ts (auto-generated by gencow init):
import { cronJobs } from "@gencow/core";
const crons = cronJobs();
// Define your scheduled jobs here
export default crons; // ← Required!Critical: You must
export default crons— without it, the scheduler won't register your jobs.
Scheduling Methods
interval — Run Every N Minutes/Hours
crons.interval("syncData", { minutes: 30 }, "data.sync");
// Runs data.sync mutation every 30 minutesOptions: { minutes?: number, hours?: number, seconds?: number }
daily — Run Once Per Day
crons.daily("morningReport", { hour: 9, minute: 0 }, "reports.daily");
// Runs reports.daily mutation every day at 09:00Options: { hour: number, minute?: number }
weekly — Run Once Per Week
crons.weekly("weeklyDigest", { dayOfWeek: 1, hour: 10 }, "reports.weekly");
// Runs reports.weekly mutation every Monday at 10:00Options: { dayOfWeek: number (0=Sun, 1=Mon, ..., 6=Sat), hour: number, minute?: number }
cron — Standard Cron Expression
crons.cron("customSchedule", "*/15 * * * *", "tasks.cleanup");
// Standard cron: every 15 minutesInline Handlers
Cloud deployments register only string action cron jobs in the platform scheduler. Inline async handlers can run in local app runtime paths, but they are skipped from the cloud cron manifest because functions cannot be safely serialized into the platform control plane.
Instead of referencing a mutation by name, you can pass an inline async function:
crons.interval("healthCheck", { minutes: 5 }, async (ctx) => {
const result = await fetch(`${process.env.GENCOW_INTERNAL_URL}/health`);
if (!result.ok) {
console.error("Health check failed!");
}
});Complete Example
// gencow/crons.ts
import { cronJobs } from "@gencow/core";
const crons = cronJobs();
// Every 30 minutes: sync external data
crons.interval("syncNews", { minutes: 30 }, "news.sync");
// Every day at 9:00 AM: generate daily report
crons.daily("dailyReport", { hour: 9 }, "reports.generateDaily");
// Every Monday at 10:00 AM: weekly summary
crons.weekly("weeklySummary", { dayOfWeek: 1, hour: 10 }, "reports.generateWeekly");
// Every 15 minutes: cleanup expired sessions
crons.cron("cleanup", "*/15 * * * *", "admin.cleanup");
export default crons;The Mutation Handler
// gencow/news.ts
import { procedure } from "./runtime";
import { news } from "./schema";
export const sync = procedure.mutation
.name("news.sync")
.handler(async ({ context: ctx }) => {
const response = await fetch("https://api.example.com/news");
const articles = await response.json();
for (const article of articles) {
await ctx.db.insert(news).values({
title: article.title,
url: article.url,
fetchedAt: new Date(),
}).onConflictDoNothing();
}
console.log(`Synced ${articles.length} articles`);
});Self-Fetch Pattern
When a cron job needs to call its own server's API:
crons.interval("healthPing", { minutes: 5 }, async (ctx) => {
// Use GENCOW_INTERNAL_URL (auto-injected at server boot)
const url = process.env.GENCOW_INTERNAL_URL;
const res = await fetch(`${url}/api/health`);
console.log("Health:", res.status);
});Note:
GENCOW_INTERNAL_URLis automatically set by the server in both cloud and local modes. Don't hardcode URLs or ports.
Register in index.ts
Make sure your cron module's mutations are exported in gencow/index.ts:
export * as tasks from "./tasks";
export * as news from "./news"; // ← cron handler mutations
export * as reports from "./reports"; // ← cron handler mutationsViewing Cron Status
- Dashboard: Admin Dashboard → Scheduler tab
- Logs: Cron execution results appear in
gencow devconsole output
Cloud Deployment
When you run gencow deploy or cloud dev packaging, the CLI reads gencow/crons.ts and writes a dependency-free .gencow/cron-jobs.json into the deploy bundle. The platform syncs cron_jobs from this manifest instead of importing your TypeScript file in the control-plane process.
This matters because cloud deployment can prune platform packages such as @gencow/core from the app node_modules. Your source should still import cronJobs from @gencow/core; the manifest is the deployment artifact that makes platform cron sync stable.
Important Notes
export default cronsis required — without it, no jobs are registered- Cloud cron handlers must use string mutation action names, not queries; inline async functions are local-runtime only
- Mutation string names (e.g.,
"news.sync") must match exactly:{module}.{export} - All times are in server timezone (UTC in cloud deployments)
- Cron jobs run even when no users are connected
Next Steps
- Deployment — Deploy your app with cron jobs
- AI Engine — Add AI capabilities