Implementing Recurring Tasks in Deta Space with Scheduled Actions
Learn how to use Scheduled Actions in Deta Space to run recurring background tasks like database cleanup and API polling without external cron services.
06 Mar 2026, 16:27 UTC

Automating Background Tasks Without External Schedulers
The primary challenge of running stateless compute units, such as Deta Space Micros, is the lack of a persistent background process to handle recurring tasks. Relying on external cron services or third-party pingers introduces unnecessary complexity and security risks. The solution is Scheduled Actions, a built-in mechanism that allows you to trigger specific functions within your Micro on a fixed interval defined in your Spacefile.
How Scheduled Actions Work
A Scheduled Action is a platform-level trigger. Instead of an external HTTP request, the Deta Space runtime sends an internal event to your Micro. Because your Micro may handle both standard web traffic and these scheduled events, your code must be able to distinguish between the two. If you treat a scheduled event as a standard HTTP request, your app may throw errors when it fails to find request headers or body data.
Configuration Example: Database Cleanup Job
Consider a scenario where you need to prune records older than 30 days from a Deta Base to maintain performance. This requires a scheduled action that runs once per day.
1. Spacefile Declaration
Define the trigger in your Spacefile. This tells the platform when to wake up your Micro and which handler to invoke.
[micro]
name = "cleanup-service"
# Runs every day at 03:00 UTC
scheduled_actions = [
{ name = "daily_prune", trigger = "0 3 * * *", handler = "cron_handler" }
]
2. Implementation (Node.js)
In your application code, ensure the handler is decoupled from the HTTP request object. Use the Deta SDK to target the specific base you wish to clean.
// Example using a generic handler pattern
async function cron_handler(event) {
// 1. Verify the event source to avoid accidental manual triggers
if (event.type !== 'scheduled') {
return { status: 400, body: 'Only scheduled events allowed' };
}
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
try {
// Logic to delete records older than the calculated date
await dbase.deleteMany({
filter: { created_at: { lt: thirtyDaysAgo.toISOString() } }
});
console.log('Cleanup successful');
} catch (err) {
console.error('Cleanup failed:', err);
throw err; // Let the platform log the failure
}
}
Operational Constraints and Limitations
- Execution Timeouts: Micros have a maximum execution duration. If your cleanup job processes millions of rows, it may be killed by the runtime before completion. For large datasets, implement pagination or batching.
- Timing Precision: Scheduled actions are "best-effort." While they generally trigger on time, they are not guaranteed to run at the exact second specified. They are unsuitable for high-precision timing (e.g., financial trade execution).
- Granularity: Sub-minute scheduling is not supported. The minimum interval is typically one minute.
- Timezones: All cron expressions are interpreted in UTC. If your task must run at 3:00 AM EST, you must manually calculate the UTC offset (e.g., 08:00 UTC).
Common Implementation Mistakes
Assuming Persistent Local Storage
A common error is writing a temporary file to the local disk during a scheduled run and expecting it to be there during the next run. Micros are stateless; any data that must persist between intervals must be stored in Deta Base or Deta Drive.
Missing Error Handling
Unlike a user-facing request where you can return a 500 error to a browser, a scheduled action fails silently in the background. Always wrap your logic in try-catch blocks and use console.log or console.error to ensure failures are visible in the Space logs.
Verification and Testing
To verify your scheduled action is working without waiting 24 hours, follow these steps:
- Shorten the Interval: Temporarily change the
Spacefiletrigger to*/5 * * * *(every 5 minutes). - Log the Payload: Add
console.log(JSON.stringify(event))at the start of your handler to confirm the event structure. - Check the Visor: Open your Space dashboard logs. Look for the execution logs coinciding with the 5-minute interval.
- Verify State Change: If the task writes to a Base, check the Base UI to ensure new entries are appearing at the expected cadence.
Rollback: To disable the scheduled action, remove the scheduled_actions block from your Spacefile and redeploy the app.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.