InAir's Latest Insights on Airtable

Building a Cross-System Agreement Check: Catching Quiet Integration Drift Before It Compounds

Written by Julia Eboli | Nov 3, 2026, 8:00:28 PM

Some integration failures never produce a signal. The CRM owns the customer's phone number and syncs it one way to Airtable, sending only records that changed in the CRM. A support agent edits the number in Airtable during a ticket. The edit saves, nothing carries it back, and the next sync skips the record because nothing changed on the CRM side. Nothing is rejected, nothing is logged as an error, and the two systems now disagree. The difference usually surfaces only when a report, a customer, or an auditor forces someone to compare them.

An agreement check closes that gap on purpose. It's a scheduled job that compares the same fields across two systems and records every mismatch it finds, so a quiet disagreement becomes a visible item someone can act on. This post covers what the check needs before you build it, how it works, where to run it, and how often. Failure visibility is one of the five factors in InAir's Integration Load framework [DRAFTED, NOT LIVE: Cluster 2.0], and the check itself is one of the mechanisms described in InAir's guide to operating Airtable inside complex system landscapes [PILLAR 2].

 

What an Agreement Check Is (and What It Isn't)

 

An agreement check reads the values of selected fields from two systems, matches the records, compares the values and logs any differences. It doesn't change the values it compares.

 

The "not an automatic fix" point matters. A job that overwrites one value with the other whenever they differ is just another sync, and it can spread a wrong value as easily as it corrects one. The check's job is to make the disagreement visible. Deciding which value is right belongs to the ownership rules.

 

Three Things You Need Before You Build It

 

1. A stable ID that both systems share. The check has to know which Airtable record corresponds to which CRM record. Matching on a name or an email fails as soon as one side formats it differently, and the check ends up comparing the wrong pairs or reporting records as missing when they aren't. Why matching on an immutable ID matters is covered in why your integrations create duplicates [DRAFTED, NOT LIVE: Cluster 1.1.3].

2. A named authoritative system for each field you compare. The check can tell you two values differ. It can't tell you which one is correct. That answer comes from a written ownership rule, as described in Cross-System Source of Truth: who owns a field when Airtable isn't the only system writing to it [DRAFTED, NOT LIVE: Cluster 1.1.2]. Without one, every mismatch turns into a debate.

3. A short list of fields worth comparing. Start with shared fields where a disagreement causes real harm: contact details, billing information, status fields that drive downstream work. Comparing every field on every record costs more capacity and produces a longer list of exceptions to review, much of which may not matter.

 

How the Check Works

 

A basic agreement check runs through six steps.

  1. Read the selected fields from the authoritative system, using its API.
  2. Read the same fields from Airtable. How this works depends on where the check runs. A check running inside Airtable reads records through the scripting API, covered below. A check running as an external job uses Airtable's Web API, which returns up to 100 records per request when listing records, with an offset for fetching the next page. Reading 5,000 records that way takes 50 requests. Reading 5,000 records that way takes 50 requests. The check isn't time-sensitive, so the script can request those pages one at a time with a short pause between them, which keeps it under Airtable's limit of 5 requests per second per base [EXT], a limit it shares with every other system calling that base.
  3. Match records by the shared stable ID. A record that should exist in both systems but appears in only one is worth logging. If the sync covers only some records, such as active customers, apply the same filter to both sides before matching, so out-of-scope records aren't flagged as missing.
  4. Normalize values before comparing them. Many mismatches are formatting, not real disagreement: "+1 555-010-0100" and "(555) 010-0100" can be the same phone number, and a trailing space or a difference in letter case can make identical text look different. Normalizing both sides to the same format first keeps the exception list to real differences.
  5. Skip records that changed very recently. If a record was edited moments before the check runs, the sync may simply not have caught up yet. Comparing only records whose last change is older than the relevant sync interval avoids flagging changes that are still in transit. Another option is to flag a mismatch only if it appears on two runs in a row.
  6. Log every mismatch without changing either value. Before adding a row to the exceptions table, the check looks for an Open or Accepted exception on the same record, field, and external system. If an Open one exists, it updates that row's Last Seen and the two values. If an Accepted one exists and the values haven't changed, it updates only Last Seen. If the values have changed, it sets the row back to Open. If no matching row exists, it creates one.

 

The Exceptions Table

 

The exceptions table is where the check's output lives, and where someone resolves it. A workable structure:

 



Two design choices make the table usable.

  • Update, don't duplicate. If the same record and field are already open, the check updates Last Seen instead of creating a new row. A mismatch that persists for a week then shows as one row that's a week old, not seven rows.
  • Route it to an owner. A filtered view of open exceptions, assigned to a role, means someone is expected to work through it. How to get that view in front of the right person is covered in alert ownership [DRAFTED, NOT LIVE: Cluster 2.2.1].

 

Where to Run It

 

Inside Airtable. An automation with the At scheduled time trigger [EXT] can run the check as often as every 15 minutes, or hourly, daily, or weekly. A Run a script action can read the Airtable table, call the other system's API with fetch() and write exceptions.

Airtable's Run a script action limits each run to 120 seconds (a temporary increase from 30 seconds, according to Airtable), 50 fetch requests and 30 record queries, and each fetch times out after 30 seconds.

For an agreement check, two of these limits set the ceiling. The script reads the Airtable side through record queries, which don't count as fetches, but every page it reads from the other system uses one fetch. If that system returns 100 records per page, one run can read at most 5,000 records from it, and fewer if the script also uses fetches for other work. The 120-second limit can stop the run first: if each page takes more than about 2.4 seconds to return, the script times out before it uses all 50 fetches.

Outside Airtable. For larger volumes, the check can run as a scheduled job in middleware or a serverless function, reading both systems through their APIs and writing exceptions back to Airtable. InAir's guide to offloading resource-intensive workloads [LIVE] covers when and how to move work beyond Airtable's native script limits.

 

How Often to Run It

 

A nightly run is a common starting point. The trade-off is how long a disagreement can exist before anyone sees it, weighed against the capacity each run uses.

For a check running as an external job, the 5,000-record example makes about 50 requests to read Airtable on each run. Nightly, that's around 1,500 a month. Hourly, it's about 36,000 a month. On Team plans, Airtable caps API usage at 100,000 calls per workspace per month, and every other integration using Airtable's API in that workspace draws from the same allowance. Business and Enterprise Scale plans have no monthly cap. The other system's own API limits apply too.

The right interval depends on how long a wrong value can sit before it causes harm, the same tolerance question covered in why update frequency changes your integration risk [DRAFTED, NOT LIVE: Cluster 2.1.2]. Fields with a short tolerance can run on a tighter schedule than the rest.

 

What It Doesn't Replace

 

An agreement check is a detection layer. It finds disagreements that ownership rules and validation didn't prevent. It doesn't remove the need for either. A landscape with clear field ownership should produce fewer exceptions, and the ones it does produce will be quicker to resolve, because the ownership rule already says which value should win.

The same check also works between Airtable bases, wherever records are copied by automations, scripts or two-way sync rather than read-only sync, since those copies can drift the same way. InAir's approach to multi-base environments in Building a Single Source of Truth Across Multiple Airtable Bases keeps write access for core records in one authoritative base, which reduces how many copies there are to check.

 

Make Disagreement Visible on Purpose

 

Two systems can disagree for months without producing a single error. An agreement check doesn't stop that from happening, but it puts a limit on how long it can go undetected: the time between two runs. With a shared ID, a named owner for each field and an exceptions table someone actually works through, quiet drift becomes a list of dated items instead of a surprise in next quarter's report.

If you want to find where the systems in your landscape have already drifted apart, and build a check that catches it from here on, that's the work InAir does. Schedule a Discovery Call with InAir to find out what your integrations are actually carrying.