How Calendar Sync Actually Works: Webhooks, Polling & Dedup Explained

9 min read

Calendar sync works by detecting changes on one calendar and replicating them to another. The three core mechanisms are: (1) change detection — how the sync tool learns something changed, using either webhooks or polling; (2) incremental sync — how it fetches only what changed, using sync tokens; and (3) deduplication — how it prevents infinite loops when syncing bidirectionally, using metadata-based event IDs. The change detection method determines real-world sync speed. Webhook-based tools like SYNCDATE receive push notifications from the Google Calendar API and Microsoft Graph within seconds of a change, completing the full sync round-trip in ~4 seconds. Polling-based tools check on a fixed schedule — typically every 5 to 15 minutes — creating a propagation delay that can cause double-bookings when scheduling tools check stale availability data.

The Three Layers of Calendar Sync

Every calendar sync system — whether it is SYNCDATE, CalendarBridge, OneCal, or a DIY solution — needs to solve three problems:

  1. Detect that something changed on a calendar
  2. Fetch only the changes (not the entire calendar every time)
  3. Prevent loops and duplicates when syncing in both directions

The differences between sync tools come down to how they solve each problem. The approach to layer one (change detection) has the biggest impact on user experience, because it determines how fast events propagate between calendars.

How does calendar sync detect a change?

A calendar sync tool finds out something changed in one of two ways. It either asks the calendar on a timer (polling), or the calendar tells it the moment a change happens (webhooks). Webhooks are far faster: a change notification arrives in about 4 seconds, while polling tools wait until their next scheduled check.

The first problem any sync tool must solve is knowing when something changes. There are two fundamental approaches: polling and webhooks.

Webhook-driven change detection works like a doorbell, not a guard who keeps checking the door. Instead of asking the calendar "did anything change?" on a timer, the sync tool registers a webhook channel once. From then on, the calendar provider sends an HTTP POST the instant an event is created, edited, or deleted. SYNCDATE uses this model with the Google Calendar API and Microsoft Graph, completing the full sync round-trip in about 4 seconds. That speed matters most when another tool checks your availability. A polling tool that only looks every 15 minutes leaves a window where someone can book over a slot you just filled. Webhooks close that window, because your "busy" block lands on the other calendar almost immediately after you create it. Webhook channels do expire after a few days, so the tool quietly renews them in the background, and a 15-minute polling fallback catches any notification the network dropped. You never have to think about either one.

Polling (How Most Sync Tools Work)

Polling means the sync tool asks the calendar "has anything changed?" on a fixed schedule — every 5 minutes, 15 minutes, or 60 minutes.

How it works:

  1. Sync tool sets a timer (e.g., every 15 minutes)
  2. Timer fires — tool calls Google Calendar API: "give me changes since my last check"
  3. If changes exist — process them
  4. If no changes — do nothing, wait for next timer

Advantages: Simple to implement. Works with any calendar API that supports listing events. No special infrastructure or publicly accessible server required.

Disadvantages: Delay between event creation and sync. If you poll every 15 minutes, an event created at 2:01pm might not sync until 2:15pm. During that gap, scheduling tools show stale availability — which can lead to double bookings. Polling also wastes API quota on empty checks, which matters because Google Calendar API has rate limits that restrict how frequently you can query.

Who uses polling: CalendarBridge (~15 min), Reclaim.ai, OGCS (user-configured, typically 15-60 min).

Webhooks (Push Notifications)

Webhooks flip the model. Instead of the sync tool asking "has anything changed?", the calendar tells the sync tool when something changes. Google Calendar's push notification system is documented in the Google Calendar API Push Notifications guide.

How it works (Google Calendar webhooks):

  1. Sync tool registers a webhook channel with Google Calendar API (calls watch())
  2. Google stores the webhook URL and a channel token
  3. When any event changes on that calendar, Google sends an HTTP POST to the webhook URL
  4. Sync tool receives the notification — fetches the actual changes — processes them
  5. Channel expires after a set period (typically days) — tool renews it automatically

