Browse all topics

Microsoft Graph delta queries

Delta queries return only what has changed since your last fetch — efficient incremental sync against Microsoft 365.

Microsoft Graph delta queries return only what has changed since your last fetch — incremental sync, in other words. They're the right pattern for any integration that needs to keep an external system in step with Microsoft 365 data, without re-fetching everything every time.

How delta works

The pattern:

  1. Initial call to a delta-supporting endpoint:

    GET https://graph.microsoft.com/v1.0/users/delta
    

    Returns the full set of users (paged). The final page includes a @odata.deltaLink — an opaque URL representing the current state.

  2. Subsequent calls use the delta link:

    GET {the-delta-link-from-last-call}
    

    Returns only the users that have changed since the last delta call — created, updated, or marked as deleted. The response again ends with a new @odata.deltaLink for the next round.

You store the delta link between calls. Each delta call is fast (only changes), and the result represents authoritative state.

What delta covers

Delta queries are supported for many Graph resources:

  • Users — profile changes, sign-in attribute changes, creation, deletion.
  • Groups — including membership changes (/groups/delta).
  • Group members/groups/{id}/members/delta.
  • Calendar events/users/{id}/calendarView/delta.
  • Drive items — file and folder changes in a SharePoint library or OneDrive.
  • Messages — mail message changes in a folder.
  • Devices — Intune-managed device state.
  • Directory roles.
  • Applications and service principals.

Each supports the same pattern: initial fetch produces a delta link; subsequent calls return only changes.

Why this matters

Without delta queries, the alternatives for sync are:

  • Re-fetch everything periodically — wasteful at scale; what's the right interval?
  • Use change notifications (webhooks) — event-driven, near real-time, but doesn't provide initial state and harder to recover from missed events.

Delta queries combine the best of both: efficient initial state, efficient incremental updates, deterministic catch-up after gaps.

A worked example

A custom HR data warehouse syncs Microsoft 365 users every 15 minutes:

# Initial run
fetch /users/delta → returns 50,000 users + deltaLink-1
store users in warehouse
save deltaLink-1

# 15 minutes later
fetch deltaLink-1 → returns 12 users (3 created, 7 updated, 2 deleted) + deltaLink-2
apply changes to warehouse
save deltaLink-2

# 15 minutes later
fetch deltaLink-2 → returns 4 users + deltaLink-3
apply changes
save deltaLink-3

Compared to re-fetching 50,000 users every 15 minutes, this is dramatically more efficient — Microsoft is happier (no throttling), your warehouse is happier (less write volume), and your bandwidth bill is lower.

Combining with change notifications

For the lowest-latency integration, combine change notifications (webhooks) for real-time signals with delta queries for catch-up and reconciliation:

  • Webhooks fire on each change → process immediately.
  • Periodic delta query → catch anything the webhook missed (network blips, app downtime) and reconcile.

This pattern is robust: webhooks for speed, delta for correctness.

Limitations

  • Delta tokens expire after a few weeks of disuse. If your app is offline for too long, you'll get a 410 Gone and need to start over with a full sync.
  • Tracked properties — delta returns only changes to properties that are tracked. Some less-common attributes don't trigger delta updates.
  • Deletes are marked — deleted resources appear in delta responses with @removed annotations rather than disappearing silently.

When delta is the right tool

Any integration that:

  • Needs to keep external state in step with Microsoft 365.
  • Has periodic sync schedules (every N minutes / hours).
  • Wants to minimise API calls at scale.
  • Needs deterministic reconciliation after outages.

For ad-hoc one-off reads, regular Graph calls are simpler. For ongoing sync, delta is the way.