Part 3 · 1 chapters · ~8 min

Migrations at Scale

Changing hundreds of services: inventory by code search, codemods and automated pull requests (OpenRewrite, jscodeshift, Sourcegraph batch changes), tracking dashboards, deadlines with exceptions, doing the long tail yourself, and the case for migrations owned by the team that wants them.

4

Automate, track, finish

code
# find every use (Sourcegraph-style search)
lang:typescript import.*from ['"]@acme/legacy-logger['"]   → 412 repositories

# codemod (jscodeshift): rewrite imports and calls
export default function (file, api) {
  const j = api.jscodeshift;
  return j(file.source)
    .find(j.ImportDeclaration, { source: { value: '@acme/legacy-logger' } })
    .forEach(p => { p.node.source.value = '@acme/log'; })
    .toSource();
}
# batch change: open one PR per repo with the codemod output, labels and a link to the migration guide

Who does the work: migrations where every team must do work for another team's benefit stall. The team that wants the migration (platform, security) should do most of it with automation and leave owners only to review. For Java, OpenRewrite recipes upgrade Spring Boot versions across repos the same way.

A MIGRATION BURNDOWN
services still on the old logging library, by week
week 0412week 2 (codemod PRs)190week 496week 641week 8 (deadline)9week 100
swipe the figure sideways, or tap expand for full screen
1/4
inventory
Find every affected service automatically (code search, dependency graph): 412 services import the old library.
measure the scope firstcode search, not surveys