Sync

One-way Airtable to Notion sync in n8n without duplicates

Every 15 minutes, pulls Airtable records changed in the last 20 minutes and updates or creates the matching Notion page, keyed on a stored Airtable ID.

Trigger
Schedule Trigger, every 15 minutes
Nodes
9
Requires
Airtable, Notion
Category
Sync
From the course
Notion, Airtable and Google Workspace
Published
2026-09-10

Node types used

  • Schedule Trigger
  • Airtable
  • If
  • Loop Over Items
  • Notion
  • Wait
Workflow diagram: One-way Airtable to Notion sync in n8n without duplicatestruelooptruefalseSchedule TriggerAirtable: changed rec…Airtable: changed recordsAny records to proces…Any records to process?Loop Over ItemsNotion: find matching…Notion: find matching pagePage found?Notion: update pageNotion: create pageWait 250ms
TriggerActionLogic

What it does

Two teams, two tools, and the same records typed into both. The obvious fix is a workflow that creates a Notion page for every Airtable record it sees, which produces a fresh duplicate on every run. The next fix is a second workflow syncing back, which produces a loop. Neither of those is a sync.

A Schedule Trigger runs every 15 minutes. An Airtable search returns only records whose Last modified time is after NOW() minus 20 minutes, so the window overlaps the schedule and a record changed near a run boundary is seen twice rather than missed. An If node checks there is a record id at all before going further. A Loop Over Items node with a batch size of one takes each record in turn. For each one, a Notion node queries the target database for a page whose Airtable ID rich text property equals the record id, returning at most one result and with Always Output Data on so an empty search still produces an item. A second If node checks whether that search returned a page id: if it did, a Notion update writes the Name and the Airtable ID onto the existing page; if it did not, a Notion create makes a new page with the same two properties. Either way a Wait node pauses 250 milliseconds before the loop takes the next record, which keeps the run under the Airtable and Notion request limits.

It is one direction only. Nothing reads Notion back into Airtable, and a record deleted in Airtable leaves its Notion page in place because the Airtable search only returns records that still exist. Only the Name field and the Airtable ID are mapped: add your own property pairs to both Notion nodes if you need more.

Node by node

  1. 1

    Schedule Trigger Fires every 15 minutes.

  2. 2

    Airtable: changed records Searches the configured base and table with the filter formula IS_AFTER({Last modified time}, DATEADD(NOW(), -20, 'minutes')), so each run sees a 20 minute window against a 15 minute schedule. The overlap is deliberate.

  3. 3

    Any records to process? An If node that checks the item has a non-empty id. The false output is empty, so a quiet window ends the run here.

  4. 4

    Loop Over Items Splits the records into batches of one so each record is matched and written individually. The done output is empty; the loop output feeds the Notion lookup.

  5. 5

    Notion: find matching page Queries the Notion database with a JSON filter on the Airtable ID rich text property equalling the current Airtable record id, limit 1. Always Output Data is on, so a miss still produces an item for the next If node to test.

  6. 6

    Page found? An If node checking whether the search result has a non-empty id. True means update, false means create.

  7. 7

    Notion: update page Updates the found page, setting the Name title from the Airtable record Name field and rewriting the Airtable ID rich text property.

  8. 8

    Notion: create page Creates a page in the same database with the Airtable Name as the title and the Airtable record id stored in the Airtable ID rich text property. That stored id is what makes the next run an update instead of a duplicate.

  9. 9

    Wait 250ms Pauses a quarter of a second, then returns to Loop Over Items for the next record. This is the pacing that keeps the run under the Airtable limit of five requests per second.

Setup after import

  1. 1

    Create an Airtable personal access token credential and select it on Airtable: changed records.

  2. 2

    Create a Notion internal integration credential and select it on all three Notion nodes.

  3. 3

    Replace the base id appPLACEHOLDER01 and the table id tblPLACEHOLDER01 on the Airtable node with your own.

  4. 4

    Replace the Notion database URL on both the find and the create node. The export ships with https://www.notion.so/YOUR_NOTION_DATABASE_ID?v=YOUR_VIEW_ID.

  5. 5

    Share the Notion database with your integration. A database that has not been shared returns nothing and the workflow silently creates duplicates instead of finding pages.

  6. 6

    Add a rich text property called Airtable ID to the Notion database, and a Last modified time field to the Airtable table. Both names are referenced literally in the filters.

Limits

  • One direction. Airtable is the source of truth and Notion is overwritten.

  • Deletes do not propagate. A record removed from Airtable leaves its Notion page behind.

  • Only Name and Airtable ID are mapped. Every other field needs adding to both Notion nodes by hand.

  • The lookup is one Notion query per record, so a large batch of changes is slow by design.

  • The 20 minute window assumes runs succeed. A workflow that was off for an hour will not catch up on its own.

Download the workflow

The 9 node export as n8n reads it. Credential ids, personal values and real endpoints are replaced with placeholders, so nothing here can reach an account that is not yours. No email, no account.

Download airtable-to-notion-one-way-sync.json

Get help with this in the community

If the import fails, if a node errors on the first run, or if you want to point this at a service it does not cover yet, post it in the free House of Loops community. Say which template it is and paste the error. Shannon Atkinson answers, and the answer stays there for the next person who hits the same thing.

Ask in the community