Timer Functions
Timer functions execute on a schedule you define. Use them for background jobs, cleanup tasks, report generation, and periodic syncs.
How It Works
- Set an interval (e.g., every 5 minutes, every 2 hours, daily)
- Configure a start time (UTC)
- Write JavaScript code or configure an external webhook
- Function runs automatically at each interval
Configuration
Schedule Settings
| Setting | Description |
|---|---|
| Interval | Number of time units between executions |
| Frequency | Unit of time: Minutes, Hours, or Days |
| Start Time (UTC) | When the first execution should occur |
Examples
| Interval | Frequency | Result |
|---|---|---|
| 5 | Minutes | Every 5 minutes |
| 1 | Hours | Every hour |
| 12 | Hours | Twice daily |
| 1 | Days | Once daily |
| 7 | Days | Weekly |
Automatic Tracking
The system automatically tracks:
| Property | Description |
|---|---|
| Last Run | When the function last executed |
| Next Run | Calculated from last run + interval |
Execution Context
Timer functions receive limited context since they're not triggered by a request:
| Property | Description |
|---|---|
scheduledTime | When the execution was scheduled |
user | Service account (if configured) |
Token Options
| Option | Description |
|---|---|
| None | No authentication |
| Service Account | Execute with service account permissions |
note
Timer functions typically use a service account since there's no "current user" triggering the execution.
Use Cases
Cleanup Jobs
Remove old or expired data:
// Delete sessions older than 24 hours
const cutoff = new Date();
cutoff.setHours(cutoff.getHours() - 24);
await fetch(`${apiUrl}/sessions?filter=createdAt lt "${cutoff.toISOString()}"`, {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${token}` }
});
console.log('Cleaned up expired sessions');
Report Generation
Generate periodic reports:
// Daily sales summary
const today = new Date().toISOString().split('T')[0];
const response = await fetch(
`${apiUrl}/orders?filter=orderDate eq "${today}"`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const orders = await response.json();
const totalSales = orders.reduce((sum, o) => sum + o.total, 0);
const orderCount = orders.length;
// Store the report
await fetch(`${apiUrl}/daily-reports`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
date: today,
totalSales,
orderCount,
averageOrder: orderCount > 0 ? totalSales / orderCount : 0
})
});
External Sync
Sync data with external systems periodically:
// Sync inventory from warehouse system every hour
const response = await fetch('https://warehouse.example.com/api/inventory', {
headers: { 'Authorization': `Bearer ${secrets.WAREHOUSE_API_KEY}` }
});
const inventory = await response.json();
for (const item of inventory) {
await fetch(`${apiUrl}/products/${item.sku}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ stockLevel: item.quantity })
});
}
console.log(`Synced ${inventory.length} inventory items`);
Status Checks
Monitor external services or data conditions:
// Check for orders stuck in processing
const oneHourAgo = new Date();
oneHourAgo.setHours(oneHourAgo.getHours() - 1);
const response = await fetch(
`${apiUrl}/orders?filter=status eq "processing" and updatedAt lt "${oneHourAgo.toISOString()}"`,
{ headers: { 'Authorization': `Bearer ${token}` } }
);
const stuckOrders = await response.json();
if (stuckOrders.length > 0) {
// Alert operations team
await fetch('https://slack.webhook.url', {
method: 'POST',
body: JSON.stringify({
text: `⚠️ ${stuckOrders.length} orders stuck in processing for over 1 hour`
})
});
}
Data Aggregation
Pre-calculate aggregates for performance:
// Update category statistics every 15 minutes
const categories = await fetch(`${apiUrl}/categories`, {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
for (const category of categories) {
const products = await fetch(
`${apiUrl}/products?filter=categoryId eq "${category.id}"&count=true`,
{ headers: { 'Authorization': `Bearer ${token}` } }
).then(r => r.json());
await fetch(`${apiUrl}/categories/${category.id}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
productCount: products.meta.count,
lastUpdated: new Date().toISOString()
})
});
}
Best Practices
- Use appropriate intervals — Don't run more frequently than needed
- Handle failures gracefully — Timer functions will retry on next interval
- Log execution details — Track what was processed for debugging
- Use service accounts — Ensure consistent permissions
- Consider time zones — Start times are in UTC
- Monitor execution — Check logs for failures or long-running jobs