Concepts

The sync model

How the warehouse stays fresh — nightly full pulls, 6-hourly incrementals, and no webhooks.

Google Ads has no webhooks, so freshness comes from scheduled pulls. A background worker keeps a normalized copy of every account in the gads_* tables (all money in micros), and reads never hit the Google Ads API live.

Three sync modes

  • Backfill — 90 days of metrics, all dimensions, and 30 days of change history. Enqueued once, when you import an account.
  • Full — a nightly LAST_14_DAYS refresh plus all dimensions and change history since the last full run.
  • Incremental — dimensions, today's and yesterday's campaign metrics, and recent change history.

Scheduling

A cron runs every 6 hours and, for each active account, enqueues a full sync when the last one is stale (older than ~20 hours) or an incremental otherwise. It never clobbers an in-flight sync. A separate worker drains the queue every 5 minutes. Audits run on their own daily schedule.

Freshness is surfaced, not hidden

gads_get_sync_status reports the latest run, and strategic reads return a dataFreshness warning. When data is stale or history is thin, act on the warning first — trigger a sync and wait — rather than trusting the numbers.

In local development there's no cron. Trigger the worker manually, or use Trigger sync in the account / gads_trigger_sync over MCP. A sync that's already running is refused rather than duplicated.

On this page