| Characteristic | Workflow-Triggered Function | Scheduled Function |
|---|---|---|
| What triggers it | A record event (create, edit, field change) | A clock (time, day, date pattern) |
| Records processed | One record at a time (the triggering record) | Multiple records — the function queries and iterates |
| Execution context | Fires in real time when the event occurs | Fires at the configured schedule regardless of events |
| Best for | Real-time responses to individual record changes | Batch operations across many records on a regular schedule |
| Common use cases | Update related record, send notification, calculate field | Nightly cleanup, weekly report, monthly rebalancing |
This function runs every weekday morning at 8am. It identifies deals whose close date has passed without being marked Closed Won or Closed Lost, updates a custom “Overdue” field and creates a task for each deal’s owner to take action.
| // Scheduled function: processOverdueDeals // Schedule: Daily at 08:00 (business days) today = zoho.currentdate; // Find deals where close date is in the past and deal is still open criteria = “(Close_Date:less_than:” + today.toString(“yyyy-MM-dd”) + “)” + ” and (Stage:not_equal:Closed Won)” + ” and (Stage:not_equal:Closed Lost)”; overdueDeals = zoho.crm.searchRecords(“Deals”, criteria, 1, 200); processedCount = 0; for each deal in overdueDeals { dealId = deal.get(“id”); dealName = deal.get(“Deal_Name”); ownerId = deal.get(“Owner”).get(“id”); closeDate = deal.get(“Close_Date”); // Mark deal as overdue updateMap = Map(); updateMap.put(“Is_Overdue__c”, true); updateMap.put(“Days_Overdue__c”, today.daysBetween(closeDate.toDate())); zoho.crm.updateRecord(“Deals”, dealId, updateMap); // Create an action task for the owner (only if no overdue task exists) taskSubject = “ACTION REQUIRED: Update close date — ” + dealName; taskData = Map(); taskData.put(“Subject”, taskSubject); taskData.put(“Due_Date”, today.toString(“yyyy-MM-dd”)); taskData.put(“Priority”, “High”); taskData.put(“Owner”, {“id”: ownerId}); taskData.put(“What_Id”, {“id”: dealId, “type”: “Deals”}); zoho.crm.createRecord(“Tasks”, taskData); processedCount = processedCount + 1; } // Log the execution result info “Processed ” + processedCount + ” overdue deals on ” + today.toString(“yyyy-MM-dd”); |
|---|
Zoho CRM’s searchRecords function returns a maximum of 200 records per call. If your function needs to process more than 200 records, implement pagination: loop through result pages until you get an empty response.
| // Paginated record search pattern pageNum = 1; pageSize = 200; hasMore = true; while(hasMore) { records = zoho.crm.searchRecords(“Deals”, criteria, pageNum, pageSize); if(records.size() == 0) { hasMore = false; } else { for each record in records { // process each record here } pageNum = pageNum + 1; } } |
|---|
Scheduled functions run without a user watching them. Add an info statement at the end of every scheduled function that records what was processed — it appears in the execution log for that function run.
If a scheduled function creates records (tasks, activities) and runs daily, it can create duplicates if the condition that triggers creation persists across multiple days. Add a check before creating any record: search for an existing record with the same key attributes and skip creation if one already exists.
What is a scheduled function in Zoho CRM?
What are the most common use cases for scheduled Deluge functions?
How do I create a scheduled function in Zoho CRM?
Are there limits on scheduled functions in Zoho CRM?
Can ABR build scheduled functions for our Zoho CRM?