LLM-Driven Developer Experience and Code Migrations at Scale

uber · Tech · 2023 · source Agentic: yes · promotional bias: low · source-backed · extracted with prompt 0.5.6 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: Developer productivity and code migration

Uber needed to improve developer experience and reduce technical debt across massive monorepos without simply adding headcount, while avoiding production risk from unreliable generated code.

Constraints:

Architecture

Uber's developer-platform strategy evolved into three tracks: build on GitHub Copilot rather than maintain a competing in-house code assistant, use agentic workflows such as AutoCover to generate and validate tests with developers in the loop, and accelerate Java-to-Kotlin migration by combining deterministic AST tooling with LLM-authored migration rules reviewed by platform engineers. A horizontal AI Developer Experience team works with monorepo experts, while ML infrastructure provides hosting, fine-tuning, and gateway capabilities.

Diagram confidence: reconstructed (reconstructed from prose).

flowchart LR
  AI_Developer_Experience_team["AI Developer Experience team"] --> Developer_IDE_surfaces["Developer IDE surfaces"]
  ML_infrastructure_team["ML infrastructure team"] --> AI_Developer_Experience_team
  Developer_IDE_surfaces --> GitHub_Copilot["GitHub Copilot"]
  GitHub_Copilot --> AutoCover["AutoCover"]
  AutoCover --> Build_and_test_runner["Build and test runner"]
  Build_and_test_runner --> AutoCover
  Java_to_Kotlin_migration_system["Java to Kotlin migration system"] --> Historical_migration_dataset["Historical migration dataset"]
  Historical_migration_dataset --> Rule_writing_agent["Rule-writing agent"]
  Rule_writing_agent --> CI_validation["CI validation"]
  CI_validation --> Rule_writing_agent
  Rule_writing_agent --> Platform_engineer_review["Platform engineer review"]
  Platform_engineer_review --> Java_to_Kotlin_migration_system
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
AI Developer Experience team Horizontal team of monorepo experts applying AI to developer workflows. ML infrastructure team, Developer IDE surfaces, AutoCover, Java to Kotlin migration system
ML infrastructure team Provides model hosting, fine-tuning, model gateway, and AI abstractions for developer tools. AI Developer Experience team, Fine-tuned backend models
Developer IDE surfaces Xcode, JetBrains IDEs, VS Code, and Copilot extension points where developers interact with AI tooling. GitHub Copilot, AutoCover, Java to Kotlin migration system
GitHub Copilot Vendor assistant Uber decided to build on top of rather than competing with directly. Developer IDE surfaces, AutoCover
AutoCover Agentic test-generation workflow that generates, builds, fixes, validates, and refactors tests with developers in the loop. Developer IDE surfaces, Build and test runner, LLM generation steps
Build and test runner Runs generated tests, surfaces failures, and drives iterative LLM repair. AutoCover, LLM generation steps
Java to Kotlin migration system Deterministic AST-based migration pipeline around IntelliJ conversion, pre/post processors, CI, code review, and LLM-authored rules. Historical migration dataset, Rule-writing agent, CI validation, Platform engineer review
Historical migration dataset Thousands of prior migrations and deltas used to discover missing migration rules. Rule-writing agent, Java to Kotlin migration system
Rule-writing agent Agentic LLM loop that drafts AST rules, responds to CI failures, and produces candidates for review. Historical migration dataset, CI validation, Platform engineer review
Platform engineer review Human approval stage before generated rules land as deterministic migration tooling. Rule-writing agent, Java to Kotlin migration system

Data flow

For the paused in-house assistant, local code context was gathered in the IDE, sent through proxies to fine-tuned backend models, verified for syntax, and displayed to developers. For AutoCover, a workflow prepares mocks and files, generates tests with an LLM, builds and runs tests, loops through LLM fixes, validates assertions, and refactors duplicates. For Java-to-Kotlin migration, historical migration deltas are mined, an agent drafts AST rules, CI runs conversion/build/test/lint, failures are fed back to another LLM, and successful deterministic rules go to platform review.

