If you’ve ever built a Microsoft 365 migration script, chances are you started with delegated authentication.
I did too.
It’s quick to set up, easy to debug, and works fine for a handful of users. The problem is that delegated auth has a habit of failing only after you trust it — usually halfway through a long-running migration.
This post isn’t about what Microsoft recommends. It’s about what breaks in real tenant-to-tenant migrations and why app-only auth eventually becomes unavoidable.
Why Delegated Auth Feels Like the Right Choice (At First)
Delegated auth is appealing because it feels familiar:
- Sign in as admin
- Consent permissions
- Run the script
- Watch data move
For POCs and demos, it works surprisingly well. That’s why so many migration scripts online are built this way.
The trouble starts when:
- Jobs run for hours
- You add concurrency
- You migrate more than a few dozen users
That’s when delegated auth shows its real limitations.
The First Failure Is Usually Silent
The first time delegated auth fails, it often doesn’t throw a clean error.
Instead, you’ll see things like:
- Requests suddenly returning 401
- Token refresh loops
- Background jobs stopping without obvious logs
What actually happened?
- The session expired
- MFA kicked in
- The refresh token became invalid
- The user context was no longer trusted
None of these are easy to diagnose mid-migration.
User-Based Throttling Is a Hidden Problem
Delegated auth ties every request to a user identity.
That means:
You hit user-based throttling faster
Parallelism collapses under load
Retry storms become more likely
In one migration, we increased concurrency to speed things up and actually made it slower. Requests started backing off constantly because everything was bound to a single admin user.
At that point, no amount of retry logic helps.
Background Jobs and Delegated Auth Don’t Mix
Tenant migrations are not interactive tasks.
They:
Run overnight
Span days
Resume after failures
Require retries long after the original process started
Delegated auth assumes there’s a user session somewhere behind the scenes.
App-only auth doesn’t.
This difference alone is enough to rule out delegated auth for serious migrations.
App-Only Auth Is Boring — and That’s a Good Thing
Once you switch to app-only authentication, something interesting happens: things get boring.
- No pop-ups.
- No session expiry.
- No MFA surprises.
You get:
- Stable tokens
- Predictable throttling behavior
- Clean separation between identity and execution It’s not flashy, but it’s reliable — which is exactly what migrations need.
Permissions Are Scarier, but More Honest
One valid concern with app-only auth is permission scope. Granting tenant-wide permissions feels dangerous, and it should.
But here’s the uncomfortable truth:
If you’re migrating tenant data at scale, you already need broad access.
Delegated auth doesn’t make that safer — it just hides it behind a user account.
With app-only auth:
- Permissions are explicit
- Access is auditable
- Rotation is easier
- Responsibility is clearer
That’s a better security posture, not a worse one.
Retry Logic Behaves Differently (and Better)
This was an unexpected benefit.
With delegated auth, retries often fail for reasons unrelated to load:
- Token refresh failures
- Session invalidation
- Conditional access policies
With app-only auth, retries usually fail for real reasons:
- Throttling
- Temporary service issues
- That makes retry logic simpler and more predictable.
- When Delegated Auth Is Still Okay
Delegated auth isn’t useless. It’s fine for:
- One-off admin tasks
- Small migrations
- Validation scripts
- Exploratory tooling
The mistake is assuming it will scale just because it worked once.
The Rule I Follow Now
My rule of thumb is simple:
If the process needs to survive a restart, it should not depend on a user session.
Tenant-to-tenant migration definitely falls into that category.
Final Thoughts
Most migration failures don’t come from bad code.
They come from wrong assumptions.
Delegated auth assumes:
- Short execution
- Stable sessions
- Low concurrency
Tenant migrations assume none of those things.
If you’re serious about migrating Microsoft 365 tenants at scale, app-only authentication isn’t an optimization — it’s a prerequisite that is also used in CloudBik.
Top comments (0)