Skip to main content

Reliability, limits, and sync-health alerts

The Airtable integration is built to keep syncing safely inside Airtable's published limits, to recover on its own from transient failures, and to tell you when something needs attention. This page explains the guardrails that protect your Airtable quota and your data, and the three sync-health alerts that surface when a run can't complete cleanly.

For the record-by-record mechanics those guardrails wrap around, see How Airtable sync works. To watch runs and clear alerts in the UI, see Monitor your Airtable syncs.

Limits at a glance

LimitValueNotes
Monthly API cap100,000 callsPer connection, per calendar month. Override it per connection under the Settings tab.
Near-cap warning80% of capDashboard warning; syncing continues.
Over-cap pause100% of capOutbound sync pauses until the counter resets.
Airtable per-base rate limit5 requests/secondAirtable's published ceiling, per base.
SKU.io self-cap~4 requests/secondPer base, to leave headroom under Airtable's limit.
429 back-off30 secondsAirtable's requested back-off before a single retry.
Outbound batch size10 recordsAirtable's hard write limit per batch.
Reported errors per run10Captured for the run summary; the rest are counted only.
Overlap lock-retry window15 minutesA blocked run retries within this window, then defers.
Token-refresh buffer2 minutesA token is refreshed this far ahead of expiry.
Webhook expiry~7 daysAirtable OAuth webhooks; SKU.io re-arms them before they lapse.

The rest of this page explains the "why" behind each of these numbers.

Monthly API-cap governance

Airtable meters API calls per month against your plan (the Team plan default is 100,000 calls). Rather than burn through that quota and start getting throttled by Airtable, SKU.io counts every call it makes and governs its own outbound sync against a monthly cap.

The cap defaults to 100,000 calls per connection per month, and you can override it per connection under the Airtable Settings tab. Usage is counted per connected account, in a rolling counter keyed to the connection and the calendar month, so each connection has its own independent budget that rolls over automatically at the month boundary.

Two thresholds matter:

UsageWhat happens
80% of cap (near cap)The Dashboard shows a warning — "Approaching your monthly Airtable API limit — consider reducing sync frequency or disabling real-time." Syncing continues normally. This is a heads-up, not a pause.
100% of cap (over cap)Outbound sync pauses. Both scheduled runs and real-time pushes stop making calls until the counter resets. The Dashboard shows "Monthly Airtable API limit reached — outbound sync is paused until it resets," and an admin alert is raised.

The Dashboard shows your live position as used / cap (percent%) with a progress bar that turns amber near the cap and red once it's reached.

The cap is enforced defensively, not once per run. A scheduled run checks the counter before it starts, and re-checks it before every fetch chunk it pulls, so a large backfill can't blow far past 100% between checks. When the cap is hit part-way through a run, the chunk loop stops immediately and the sync does not advance its watermark — the records it didn't reach stay in the delta and retry on the next run once the counter has room again. Real-time single-record pushes respect the same cap: once you're over, a real-time push is skipped rather than consuming quota you don't have.

Per-base rate limiting and 429 back-off

Airtable enforces 5 requests per second per base. SKU.io caps itself at roughly 4 requests per second per base to leave headroom, using a token bucket shared through Redis. The bucket is keyed on the Airtable base, not on the job or the tenant, so every scheduled run and real-time push touching the same base cooperates under one ceiling — concurrent workers can't collectively exceed it.

When the bucket is momentarily full, a worker waits in short 250ms increments (up to about 10 seconds) for a slot to free up, rather than erroring out. This brief back-pressure is normal and invisible in the UI.

The same base-keyed limiter and 429 back-off govern writes made from an automation, so an Airtable: Write Rows node cooperates under the same ceiling as your scheduled runs and real-time pushes. See Write to Airtable from an automation.

If Airtable still returns a 429 Too Many Requests, the connector raises a rate-limit error carrying Airtable's required back-off (30 seconds by default). The batch then sleeps for that back-off, re-acquires a slot from the limiter, and retries once. If the single retry still fails, the batch falls back to per-record isolation (below) so a persistent problem is narrowed to the specific rows that caused it rather than failing the whole batch.

Per-record error isolation

