Running a Vercel Cron Job Daily in SitecoreAI + Next.js Application
Thursday, September 3, 2026
Summary
When working with SitecoreAI + Next.js, there are often situations where you need to run a server-side script automatically — for example, syncing data, calling an API, cleaning up records, or running some custom business logic.
In a traditional Sitecore application, you might use a Sitecore scheduled task. With SitecoreAI or headless XM Cloud application, I prefer keeping this responsibility in the Next.js application and using Vercel Cron to trigger it.
Here’s a simple setup using the Next.js App Router.
1. Create a Route Handler
Create: src/app/api/cron/daily/route.ts
The route will contain the entry point for our scheduled job.
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const authHeader = request.headers.get('authorization');
if (authHeader !== "Bearer $process.env.CRON_SECRET") {
return NextResponse.json(
{ message: 'Unauthorized' },
{ status: 401 }
);
}
try {
await runDailyJob();
return NextResponse.json({
success: true,
message: 'Daily job completed',
});
} catch (error) {
console.error('Daily job failed:', error);
return NextResponse.json(
{
success: false,
message: 'Daily job failed',
},
{ status: 500 }
);
}
}
async function runDailyJob() {
// Your logic here
console.log('Running daily job...');
}
The important part here is that the endpoint is protected with a secret. We don’t want anyone to be able to call our cron endpoint and trigger the job.
Add the secret to your environment variables:
CRON_SECRET=your-secret-value
Configure Vercel Cron
If your SitecoreAI + Next.js application is hosted on Vercel, add a vercel.json file to the project root:
{
"crons": [
{
"path": "/api/cron/daily",
"schedule": "0 0 * * *"
}
]
}
The cron expression:
0 0 * * *
means every day at 12:00 AM.
One thing to keep in mind is the time zone. Make sure the cron schedule and your business requirement are aligned. If “12:00 AM” means midnight in a specific local time zone rather than UTC, account for that when configuring the schedule.
Keep the Job Logic Separate
As the job grows, I wouldn’t keep all the logic inside route.ts.
Instead, create something like:
src/
├── app/
│ └── api/
│ └── cron/
│ └── daily/
│ └── route.ts
│
└── services/
└── daily-job.tsThen:
// services/daily-job.ts
export async function runDailyJob() {
console.log('Starting daily job');
// Sitecore API calls
// External API calls
// Database operations
// Other business logic
console.log('Daily job completed');
}
And the /cron/daily/route.ts becomes very simple:
import { NextResponse } from 'next/server';
import { runDailyJob } from '@/services/daily-job';
export async function GET(request: Request) {
const authHeader = request.headers.get('authorization');
if (authHeader !== "Bearer $process.env.CRON_SECRET") {
return NextResponse.json(
{ message: 'Unauthorized' },
{ status: 401 }
);
}
try {
await runDailyJob();
return NextResponse.json({ success: true });
} catch (error) {
console.error('Daily job failed:', error);
return NextResponse.json(
{ success: false },
{ status: 500 }
);
}
}
This keeps the cron endpoint responsible for triggering the job while the service contains the actual business logic.
Test It Locally
Before deploying, you can test the endpoint manually:
curl -H "Authorization: Bearer your-secret-value" http://localhost:3000/api/cron/daily
You should get:
{
"success": true
}
The Final Setup
The overall flow is pretty simple:
Vercel Cron
│
│ Every day at 12:00 AM
▼
/api/cron/daily
│
▼
runDailyJob()
│
├── Sitecore
├── External APIs
├── Database
└── Other business logicFor a SitecoreAI + Next.js App Router application, this is a lightweight way to handle scheduled server-side work without introducing a separate cron server or coupling the job to the Sitecore platform.
For larger or long-running jobs, I’d consider pushing the actual work to a background queue rather than doing everything inside the HTTP request.
Running Cron Jobs in Lower Environments
Vercel Cron Jobs are automatically invoked only for Production deployments. Preview deployments and other lower environments do not receive scheduled Cron invocations.
If the Cron Job needs to run automatically in lower environments such as Development, QA, or Staging, an external scheduler can be used to invoke the same API endpoint.
For example, Windows Task Scheduler or Azure Logic Apps can periodically make an HTTP request to the lower-environment deployment:
Windows Task Scheduler
|
│ Every day at 12:00 AM
▼
https://qa.example.com/api/cron/daily
│
▼
Cron Job
OR
Azure Logic Apps
|
│ Scheduled HTTP request
▼
https://qa.example.com/api/cron/daily
|
│
▼
Cron Job
Azure Logic Apps provides a Recurrence trigger and can make HTTP/HTTPS requests to external endpoints, making it a good option when the application is already using Azure.
The endpoint can be secured using the same CRON_SECRET pattern:
curl -H "Authorization: Bearer $CRON_SECRET" https://qa.example.com/api/cron/daily
Use a different CRON_SECRET for each environment so that the QA/Staging scheduler never has access to the Production secret. Vercel also recommends using CRON_SECRET to secure Cron Job invocations.
The resulting setup can be:
Local → Manual HTTP request
Development → Windows Task Scheduler / Azure Logic Apps
QA → Windows Task Scheduler / Azure Logic Apps
Staging → Windows Task Scheduler / Azure Logic Apps
Production → Vercel Cron
This approach allows the same Cron API and business logic to be used across all environments, while the scheduling mechanism changes depending on the environment. Production uses Vercel Cron, while lower environments use an external scheduler.
Conclusion
Using Vercel Cron with a Next.js Route Handler gives us a simple and flexible way to run scheduled server-side tasks in a SitecoreAI + Next.js application.
Instead of relying on traditional Sitecore scheduling, the job lives with the Next.js application and can easily interact with Sitecore, external APIs, databases, or other services. It also keeps the implementation lightweight, easy to maintain, and independent of the Sitecore CM environment.
For SitecoreAI projects, this approach fits nicely with the headless and cloud-native architecture—Sitecore focuses on content management, while Next.js handles the application logic and scheduled workloads.
Overall, it gives us a clean separation of responsibilities and an easy way to add automation without introducing additional infrastructure.