3 supporting quotes
“You have the code context gathering locally. It's taking that. It's handing it to the proxies that we have in place, which are talking to our back end hosted models”transcript, stated
“Then you have a step where we need to invoke an LLM. So that's the generate phase. And then we go build and run the tests.”transcript, stated
“We have an LLM that tries to write the draft rule. It then runs that through the Java to Kotlin tooling, gets a Kotlin output, runs that through CI.”transcript, stated

Why this architecture

Uber learned that building a full internal assistant would keep them in a costly catch-up race, so they built on Copilot for IDE surfaces and reserved internal AI investment for workflow-specific automation where Uber context and deterministic validation mattered.

3 supporting quotes
“we felt we would always be playing catch up with the vendored solutions.”transcript, stated
“So we decided to follow the ecosystem principle, where we wanna build on top of ecosystems, or produce ecosystems.”transcript, stated
“what if we took the two approaches using the LLMs and the determinism of the AST approach, and tried to get something better than both?”transcript, stated

Models used: GitHub Copilot · Starcoder · Code Llama · fine-tuned code models · LangChain · LangGraph · LLM repair loop · LLM-authored AST rules

Scale

Alternatives considered (roads not taken)

Compete with Copilot using an in-house coding assistant

Rejected because: The project required broad IDE, hosting, fine-tuning, and service investment while vendor products kept improving faster.

“There were six months of work just to get to the V1 across many engineers.”transcript, stated
“No matter what we were doing, they were always out competing us on headcount and new things were coming out”transcript, stated

Ask ChatGPT to migrate the whole monorepo

Rejected because: A flexible direct LLM migration would be fast, but hallucinations were too risky for mobile production code.

“obviously, like let's just drop this into ChatGPT and say migrate the entire monorepo. That seems totally safe, I think.”transcript, implied
“Hallucinations are gonna happen regardless of the prompt tuning and any one of those is going to risk a production outage.”transcript, stated

Have platform engineers manually write all AST postprocessor rules

Rejected because: The team expected many reusable rules and footguns, so LLM-assisted rule drafting could accelerate deterministic tooling.

“We're gonna keep needing to go back and write these and it's gonna be a really long process for us to write all the rules”transcript, stated
“we had the LLM help write the AST rules. We had platform reviewers review those, check those in, and now we have a deterministic output.”transcript, stated

Patterns

tool-use-orchestration (orchestration)

Uber models developer workflows as state machines where deterministic tools run builds, tests, AST transforms, and CI while LLM steps generate or repair artifacts.

“think about that workflow as like a state machine, and some of the steps that you go through could be a deterministic step where you have to use some sort of tool”transcript, stated
“It then runs that through the Java to Kotlin tooling, gets a Kotlin output, runs that through CI. Runs tests, builds, lint, everything you would expect.”transcript, stated

human-in-the-loop-gate (governance)

Developers iterate on generated tests, and platform engineers review LLM-authored AST rules before deterministic migration tooling lands.

“we really wanna have the developer be in the loop to iterate there.”transcript, stated
“That then goes to a platform engineer for review. Once that's finally in a good place, that lands.”transcript, stated

eval-driven-development (evaluation)

Uber added test validation, mutation-testing ideas, CI checks, and qualitative/quantitative developer productivity metrics to keep AI tooling tied to actual impact.

“once we get a test, we wanna go do some passes on it now to see if we can up level it.”transcript, stated
“we're leading with a qualitative approach first and then trailing with the quantitative metrics.”transcript, stated

Tradeoffs

Build on Copilot rather than continue competing internally.

Chose Vendor ecosystem integration over A fully in-house IDE coding assistant.

Rationale: The internal assistant could not keep up with vendor investment and had high integration and maintenance cost.

“we felt we would always be playing catch up with the vendored solutions.”transcript, stated
“we leaned very heavily into GitHub Copilot.”transcript, stated

Use deterministic AST tooling with LLM-authored rules for migration.

Chose LLM-assisted rule generation plus deterministic conversion over Direct LLM migration of source code.

