Here is a number from our own warehouse. A collection phase that took roughly 63 minutes on its first full run against a real tenant completed in about 26 seconds on the next run of the same phase. Same tenant, same code, same content. The only difference was a stored delta token. That is not an optimization — it is a different order of magnitude, and it is the single most important economic fact about scanning Microsoft Graph.
If a governance tool re-enumerates your entire estate every night, it is throwing that fact away. It is paying full price for a scan that should cost about one percent of the first.
What a delta query actually does
A delta query — Microsoft’s term is change tracking — lets an application “discover newly created, updated, or deleted entities without performing a full read of the target resource with every request” (delta query overview). The mechanics are simple and worth understanding, because the discipline lives in the details.
You call delta on a resource with no token. Graph starts enumerating and returns pages. Each page carries either an @odata.nextLink (more of the current state to page through) or, on the final page, an @odata.deltaLink. That deltaLink contains an opaque $deltatoken that encodes a snapshot of the resource at that moment. You persist it.
Next run, you call the deltaLink instead of starting fresh. Now Graph returns only what changed since the token — new items, modified items, and deletions (flagged with a deleted facet for driveItems, so you remove them from your local store). You get a new deltaLink at the end. Repeat forever. For driveItems in a SharePoint or OneDrive drive, this is the documented, supported way to track a drive and its children over time.
The first scan reads everything because it must. Every scan after that reads a diff.
Why scan #2 is cheap
The cost of a full scan is dominated by volume — every drive, every item, every permission read, all subject to SharePoint’s resource-unit throttling and the wall-clock cost of paging through hundreds of thousands of items. A delta run re-enumerates only the drives and items that actually changed since your token. In a steady-state tenant that is a rounding error against the total.
Two things compound the win:
- It dodges throttling. Microsoft is explicit that delta query “reduces the amount of data it requests… likely limit[ing] the chances of the requests being throttled” (delta query overview). Fewer requests against SharePoint’s rate limits means fewer 429s, less backoff, and no contention with the customer’s other tooling sharing the same tenant budget. The cheap scan is also the polite one.
- It is fresher. A diff you can run in seconds can run often. A full scan you can only afford nightly means your data is up to twenty-four hours stale by design. Incremental sync buys freshness and cost at the same time.
The discipline: tokens are state, and tokens expire
The delta token is not a cache you can rebuild on a whim. It is your sync state, and losing it means paying for a full scan again. So:
Persist tokens durably, per resource. One token per drive, written transactionally with the data it represents. If your process dies mid-run, you must be able to resume from the last good token, not restart from zero.
Handle expiry and reset gracefully. Tokens do not live forever. Directory-object tokens are valid for seven days; an expired token comes back as a 40x-series error. Worse, Graph can return a 410 Gone at any time — a synchronization reset triggered by internal maintenance or migration — which forces a full re-enumeration. For driveItems the 410 arrives with a resyncChangesApplyDifferences or resyncChangesUploadDifferences instruction and a fresh nextLink (driveItem: delta). A tool that treats these as crashes instead of expected states will either fall over or silently stop updating. Full resync must be a routine, tested path — not an incident.
Microsoft’s own best practices for detecting changes at scale say the same thing: use delta for the initial enumeration and the deltaLink thereafter, because paging children collections isn’t guaranteed to catch writes that land mid-scan. Delta is not just cheaper — for a correct picture at scale it is the only supported way.
Why “re-scan everything nightly” is the wrong architecture
It fails on all three axes that matter. It is expensive — you pay full enumeration and permission-read cost every single night. It is throttle-prone — full scans are exactly what triggers SharePoint’s per-app and tenant-wide limits, and a vendor hammering those limits can get the customer a Message Center abuse notice. And it is no fresher for the cost, because a scan you can only afford once a day is a day stale by construction.
The right shape is: one honest, expensive baseline, then cheap incremental syncs forever after, with delta tokens protected like the state they are. The first scan is the hard problem. Steady state should be nearly free — roughly 63 minutes down to 26 seconds for the same work. If your governance tool isn’t built that way, you are paying for its architecture on every bill and in every 429.
Polaris Governance Hub runs inside your own Microsoft 365 tenant and syncs incrementally by design — full baseline once, delta thereafter, tokens persisted and resync handled as a routine path. We’re taking a small number of design partners. See what Copilot can reach in your estate.