Deciding that a sync should send only the records that changed is the easy part. The work is in knowing, on every run, exactly which records those are, and in not losing one when a request fails halfway through.
InAir's guide to running Airtable inside complex system landscapes describes the problem this solves: a CRM that rewrites every customer record every fifteen minutes, overwriting fields it doesn't own and spending the base's request capacity on updates that change nothing. The fix it names has two forms, an event-based trigger and timestamp validation, and both run on the sending system. This post is about building them.
Airtable has no way to know which records changed in another system, so the sending system has to decide what to send. That also keeps the comparison simple. Timestamp validation compares two times that both come from the sending system: when a record was last updated there, and when it was last sent to Airtable successfully. Airtable's own last-modified time plays no part in deciding what to send.
An event-based sync is triggered by a change to a field the sender owns. The edit itself is the signal to send the record.
It's the more immediate of the two methods, and it needs care at the receiving end, because events don't always arrive the way they were produced. Stripe's webhook documentation is a clear example of what to plan for. It states that Stripe "doesn't guarantee the delivery of events in the order that they're generated", that an endpoint "might occasionally receive the same event more than once," and that failed deliveries are retried "for up to three days with an exponential back off in live mode." Other systems behave differently, so check the documentation of the one you're connecting.
For a sync into Airtable, that leaves two things to build and one gap to cover:
Timestamp validation keeps the schedule but changes what each run does. Before sending anything, the sync asks the sending system for the records updated since its last successful run, and sends only those.
The detail that decides whether this is reliable is when that "last successful run" time is recorded. A dependable version works like this:
A record edited while the run is in progress has an update time later than the start, provided the sending system sets that time when the change is saved, so the next run picks it up. Saving the finish time instead would skip that edit until the record changes again.
If a request fails partway through, the marker doesn't move to the run's start time. It moves only as far as the earliest update time among the records that weren't confirmed, so those records, and anything updated after them, are sent again on the next run with their current values. Records that were confirmed and come round again are written with the same values, which changes nothing. With the version check from Method 1 in place, those writes are skipped altogether.
The two methods cover each other's gaps. Events keep Airtable close to current, and a scheduled check running less often, every hour for example, sends anything changed since its marker, which includes any edit whose event was lost. Both paths go through the same queue and the same version check. Anything the check finds that already arrived by event is skipped, and once both paths pass through that check, an older version can't replace a newer one, whichever path it came from.
Change detection answers one question: which records changed in the sending system. A few things fall outside it, and each needs its own handling.
Sending fewer records doesn't mean sending fewer fields. When a record is sent, it carries every field the sending system owns, not just the one that changed, so an owned field that was altered in Airtable is set back to the sender's value. A field both systems legitimately write has no single owner, so it needs a conflict rule rather than an overwrite. Cross-System Source of Truth covers that rule and how to decide ownership. Fields the sender doesn't own are left out, and the request is a PATCH, which updates only the fields included in the request.
This is also why change detection lowers a landscape's Integration Load. The framework measures update frequency by what each sync actually sends, and the cost of a run depends on how many records it writes, as Why Update Frequency Changes Your Integration Risk [DRAFTED, NOT LIVE: Cluster 2.1.2] works through in numbers.
In a sandbox, run four checks:
If all four pass, what the sync sends follows real edits in the sending system, not the clock.
If you want to find out which of your syncs are still rewriting every record, and switch them over without interrupting the data they carry, Schedule a Discovery Call with InAir and we'll work through them with you.