Advantages: Near-instant sync. Events propagate in seconds, not minutes. No wasted API calls when nothing changes. More efficient use of Google Calendar API quotas.

Disadvantages: More complex to implement. Requires a publicly accessible HTTPS endpoint to receive push notifications. Webhook channels expire and need renewal. Some calendar APIs do not support webhooks at all. Notifications can occasionally be missed due to network issues or Google infrastructure hiccups.

Who uses webhooks: SYNCDATE (~4 second total round-trip).

Hybrid: Webhooks + Polling Fallback

The most reliable approach combines both. Webhooks handle the fast path (instant notification), while a background polling job catches anything webhooks might have missed. Google's own documentation notes that push notifications are not guaranteed for every change, making a fallback mechanism essential for production systems.

SYNCDATE uses this hybrid model: webhooks for near-instant sync (~4 seconds), with a 15-minute polling fallback that picks up any missed changes. This ensures zero events are lost even during temporary webhook delivery failures.

To understand why some sync tools feel "delayed" while others feel instant, see Why Is My Calendar Sync Delayed?.

What is a sync token?

A sync token is a short code from the calendar API that marks your place in the calendar's change history, like a bookmark. The next time the sync tool asks for changes, it hands back the token and the calendar returns only what changed since then. This is called incremental sync, and it lets the tool fetch a handful of events instead of thousands.

Once the sync tool knows something changed, it needs to fetch what changed without re-downloading the entire calendar. This is where sync tokens come in.

Incremental sync is the difference between fetching a few events and fetching your whole calendar every time. A calendar with two years of history can hold 3,000 or more events. Without a sync token, the tool would re-download all 3,000 on every single change, burning API quota and slowing everything down. With a sync token, the calendar returns only the 1 to 5 events that actually changed since the last check. In practice this cuts API usage by 99% or more. Google's incremental sync documentation describes the mechanism, and the data builds on the iCalendar specification (RFC 5545). Microsoft Outlook uses the same idea under a different name, calling it a delta query that returns a deltaLink URL. Tokens do expire, and Google can invalidate one after weeks of inactivity, at which point a well-built tool quietly falls back to a full sync and grabs a fresh token. Every reliable sync tool relies on incremental sync, because full re-fetches simply do not scale.

The Problem with Full Sync

A Google Calendar with 2 years of events might have 3,000+ events. Re-fetching all 3,000 events every time one event changes is wasteful — it burns API quota, takes time, and creates unnecessary server load. For busy professionals, Reclaim.ai reports that the average knowledge worker's calendar contains hundreds of events per year, making full-calendar fetches prohibitively expensive at scale.

How Sync Tokens Work

Google Calendar API provides sync tokens — opaque strings that represent a point in time in the calendar's change history. Google's incremental sync documentation describes the mechanism in detail. The underlying data format builds on the iCalendar specification (RFC 5545), with Google adding their own extensions for change tracking.

First sync (no token):

  1. Sync tool calls events.list() with no sync token
  2. Google returns all events within the requested time range
  3. Google includes a nextSyncToken in the final page of results
  4. Sync tool stores this token

Subsequent syncs (with token):

  1. Sync tool calls events.list() with the stored nextSyncToken
  2. Google returns only events that changed since that token was issued
  3. Google includes a new nextSyncToken
  4. Sync tool processes only the changed events and stores the new token

This is called incremental sync. Instead of fetching 3,000 events, the tool fetches 1-5 changed events. Massively more efficient — often reducing API usage by 99% or more.

The sections below cover sync token edge cases and practical constraints.

Sync Token Gotchas

Sync tokens have practical constraints that sync tools must handle correctly. These are some of the known limitations of the Google Calendar API:

Pagination matters. Google only returns the nextSyncToken on the final page of results. If a calendar has more than 250 events (one page), the tool must paginate through all pages before it gets a usable sync token. Without proper pagination, the tool never gets a sync token and does a full sync every time — wasting quota and slowing down the process.

