Stakeholder Management: Bringing a Resistant Lead Developer Along
The hardest part of a major platform migration wasn't the architecture — it was the person who'd built what we were replacing. Rather than working around the lead developer's resistance, we made them the driver of the migration: ownership of the strategy, guardrails that protected quality without threatening autonomy, and a 90-day challenge with measurable milestones. The technical migration succeeded because the people strategy came first.
4–6 min read
Key Takeaways
- Resistance is usually ownership in disguise
- Guardrails protect both the project and the person
- Make the expertise irreplaceable to the migration, not to the legacy system
Context
We were planning a significant platform migration — retiring a legacy embedded component and decomposing a monolithic worker service into .NET 8 microservices. The technical strategy was sound: adapter patterns, dual-run validation, Strangler Fig extraction. On paper, it was a well-sequenced modernization effort.
The complication was human. The lead developer on the team had deep ownership over the component being replaced. They'd built it, maintained it, and understood its behavior better than anyone. They were also the person most likely to resist the migration — not because they didn't understand the technical case, but because the migration implicitly said "the thing you built needs to be replaced."
That's a legitimate emotional response, and ignoring it would have been the fastest way to sabotage the project. A lead developer who passively resists — who finds edge cases that "prove" the new system isn't ready, who deprioritizes migration work in favor of firefighting, who becomes a bottleneck on every decision — can stall a migration indefinitely without ever saying no.
I'd seen this pattern before. The solution wasn't to work around the resistance. It was to make the resistant person the driver.
The challenge
The migration had real technical risk. The embedded component handled parsing, rendering, and configuration across multiple workflows. A mismatch in the replacement would surface as silent data corruption — the kind of failure you don't catch until a customer reports it. The lead developer's deep knowledge of edge cases and undocumented behavior was genuinely valuable. Sidelining them would have been both disrespectful and strategically stupid.
But leaving the migration in their hands without structure would have been equally risky. Without guardrails, the project could expand indefinitely — "just one more edge case," "not ready yet," "we need more testing" — all technically reasonable objections that conveniently prevent the migration from ever completing.
The challenge was designing an ownership model that channeled the lead developer's expertise and pride into driving the migration forward, while preventing that same ownership from becoming a veto on progress.
What I did
Framed the migration as a challenge, not a replacement. The language mattered. This wasn't "we're replacing your component." It was "this is the hardest technical migration on the roadmap, and you're the only person who can lead it." That reframe was genuine — the lead developer's knowledge of the existing system's edge cases was irreplaceable. The migration would be faster and safer with them driving it than with anyone else.
Gave them real ownership of the strategy. They chose the porting approach. They designed the test harness. They approved compatibility changes. They mentored others on the component's behavior. This wasn't delegated busywork — it was genuine technical authority over how the migration would execute. When someone controls the strategy, they have skin in its success rather than incentive to prove it was premature.
Built guardrails that protected quality without micromanaging. Four rules defined the engagement. No big-bang rewrites — adapter or sidecar first, native rewrite later. Dual-run validation with automatic fallback — the new system runs alongside the old, and any mismatch triggers a safe rollback. A change freeze on new features, gated by RFCs, to prevent scope creep disguised as improvement. And a 90-day timebox that created urgency without pressure — a challenge with a finish line.
Structured the work as a 30/60/90 with measurable milestones. At 30 days: adapter built, golden-master test harness running, canary deployment with fallback, 95% fixture parity. At 60 days: extended coverage, dual-run validation in staging, draft documentation, two weeks of clean dual-run data. At 90 days: production cutover, begin native optimization, documentation and training complete with two trained deputies.
Made the work visible. The lead developer's contribution to the migration was surfaced in sprint reviews, credited in release communications, and linked to their performance goals. Not as a formal incentive program — just as the natural consequence of doing important, difficult work. When the organization sees the migration as a technical achievement rather than a maintenance chore, the person driving it is recognized by default.
Addressed the bus factor without threatening their importance. The lead developer's deep knowledge was an asset, but it was also a single point of failure. Pairing sessions, trained deputies, and mandatory documentation were built into the 90-day plan — framed as "your expertise is too valuable to exist in one person's head," not as reducing dependency. Same outcome, opposite emotional response.
Why this worked
The conventional approach to a resistant stakeholder is to either escalate past them or route around them. Both fail here. Escalating turns the lead developer into an adversary with deep institutional knowledge and every incentive to prove the migration was a mistake. Routing around them loses the very expertise that makes the migration safe.
The approach that worked was making resistance unnecessary. When the lead developer drives the migration, controls the strategy, and has guardrails that protect them from being blamed for regressions — there's nothing left to resist. Their expertise becomes the engine of the migration instead of the brake.
The dual-run fallback was particularly important. It removed the fear of failure. If the new system produced a different result, the old system caught it automatically. The lead developer wasn't betting their reputation on a clean cutover — they were running an experiment with a safety net. That psychological shift — from "defending the old system" to "proving the new one" — changed the dynamic entirely.
Takeaways
1
Resistance is usually ownership in disguise. When someone pushes back on replacing something they built, they're telling you they care about quality and they're afraid of losing control. Channel that energy instead of fighting it — make them the owner of the replacement.
2
Guardrails protect both the project and the person. Dual-run fallbacks, RFC gates, and timeboxes aren't constraints on the lead developer — they're protection. Protection from scope creep, from blame if something goes wrong, and from the migration dragging on indefinitely. Good guardrails make autonomy safe.
3
Make the expertise irreplaceable to the migration, not to the legacy system. The lead developer's value shouldn't be "only person who understands the old thing." It should be "only person who can safely build the new thing." That shift turns preservation instinct into forward momentum.
4
Address the bus factor as investment, not insurance. Framing documentation and deputy training as "your expertise is too valuable to live in one person's head" lands differently than "we need to reduce our dependency on you." Same outcome, opposite emotional response.
Related
Why I Don't Do Technical Interviews for Senior Engineers
By the time someone has a decade of experience on their resume, I already know they can code — and write correct code at that. What I don't know, and what actually determines whether they'll thrive on my team, is whether they're curious, passionate, and wired to build great things. That's what the interview is for.
Read more ArchitectureTaming 50 Million Callbacks with Event-Driven Architecture
A legacy .NET HttpHandler buried inside the customer portal was processing webhook callbacks synchronously — and at 20M+ messages a month, vendor retry storms inflated that to 75 million callbacks with 90-second processing latency. We replaced it with an Azure Function that acknowledges in milliseconds and routes to channel-isolated processors via Service Bus, dropping latency to sub-second and eliminating the retry cascade entirely.
Read more