Rationale: This preserved deterministic output and reviewability while using LLMs to speed up rule authoring.

“Obviously, this has some positives. It's very flexible. You could just give it code, tell it what you want, and you're gonna get an output.”transcript, stated
“Now, obviously, this has some downsides. It's slower than throwing it all into ChatGPT and calling it a day. But we think this is a trade off that we're willing to eat.”transcript, stated

Keep developers in the loop for generated unit tests.

Chose Interactive AutoCover test generation and validation over Automatically checking in generated tests.

Rationale: The team expected an error rate and wanted developers to iterate on generated tests before adoption.

“we don't wanna just kind of make tests, then check them in, we really wanna have the developer be in the loop to iterate there.”transcript, stated
“we should probably start labeling all the tests from AI too.”transcript, stated

Gotchas (what bit them)

AI MVPs were much easier than production developer tools.

Root cause: Production required IDE integrations, hosting, fine-tuning, service infrastructure, latency, analytics, and maintenance.

Resolution: Pause the in-house assistant and build on the vendor ecosystem where it already had distribution and investment.

“MVPs are really easy in this space. It's really easy to get an exciting video up, but productionizing that can be incredibly difficult and expensive.”transcript, stated
“we decided to kill it, to put it on pause.”transcript, stated

Internal assistants risked cannibalizing existing developer UI surfaces.

Root cause: Developers were already using Copilot chats and autocomplete surfaces.

Resolution: Use Copilot extension points and ecosystem integration rather than adding competing chats or hijacking autocomplete.

“If they were already using Copilot and had chats there, were we adding another chat? Were we hijacking the autocomplete?”transcript, stated
“So we decided to follow the ecosystem principle, where we wanna build on top of ecosystems”transcript, stated

Direct LLM code migration was too risky for mobile production.

Root cause: Hallucinated code could slip through review and cause outages in conservatively rolled out mobile apps.

Resolution: Use LLMs to write deterministic AST rules, then run conversion, tests, lint, and platform review before automation.

“Hallucinations are gonna happen regardless of the prompt tuning and any one of those is going to risk a production outage.”transcript, stated
“we had the LLM help write the AST rules. We had platform reviewers review those, check those in, and now we have a deterministic output.”transcript, stated

Developer productivity measurement can create bad incentives.

Root cause: Metrics such as lines of code or test coverage can produce verbosity or flaky tests if optimized blindly.

Resolution: Lead with qualitative developer feedback and normalize quantitative impact around developer time saved.

“If your organization prioritizes lines of code for your engineers, you're gonna get more verbose code.”transcript, stated
“we're leading with a qualitative approach first and then trailing with the quantitative metrics.”transcript, stated

Evaluation

Uber used acceptance-rate and latency goals for the paused assistant, developer skepticism and test validation for AutoCover, CI/build/test/lint loops for migration rules, Copilot adoption/PR velocity for rollout impact, and qualitative developer feedback plus developer-time-saved as broader metrics.

Metrics: 10% target acceptance-rate improvement · less than one second for 100 tokens · around 60% active 30-day Copilot developers · around 10% lift in PR velocity · CI, tests, builds, and lint · developer time saved

3 supporting quotes
“we expected we would be able to raise acceptance rate by about 10% over a non fine tuned.”transcript, stated
“today we have something around 60% of our developers that are active 30 day users for CoPilot.”transcript, stated
“we're trying to normalize the quantitative approach across all of our different projects into something that we're seeing emerging at other companies as well which is developer time saved.”transcript, stated

Outcomes

The work spans six monorepos, over 100 million lines of code, an Android monorepo with over 10 million lines and close to 100,000 files, and about 60% active 30-day Copilot developer usage.

3 supporting quotes
“And so we decided to kill it, to put it on pause.”transcript, stated
“we've shown some of the skeptics on this, where they were like, "This is never gonna work. And these tests are crazy."”transcript, stated
“with this approach, we think we'll be able to cut the migration in half.”transcript, stated