DEV Community

Cover image for Set It and Forget It: Scheduling Weekly Data Syncs in Retool
DonMacDonHadAFarm
DonMacDonHadAFarm

Posted on

Set It and Forget It: Scheduling Weekly Data Syncs in Retool

Set It and Forget It: Scheduling Weekly Data Syncs in Retool

If you've ever manually pulled a report, cross-checked it against a spreadsheet, and re-entered the results into your CRM — you know how much time that eats every single week. Here's how I replaced that whole routine with one scheduled Retool Workflow, and why the same setup works no matter what your source or destination system actually is.

What is a Retool Workflow, and why bother with it here?

A Retool Workflow is a backend automation built visually — a chain of blocks (queries, code, conditionals, API calls) that runs on its own, no user needed. Unlike a regular Retool app, which waits for someone to click something, a Workflow can run on:

  • A schedule (cron-based)
  • A webhook, when another system fires an event
  • Another workflow calling into it

The schedule trigger is the piece that matters for recurring internal tasks — the ones that are simple in logic but easy to mess up or forget when a human's doing them by hand every week.

Where this pattern shows up

Data syncs between two systems that don't talk natively. Recurring reports pushed to a team channel — Slack, ClickUp, wherever your team actually looks. Cleanup jobs. Basically any task where the answer to "who's responsible for this" is technically a person but should really be a machine.

The example: RDS → Retool → Zoho CRM

Here's the actual shape of what I built. Our employee hours data lives in Postgres on AWS RDS — a separate weekly batch job already loads it there, so by the time Retool touches it, the numbers are sitting in a table ready to query. From there, the workflow pulls the week's totals and pushes them into Zoho CRM so the whole team can see updated productive hours without anyone opening a spreadsheet.

The part worth paying attention to: Retool doesn't care that the source is RDS Postgres specifically. Swap that resource connection for MySQL, a REST endpoint, Airtable, whatever — the rest of the workflow barely changes. Same goes for the destination. Zoho happens to be what we use, but the pattern holds for HubSpot, Salesforce, or any CRM with an API. That's really the point of building this in Retool instead of hardcoding a script somewhere — the connectors are swappable, the logic isn't.

The flow, block by block

1. Trigger — weekly schedule

0 6 * * 1   # every Monday, 6am
Enter fullscreen mode Exit fullscreen mode

Retool's schedule trigger takes a standard cron expression, so nothing external to manage.

2. Query block — pull the week's hours from RDS

Connected directly to our Postgres resource in Retool:

SELECT employee_id, full_name, SUM(hours_logged) AS weekly_hours
FROM payroll.time_entries
WHERE entry_date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY employee_id, full_name;
Enter fullscreen mode Exit fullscreen mode

3. Code block — shape the payload

This is the step that took the most trial and error, honestly — Zoho's API is picky about field names and won't tell you clearly when a payload's malformed, it just silently fails the record. Worth testing this block in isolation before wiring it further.

return query1.data.map(row => ({
  employee_id: row.employee_id,
  field_updates: {
    Weekly_Productive_Hours: row.weekly_hours
  }
}));
Enter fullscreen mode Exit fullscreen mode

4. Loop block — push each record to Zoho

This is where the payload from the previous step actually gets used. A loop block takes that array and runs a POST/PUT request against the Zoho API once per iteration, one record at a time, using each employee's ID and hours total as the request body. This is really the piece that makes Retool worth building this in over a raw script — the loop block, the API resource, and the payload are all separate, reusable pieces instead of one tangled function, so if the destination ever changes, you're really just swapping which API resource the loop calls.

One gotcha here: looping through updates too fast tripped Zoho's rate limit the first time I ran this against the full team. Adding a short delay between iterations fixed it — worth checking your CRM's rate limits before pointing this at a large dataset.

5. Notify block — reuse an existing ClickUp connection

Our team runs on ClickUp rather than Slack, so this step posts a custom message to a ClickUp channel confirming the sync ran and how many records were updated. Rather than building that from scratch, this calls a query that's already sitting in Retool's shared query library — a small reusable node set up once for "post a message to ClickUp" that any workflow can call. That's the other thing worth calling out about building this in Retool: once you've built one notification step, you don't rebuild it for the next automation, you just reuse the existing query and swap the message text. It cuts down on exactly the kind of repetitive setup that makes automations tedious to maintain over time.

Why this is worth building over doing it by hand

No missed weeks, no copy-paste errors, and a log of every run so you can see exactly what happened if a number looks off. And because the RDS and Zoho connections are just resources in Retool, this same skeleton has since been reused for two other syncs on completely different systems — barely touched the logic, just swapped the connectors.

A few things I'd tell myself before starting

Test each block on its own first — don't wire the whole chain and hope. Add error handling before you trust it running unattended; one bad record shouldn't silently kill the whole run. Run it manually a few times before letting the cron trigger touch production data. And keep the notification step even though it feels unnecessary once things are working — it's the only thing that tells you when it quietly stops.

If you're working with Retool and want to go deeper on any of these blocks, I'm writing more from this series — happy to answer questions in the comments.

Top comments (0)