Tokens expire. Google can invalidate a sync token at any time (typically after weeks of inactivity). When this happens, the API returns a 410 Gone error. The sync tool must fall back to a full sync and obtain a new token. Well-built tools handle this transparently without user intervention.

No time filters with tokens. When using a sync token, you cannot pass timeMin or timeMax parameters. Google returns all changes regardless of date range. The sync tool must filter events at the application level (e.g., skipping events beyond the user's configured sync horizon).

Recurring events come as masters. Sync tokens require singleEvents=false, which means recurring events are returned as the master event with a recurrence rule (RRULE per RFC 5545), not as individual expanded instances. The sync tool must handle RRULE parsing and ensure recurring events sync correctly with timezone information intact.

Microsoft Graph API uses a similar concept called delta queries. Instead of a sync token, Outlook returns a deltaLink URL. Calling that URL returns only events changed since the link was generated. Same principle, different API naming. SYNCDATE fully supports Google Calendar, Microsoft Outlook/Office 365, iCloud, Fastmail, and Nextcloud — enabling cross-provider sync using each platform's native incremental sync mechanism. For the most common setup scenario, see our guide on syncing Google Workspace and personal Gmail.

What stops two-way sync from looping forever?

Two-way sync would copy events endlessly without a way to recognize its own copies. The fix is deduplication: every event the tool creates carries a hidden tag, so when that copy comes back around, the tool sees its own tag and skips it. No tag check means infinite duplicates.

Deduplication is the single feature that separates a working two-way sync from one that floods your calendar. When Calendar A syncs to Calendar B and B syncs back to A, each copy looks like a brand-new event unless the tool can tell its own work apart. SYNCDATE solves this by stamping every event it creates with one piece of metadata: a calendarSyncId tag in the form <user_id>:<original_source_event_id>. When a change comes in, the rule is one line of logic. If the event already carries a calendarSyncId for this user, skip it, because the tool created it. That single tag stops the A-to-B-to-A loop cold. It is also far more reliable than guessing by title or start time, which break the moment someone edits a title, moves an event across time zones, or sets up a recurring series. For more on this, see How to Stop Calendar Events from Duplicating.

The loop: Event created on A → synced to B → sync detects "new event on B" → syncs back to A → sync detects "new event on A" → syncs to B → forever.

Metadata-Based Dedup

The solution is to mark synced events so the system can identify its own copies.

How SYNCDATE does it:

Every event created by SYNCDATE includes a custom metadata property:

```

calendarSyncId: <user_id>:<original_source_event_id>

```

  • user_id identifies which user's sync created this event
  • original_source_event_id references the original event that started the chain

When processing changes, the rule is simple: if an event has a calendarSyncId that starts with the current user's ID, skip it — it is a copy the system already created.

This prevents the A-to-B-to-A loop because:

  1. User creates event "Dentist" on Calendar A
  2. SYNCDATE copies it to Calendar B with metadata calendarSyncId: user123:eventA_id
  3. Google sends a webhook notification about the new event on Calendar B
  4. SYNCDATE checks: does this event have calendarSyncId starting with user123? Yes — skip
  5. No loop. No duplicate.

This approach is far more reliable than name-based matching or time-based matching, which break down with recurring events, edited titles, or timezone differences.

Cross-Sync Dedup

A more subtle problem: what if a user has two different sync processes that overlap?

  • Sync 1: Calendar A ↔ Calendar B
  • Sync 2: Calendar A ↔ Calendar C
  • Both syncs copy an event from A to their targets. Then Sync 1 sees the event on B and tries to copy it to A (skip — dedup catches it). But what if there is also a Sync 3: B ↔ C? Sync 3 might try to copy the event from B to C, but it is already on C from Sync 2.

SYNCDATE handles this with transitive dedup: the calendarSyncId always references the original source event, not intermediate copies. Before creating an event on a target calendar, the system checks the synced_events database table to see if that original source event already exists on the target via any sync process. This prevents duplicates even in complex multi-calendar configurations.

Multi-User Dedup

Dedup is scoped per user. If user A syncs a calendar and stamps events with user_A:eventId, user B's sync sees that metadata but does not skip it (different user prefix). This means multiple users can independently sync the same shared calendars without interfering with each other — essential for teams where several members might each sync a shared team calendar to their own personal calendars.

Conflict Resolution

When two-way sync is active, the same event can be modified on both calendars simultaneously. How does the sync tool decide which version wins?

Last-write-wins (most common): Compare the updated timestamp on both versions. The most recent modification takes precedence. This is simple, deterministic, and handles 99% of real-world cases. Both SYNCDATE and CalendarBridge use this approach. The iCalendar specification (RFC 5545) defines the LAST-MODIFIED property that underpins this strategy.

Merge (rare): Some enterprise sync tools attempt to merge non-conflicting field changes (e.g., title changed on Calendar A + time changed on Calendar B — apply both). This is complex, error-prone, and generally not worth it for calendar sync where the same person typically edits the same event.

Privacy During Sync

An important aspect of how calendar sync works is what information gets copied. SYNCDATE syncs events as "Busy" blocks by default, meaning the target calendar shows that you are busy at that time without revealing event titles, descriptions, or attendees. This is critical for privacy in calendar sync — especially when syncing personal events to a work calendar. For teams distributed across the EU, our guide on calendar sync for European teams covers GDPR-specific considerations.

All OAuth tokens are encrypted with AES-256-GCM at rest, following Google's OAuth 2.0 security best practices. SYNCDATE is hosted on EU infrastructure (Hetzner, Germany), compliant with GDPR requirements, and never stores the content of your calendar events on its servers — it reads, transforms, and writes events in real time.

Putting It All Together

Here is the complete flow for a webhook-based, incremental, deduplicated calendar sync:

  1. User creates event "Team Standup" on Calendar A at 9am Monday
  2. Google sends webhook to SYNCDATE's server: "Calendar A changed"
  3. SYNCDATE fetches changes using stored sync token — gets the new "Team Standup" event
  4. Dedup check: Does "Team Standup" have a calendarSyncId for this user? No — it is an original event, proceed
  5. Exclusion rules: Check if event matches any user-defined rules (skip all-day events, skip events whose title contains a pattern). If matched, skip
  6. Privacy filter: Apply sync settings (e.g., copy as "Busy" block or with full details)
  7. Create on target: SYNCDATE creates a copy on Calendar B with metadata calendarSyncId: user123:standup_event_id
  8. Store mapping: SYNCDATE records the source-to-target event mapping in its database
  9. Google sends webhook about the new event on Calendar B
  10. SYNCDATE fetches changes — gets the event with calendarSyncId
  11. Dedup check: calendarSyncId starts with current user's ID — skip (it is our own copy)
  12. Done. Total time from step 1 to step 6: ~4 seconds.

If you're wondering whether Google offers this natively, the answer is no — see can you actually sync Google Calendars between accounts? for the full breakdown. This entire flow repeats for updates and deletions too. Move a meeting to a new time? The update propagates in ~4 seconds. Cancel a meeting? The deletion propagates in ~4 seconds.

SYNCDATE: Try Webhook-Driven Sync for Free

SYNCDATE's free tier includes everything described in this article:

  • Webhook-driven sync with ~4 second propagation (not polling)
  • Metadata-based deduplication preventing infinite loops and duplicate events
  • Incremental sync tokens for efficient API usage
  • 15-minute polling fallback ensuring zero missed changes
  • Exclusion rulesskip all-day events or filter by title so holidays, OOO markers, and other noise don't clutter your target calendar
  • Calendar viewsee all connected calendars on one screen in day, week, month, or agenda layout (no syncs required)
  • 2 calendars, 2 accounts — forever free, no credit card required

For larger setups, the Plus plan (€4.69/month, 20 calendars, 5 accounts) and Pro plan (€12.49/month, 100 calendars, 20 accounts with priority sync) cover most professional needs. Annual billing saves 17%. See the full pricing breakdown.

Frequently Asked Questions

How does calendar sync work technically?

Calendar sync detects changes on one calendar (via webhooks or polling), fetches only the changed events (using sync tokens for efficiency), checks if the change is an original event or a synced copy (deduplication), and replicates original changes to the target calendar. Two-way sync runs this process in both directions. The entire round-trip takes ~4 seconds with webhook-based systems like SYNCDATE.

What is a calendar sync token?

A sync token is an opaque string from the calendar API that represents a point in time in the calendar's change history. When you pass it to the API on subsequent requests, the API returns only events that changed since the token was issued — enabling incremental sync without re-fetching the entire calendar. See the sync token section above for more detail.

How does calendar sync prevent duplicate events?

Dedicated sync tools use metadata-based deduplication. Each synced event is stamped with a unique identifier (calendarSyncId) referencing the original source event. When the sync processes changes, it checks for this metadata and skips events it already created, preventing the infinite loop that would otherwise occur with two-way sync. For more detail, see How to Stop Calendar Events from Duplicating.

Why is some calendar sync real-time and some delayed?

It depends on the change detection method. Webhook-based sync (like SYNCDATE) receives push notifications from the calendar API within seconds. Polling-based sync (like CalendarBridge) checks for changes on a timer, typically every 5-15 minutes. The difference matters most when scheduling tools check your calendar for availability — stale data during the polling gap can cause double bookings. See the webhooks vs polling section above for a full comparison.

Is calendar sync secure?

Reputable sync tools use OAuth 2.0 for authentication, meaning they never see or store your Google password. SYNCDATE encrypts all OAuth tokens with AES-256-GCM at rest and is hosted on EU infrastructure (Hetzner, Germany). Events are read, transformed, and written in real time — SYNCDATE does not store event content on its servers.

Does calendar sync work with Outlook?

Yes. Microsoft Graph API supports a similar mechanism (delta queries instead of sync tokens, change notifications instead of webhooks). SYNCDATE fully supports Google Calendar, Microsoft Outlook/Office 365, iCloud, Fastmail, and Nextcloud, enabling cross-provider sync. For a full comparison of sync tools, see our free calendar sync tools comparison.

How long does it take to sync calendar events?

It depends on the sync method. Webhook-based tools like SYNCDATE sync in ~4 seconds: Google Calendar pushes a change notification within 1-5 seconds of an event update, and SYNCDATE processes and replicates it to the target calendar in the remaining time. Polling-based tools take 5-30 minutes depending on their check interval. The difference matters most when preventing double-bookings — a 15-minute delay means 15 minutes where another tool can schedule a meeting over your blocked time.

Is calendar sync instant?

Not quite instant, but close. Webhook-based sync like SYNCDATE propagates a change in about 4 seconds, because the calendar pushes a notification the moment something changes. Polling-based tools are not instant at all — they only check on a timer, so a change can wait 5 to 15 minutes before it syncs. A 15-minute polling fallback catches anything a webhook misses, so you get speed without losing changes. See why calendar sync gets delayed for the full picture.

Does calendar sync work two ways?

Yes. Two-way sync means a change on either calendar appears on the other. Add an event to your work calendar and it shows on personal; add one to personal and it shows on work. SYNCDATE supports two-way sync across Google Calendar, Microsoft Outlook/Office 365, iCloud, Fastmail, and Nextcloud. iCal feeds are one-way only, since the source is read-only. See one-way vs two-way calendar sync for when each makes sense.

Will synced events show up as duplicates?

No, not with a tool that deduplicates correctly. SYNCDATE stamps every event it creates with a hidden calendarSyncId tag. When that copy comes back through the sync, the tool recognizes its own tag and skips it, so the event is never created twice. This is what prevents the infinite loop that two-way sync would otherwise cause. If you have seen duplicates with another setup, see How to Stop Calendar Events from Duplicating.

How Calendar Sync Works: Webhooks, Polling & Dedup | SYNCDATE