Cron Jobs
Run scheduled work on a Cloudflare Cron Trigger.
Scheduled work runs as a Cloudflare Cron Trigger
on the opb-brain-api Worker. One job is scheduled today: /cron/keep-alive, daily at 01:00 UTC.
Writing the work
A scheduled job is an ordinary route handler in apps/api. Keeping it a route
rather than inline Worker code means it has one implementation, one authorization check, and can be
exercised with curl like anything else.
Put new handlers under apps/api/app/cron/:
import { database } from '@repo/database';
export const GET = async (request: Request): Promise<Response> => {
// Authorize before doing anything — a cron endpoint is publicly reachable.
return new Response('OK', { status: 200 });
};The shipped keep-alive job runs SELECT 1 against D1 as a liveness probe. It used to exist to
stop a serverless Postgres instance suspending between requests; D1 does not suspend, and the job
was kept only because the health signal is still useful.
Scheduling
The schedule lives in the Worker config:
"triggers": {
"crons": ["0 1 * * *"]
}How the trigger reaches the route
apps/api/worker.ts is the Worker entrypoint. It re-exports the fetch handler OpenNext generates
— so HTTP behaviour is exactly what Next.js produced — and adds a scheduled handler that calls
the route through that same fetch with the CRON_SECRET bearer token:
async scheduled(_event, env, ctx) {
const request = new Request('https://opb-brain-api/cron/keep-alive', {
headers: { authorization: `Bearer ${env.CRON_SECRET}` },
});
const response = await openNextWorker.fetch(request, env, ctx);
if (!response.ok) {
throw new Error(`Keep-alive probe failed with ${response.status}.`);
}
}Throwing marks the scheduled invocation as failed, so it shows up in Workers observability rather than passing silently.
Authorization
The route compares the bearer token with timingSafeEqual. Without a valid token it returns 401;
without CRON_SECRET configured at all it returns 503 rather than running unauthenticated. Set
the secret per Worker:
cd apps/api && bunx wrangler secret put CRON_SECRETTriggering manually
curl -H "authorization: Bearer $CRON_SECRET" http://localhost:3002/cron/keep-aliveLocally, wrangler dev also exposes /__scheduled to fire the trigger by hand.