How to Use n8n for Scheduled Batch API Syncs Without External Storage
Imagine you're maintaining a tools database in Baserow that should stay in sync with a JSON list. Your goals:
- Add new tools when they appear on your list.
- Update existing ones if they haven’t been synced recently.
- Re-run AI enrichment (like LLM tagging) only when necessary.
This pattern works for many use cases: syncing products, users, articles, datasets, and more.
In this tutorial, you’ll learn how to build a scheduled batch sync in n8n that:
- Pulls data from a remote API (e.g., Crunchbase),
- Compares it with local records (e.g., Baserow),
- Decides whether to create or update records,
- All without using any external database, cache, or storage layer.
This method uses n8n's workflowStaticData
to manage state internally and batch processing nodes to handle large payloads efficiently.
What You’ll Learn
- How to initialize and persist state using
workflowStaticData
- How to loop through large datasets using
Split In Batches
- How to conditionally generate batch
create
andupdate
payloads - How to perform Baserow batch writes efficiently
Step 1: Schedule the Workflow
Use the Cron node to run this sync weekly or monthly. You can adjust it later for more frequent intervals.
Step 2: Pre-Fetch Existing Records from Baserow
Use the Baserow “List Rows” node to fetch all existing tools. You'll use this as your lookup base.
Immediately after, add a Code
node to build a lookup map and initialize two empty arrays for later use.
The lookup map avoids repeated Baserow API calls.
const toolMap = {};
for (const item of items) {
const data = item.json;
if (data.g2_product_id) {
toolMap[data.g2_product_id] = {
row_id: data.id,
status: data.status,
last_llm_run_at: data.last_llm_run_at
};
}
}
const staticData = $getWorkflowStaticData('global');
staticData.baserowToolMap = toolMap;
staticData.batch_create_list = [];
staticData.batch_update_list = [];
return items;
Step 3: Fetch New G2 Data
Use an HTTP node to pull the latest tool data from the G2 API. Limit to key fields like name
, link
(as ID), and any others you need.
Step 4: Split the JSON List into Batches
Use “Split In Batches” to break large datasets into smaller chunks (e.g., 50–100 tools each).
This protects you from hitting API limits and gives you more control.
Step 5: Process Each Batch with Code
Add a Code
node right after the Split to process each batch:
const staticData = $getWorkflowStaticData('global');
const toolMap = staticData.baserowToolMap;
let createList = staticData.batch_create_list;
let updateList = staticData.batch_update_list;
const today = new Date().toISOString().split('T')[0];
const oneMonthAgo = new Date();
oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1);
for (const item of items) {
const g2Tool = item.json;
const existing = toolMap[g2Tool.link];
if (!existing) {
createList.push({
name: g2Tool.name,
g2_product_id: g2Tool.link,
created_at: today,
last_synced_g2_at: today,
status: 'New - Needs LLM'
});
} else {
const { row_id, status, last_llm_run_at } = existing;
const updatePayload = {
id: row_id,
last_synced_g2_at: today
};
const needsReRun = (() => {
const skipStatuses = ['New - Needs LLM', 'Needs LLM Re-run', 'LLM Failed'];
if (skipStatuses.includes(status)) return false;
if (!last_llm_run_at) return true;
const lastRun = new Date(last_llm_run_at);
return lastRun < oneMonthAgo;
})();
if (needsReRun) {
updatePayload.status = 'Needs LLM Re-run';
}
updateList.push(updatePayload);
}
}
staticData.batch_create_list = createList;
staticData.batch_update_list = updateList;
return items;
Step 6: Batch Create in Baserow
Use the Baserow “Create Rows (Batch)” node.
Batch write nodes let you scale to thousands of records without overwhelming your systems.
- Enable batching
- Set batch size:
100
- Interval:
500ms
Use this JSON body:
{
"items": {{ JSON.stringify($json.batch_create_list) }}
}
Step 7: Batch Update in Baserow
Use the Baserow “Update Rows (Batch)” node.
{
"items": {{ JSON.stringify($json.batch_update_list) }}
}
The LLM re-run logic avoids unnecessary re-processing.
Summary
With just one scheduled workflow, you’ve built a system that:
- Tracks known vs unknown records,
- Decides what needs to be created or updated,
- Manages batching and freshness logic.
ABOUT ME
I'm Juliet Edjere, a no-code professional focused on automation, product development, and building scalable solutions with no coding knowledge.
I document all things MVP validation and how designs, data, and market trends connect.
Click. Build. Launch.
Visit my website → built with Carrd and designed in Figma