DEV Community

Manoj Dwivedi
Manoj Dwivedi

Posted on

Delegated vs App-Only Auth in Microsoft 365 Migrations (Hard Lessons)

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:

  1. Sign in as admin
  2. Consent permissions
  3. Run the script
  4. 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:

  1. Jobs run for hours
  2. You add concurrency
  3. 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)