Netlify Scheduled Functions Debugging Guide 2026
Debug Netlify scheduled functions with real error patterns, production patterns, and console techniques. Complete walkthrough for indie hackers.
TL;DR
Netlify scheduled functions (background functions) fail silently by default. Enable CloudWatch logs, use console.log() strategically, verify cron syntax with crontab.guru, and test locally with netlify functions:invoke. Real errors include "Task timed out" (15min limit), "Handler not found", and permission issues.
---
Why Scheduled Functions Are Hard to Debug
Unlike HTTP functions, scheduled functions run in the background without immediate feedback. There's no HTTP request to inspect, no browser console, and errors can disappear into the void. Netlify executes these on a schedule you define—if something breaks, you might not notice for hours.
The core issue: Scheduled functions use AWS EventBridge under the hood (verify in [official Netlify docs on scheduled functions](https://docs.netlify.com/functions/overview/#scheduled-functions)), and debugging requires understanding both Netlify's abstraction and AWS CloudWatch logs.
---
Common Error Patterns in Production
Here are three errors you'll see in CloudWatch logs or function invocation responses:
Error 1: Task Timeout ``` Task timed out after 900.00 seconds (15 minutes) ``` Netlify scheduled functions have a hard 15-minute timeout. Long-running database queries, external API calls without timeout handling, or infinite loops trigger this.
Error 2: Handler Export Missing
```
Handler 'handler' not found in 'my-function.js'. Check exports and file location.
```
You exported a named function but Netlify expects a default export, or the file path in netlify.toml is incorrect.
Error 3: Insufficient IAM Permissions ``` User: arn:aws:iam::ACCOUNT:role/netlify-function-role is not authorized to perform: dynamodb:PutItem ``` Your function tries to access AWS services (DynamoDB, S3) but the execution role lacks permissions.
---
Setup: Enable Logging First
Before debugging, enable logging. Add to your netlify.toml:
```toml [[functions]] name = "my-scheduled-function" schedule = "0 9 * * *" path = "netlify/functions/my-scheduled-function.js" ```
Then in your function directory, ensure CloudWatch integration is enabled via your Netlify site settings. You can verify logs in two places:
1. Netlify UI: Site → Functions → Select function → Invocations tab (shows last 100 invocations)
2. AWS CloudWatch: If you've linked your AWS account, logs appear under /aws/lambda/netlify-function-*
---
Production-Ready Scheduled Function Pattern
This is what should ship to production:
```javascript // netlify/functions/daily-sync.js const https = require('https');
const makeRequest = (url, timeout = 8000) => { return new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error('Request timeout')), timeout); https.get(url, (res) => { clearTimeout(timer); let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); }).on('error', reject); }); };
exports.handler = async (event) => {
const startTime = Date.now();
const functionName = 'daily-sync';
try {
console.log([${functionName}] Execution started at ${new Date().toISOString()});
console.log([${functionName}] Trigger: ${event.source || 'unknown'});
// Your scheduled work here
const data = await makeRequest('https://api.example.com/sync', 8000);
console.log([${functionName}] Completed in ${Date.now() - startTime}ms);
return {
statusCode: 200,
body: JSON.stringify({ success: true, duration: Date.now() - startTime })
};
} catch (error) {
console.error([${functionName}] Error: ${error.message}, { stack: error.stack });
// Still return 200 so EventBridge doesn't retry infinitely
return {
statusCode: 500,
body: JSON.stringify({ error: error.message, duration: Date.now() - startTime })
};
}
};
```
Key patterns:
startTime tracking for performance debugging---
Local Testing Before Deploy
Use the Netlify CLI (verify current version in [official docs](https://docs.netlify.com/cli/get-started/)) to test locally:
```bash
Install CLI
npm install -g netlify-cliTest invocation
netlify functions:invoke daily-sync --localWith custom event payload
netlify functions:invoke daily-sync --local --payload '{"test":true}' ```For cron syntax validation, test at [crontab.guru](https://crontab.guru) before deploying. Common mistake: 0 9 * * * runs at 9:00 UTC, not your local timezone.
---
Debugging Checklist
1. Verify the cron expression - Use crontab.guru, double-check timezone assumptions
2. Check handler export - Must be exports.handler or export default handler
3. Review CloudWatch logs - Netlify UI or AWS console for the actual error
4. Add console.log() strategically - Log at function start, before risky operations, and in catch blocks
5. Test timeout scenarios - Artificially delay an external API to confirm timeout handling
6. Confirm IAM permissions - If using AWS services, verify execution role has required permissions
7. Check function size - Verify function doesn't exceed Netlify's [bundle size limits](https://docs.netlify.com/functions/overview/#limits) (verify in official docs)
---
Integration with Error Tracking
For production reliability, send errors to Sentry or similar:
```javascript const Sentry = require('@sentry/node');
Sentry.init({ dsn: process.env.SENTRY_DSN });
exports.handler = async (event) => { try { // your code } catch (error) { Sentry.captureException(error); throw error; } }; ```
This gives you dashboards and alerts instead of silently failing.
---
Related Resources
---
What am I missing?
Have you encountered edge cases with Netlify scheduled functions? Specific error messages not covered here? Leave a comment below—indie hackers often solve these problems in unique ways, and your experience helps the community. Also note: verify all version numbers and pricing in official Netlify docs, as these change quarterly.