Force-dynamic not working for cron jobs

We’re experiencing an issue with our serverless API route that handles reminder emails. Despite implementing safety checks that should prevent reminders from being sent more frequently than every 12 hours, we continue to see reminders being sent at much shorter intervals in our production environment. The same code works correctly in our local development environment.

Technical Details

Endpoint: /api/reminders
Runtime: Edge
Dynamic: force-dynamic

Expected Behavior:

  • Our cron job calls this endpoint periodically
  • The endpoint processes reminder eligibility with safety checks that prevent any reminders from being sent to the same recipient more frequently than every 12 hours
  • The safety check code looks like this:
// SAFETY CHECK: Enforce minimum time between reminders regardless of other logic
if (sme.last_reminder_sent) {
const lastSent = new Date(sme.last_reminder_sent);
const now = new Date();
const hoursSinceLastReminder = (now.getTime() - lastSent.getTime()) / (1000 * 60 * 60);

// Minimum 12 hours between any reminders as a safety measure
const MINIMUM_HOURS_BETWEEN_REMINDERS = 12;

if (hoursSinceLastReminder < MINIMUM_HOURS_BETWEEN_REMINDERS) {
// Block reminder and log the block
return {
success: false,
projectId: project.id,
smeId: sme.sme_id,
reminderType: null,
message: `Safety check: Only ${Math.round(hoursSinceLastReminder)} hours since last reminder (minimum: ${MINIMUM_HOURS_BETWEEN_REMINDERS})`
};
}
}

Actual Behavior:

  • In production, reminders are being sent much more frequently (every 3-6 hours)
  • Local testing confirms the safety check is working properly
  • Database records show the last_reminder_sent field is being updated correctly
  • Our enhanced logging (using console.error) shows the safety checks are working locally

And no logs on vercel:

Questions:

  1. Could multiple concurrent executions of the same serverless function be occurring in Vercel, bypassing our safety checks?
  2. Is there a caching issue where stale data is being used in subsequent function executions?
  3. Are serverless functions in Vercel potentially running with different timestamps/timezones than expected?
  4. Could there be issues with database connection pooling or transaction isolation that’s causing race conditions?
  5. Is there a way to better debug or trace the execution of this function in the Vercel environment?
  6. Anything else?

Additional info

  • We’re using Supabase for our database
  • Our development environment is Next.js 14
  • We don’t see any relevant errors in the Vercel Function logs
  • The issue seemed to start recently without code changes in this area

We’d appreciate any insights or debugging suggestions to help resolve this production-only issue. Please let us know what additional information you might need.

Thank you for your help.

Hello,

does your cron have 308 redirect or trailingslash Troubleshooting Vercel Cron Jobs ?

Hi, I’ve checked my configuration and can confirm I don’t have trailingSlash set in next.config.js (which i believe defaults to false).

My cron job path is set to /api/reminders which matches my API route

My middleware explicitly excludes API routes from processing.

I’ve also observed 404 cache errors in the logs i shared earlier.

Could the 308 redirects be coming from Vercel’s edge network or Next.js’ internal handling? What I’m primarily concerned about is that reminders are being sent too frequently despite safety checks in my code.

UPDATE:

We confirmed a potential 308 redirect issue: Our cron job is correctly configured with ‘/api/reminders’ (no trailing slash)

However, testing shows that if a trailing slash is added (making it ‘/api/reminders/’), a 308 redirect occurs

Your documentation notes that “cron jobs do not follow redirects”
This suggests that occasionally Vercel’s system might be adding a trailing slash despite our correct configuration

  1. Steps we’ve taken:
  • Added comprehensive Cache-Control headers to the endpoint code to prevent caching
  • Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate
  • Pragma: no-cache
  • Expires: 0
  • Surrogate-Control: no-store
  • Double-checked our cron job configuration (it was already correctly set to ‘/api/reminders’ without trailing slash)
  • Enhanced error logging for better visibility

Current status:

  • After deploying these changes and purging the cache, we’re seeing improvements
  • Our application-level safety checks are now properly blocking too-frequent reminders
  • We’re still seeing 404 cache misses in the logs, but these appear to be expected behavior
  • Most importantly, no users are receiving unnecessary reminders

Questions:

  1. Are the 404 cache errors (‘GET Using cache’ followed by 404) normal and expected?
  2. Is there anything else we should implement to make our cron jobs more reliable?
  3. Are there any other best practices for Next.js Edge routes triggered by cron jobs?

Thanks.

This shouldn’t be happening. If you have a reproducible steps, please share with us so we can take a look.

The 404 cache errors you’re seeing (where ‘GET Using cache’ is followed by a 404) are not necessarily expected behavior. This could indicate a few different issues:

  1. Cached responses: When cron jobs respond with a cached response, they might not show up properly in logs . This could explain the ‘Using cache’ message.
  2. Nonexistent paths: If your cron job is configured for a path that doesn’t exist, it will generate a 404 error, but Vercel will still execute the job.

Thought for 4 seconds### Understanding 404 Cache Errors in Cron Jobs

The 404 cache errors you’re seeing (where ‘GET Using cache’ is followed by a 404) are not necessarily expected behavior. This could indicate a few different issues:

  1. Cached responses: When cron jobs respond with a cached response, they might not show up properly in logs . This could explain the ‘Using cache’ message.
  2. Nonexistent paths: If your cron job is configured for a path that doesn’t exist, it will generate a 404 error, but Vercel will still execute the job .

Making Cron Jobs More Reliable

To improve the reliability of your cron jobs:

  1. Secure your cron jobs: Add a CRON_SECRET environment variable and verify it in your endpoint:
export function GET(request: NextRequest) {
  const authHeader = request.headers.get('authorization');
  if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response('Unauthorized', { status: 401 });
  }
  
  // Your cron job logic here
  return Response.json({ success: true });
}
  1. Implement concurrency control: If your cron jobs take too long to run, you might have concurrent invocations. Consider implementing a lock mechanism (e.g., using Redis) .
  2. Error handling: Vercel won’t retry failed cron jobs, so implement robust error handling in your code .
  3. Check logs: Use the “View Logs” button in the Cron Jobs tab to diagnose issues .

For Edge routes triggered by cron jobs:

  1. Be aware of duration limits: Edge functions have duration limits similar to Serverless functions. If you need more processing time, consider splitting your workload .
  2. Handle redirects properly: Cron jobs don’t follow redirects. When a cron-triggered endpoint returns a 3xx status code, the job completes without following the redirect .
  3. Data caching: Verify whether your data requests are being cached appropriately. For Edge routes, ensure you’re using proper caching strategies .
  4. Error boundaries: Implement error handling to gracefully handle failures .
  5. Dynamic rendering considerations: Be mindful that using dynamic APIs will opt your route into Dynamic Rendering, which could affect performance .
  6. Streaming responses: Consider using streaming for long-running processes to improve user experience .

To debug your specific 404 cache errors, I recommend checking your logs and verifying that the paths in your cron job configuration actually exist in your application.