Outbound writes go to Airtable in batches of up to 10 records (Airtable's hard write limit). If a batch write throws, SKU.io does not fail the whole batch — it retries the batch one record at a time, so a single malformed row can't take its nine well-formed neighbors down with it.

Rows that succeed in isolation are written normally. A row that still fails on its own is counted as failed and its error message is captured for the run summary, up to a maximum of 10 reported errors (enough to diagnose without flooding the log). You'll see these in the run's completion summary in the Activity tab.

Failures also hold the line on data safety. Whenever a run finishes with any failed rows, SKU.io does not advance the sync watermark — the cursor stays put so the failed rows are re-attempted on the next run instead of being skipped over. The connection's error count is incremented, and a sync-failed alert is raised. A subsequent fully clean run resets the error count and advances the watermark normally.

Overlap protection on concurrent runs

A dataset can be triggered two ways at once — a scheduled run firing while you click Sync now, for example. To stop both from writing the same records simultaneously, each dataset mapping takes a per-mapping lock for the duration of its run.

If a second run can't get the lock because one is already in progress, it doesn't fail and it doesn't double-write. It releases itself and retries a couple of minutes later, bounded to a 15-minute retry window. This is safe because the sync is delta and cursor-based — re-running it produces the same result, so a deferred run picks up whatever is left when the lock clears.

Automatic access-token refresh

Airtable access tokens are short-lived, and Airtable rotates the refresh token every time it's used. SKU.io refreshes an expired (or nearly expired) token transparently before each API call, so you never have to reconnect for routine expiry.

Because the refresh token rotates, two workers refreshing at the same time would invalidate each other's tokens and force a reconnect. To prevent that, refreshes are serialized behind a per-connection lock: only one worker refreshes at a time, and any worker that was waiting re-reads the freshly stored token instead of refreshing again. A token is refreshed slightly ahead of its true expiry (a two-minute buffer) so an in-flight request never races the clock.

Two edge cases surface rather than fail silently:

  • If Airtable returns an empty token on refresh, SKU.io raises an error — the connection effectively needs to be reconnected from the Settings tab. See Connect Airtable to re-authorize.
  • If a worker waits too long for the refresh lock, its request throws instead of risking a second concurrent refresh. It's retried on the next run.

Sync-health alerts

When a condition needs your attention, the Airtable integration raises an admin alert through SKU.io's shared alert framework — the same alerts surface used across integrations. There are three Airtable alert types, and each one is designed to be self-clearing: a raise and its matching resolve share a single dedup key, so a persistent condition stays one occurrence-counted alert (not a flood of duplicates) and disappears on its own the moment the next healthy run happens.

AlertPriorityRaised whenAuto-resolves when
Airtable Sync FailedHighA dataset run finishes with failed rows, or the job errors outright.A later run for the same dataset completes cleanly.
Airtable Monthly API Cap ReachedHighA connection hits 100% of its monthly API cap and outbound sync is paused.Usage falls back under the cap — typically at the monthly reset.
Airtable Webhook LapsedNormalAn inbound webhook can no longer be polled (expired, deleted, or a stale cursor).The webhook re-registers and a poll succeeds.

Each alert links straight to the relevant screen — a sync-failed alert to the connection's Activity tab, an API-cap alert to the Dashboard, and a webhook-lapsed alert to the Datasets tab.

What the webhook-lapsed alert means

Airtable's OAuth webhooks expire after about seven days. SKU.io re-arms them automatically before they lapse, but if one does lapse (or is deleted on Airtable's side), inbound review doesn't stop — it falls back to a scheduled full-table scan until the webhook re-registers. The alert tells you real-time inbound is temporarily running on the slower fallback path, not that inbound has broken. Inbound proposals keep flowing to the review queue throughout. For how inbound changes are gated and applied, see Review inbound changes and Inbound safety.

Alerting never breaks a sync

Every alert call is guarded. If raising or resolving an alert itself fails for any reason, SKU.io logs a warning and carries on — a hiccup in the alerting layer can never interrupt an in-progress sync. Alert notifications route to the alert type's default audience (your admins) plus anyone subscribed to that type. All three Airtable alert types are tagged back to the Airtable integration, so you can filter for them alongside your other Airtable alerts.

Each connection is isolated

If you run more than one Airtable connection, or the same connection has several dataset mappings, their reliability state is tracked independently so a problem on one never bleeds into another:

  • API usage is counted per connection (per connected account, per month), and the per-connection cap override applies only to that connection. One connection hitting its cap doesn't pause another.
  • Record links, cursors, webhook tokens, and delete/apply behavior are tracked per dataset mapping. A lapsed webhook on one dataset doesn't affect another dataset's syncs. A webhook token is registered once per connection and reused across that connection's mappings.
  • The rate limiter is the one thing deliberately shared — but only per Airtable base — so concurrent mappings pointed at the same base cooperate under one ceiling instead of competing.

Next steps

Last verified: