Skip to content

PATTERN Cited by 1 source

Language consolidation for fleet standardization

Problem

A large engineering org (1000s of engineers, thousands of microservices) that embraced language heterogeneity early — Python + JavaScript + Java + Go + Ruby + PHP all in production — accumulates a costly tax over time:

  • N× the service-library ecosystem. Each language needs its own tracing client, logging library, RPC wrapper, metrics reporter, etc. These diverge in behavior and quality.
  • Cross-language call overhead. Every inter-service RPC crosses a serialization boundary; type-system compatibility is perpetual yak-shaving.
  • Tooling N×. Build systems, test runners, dependency management, CI/CD pipelines — all multiplied.
  • Expertise fragmentation. Engineers end up language-locked; mobility across teams is harder.
  • Onboarding friction. New engineers learn N language ecosystems before contributing.
  • The distributed-monolith trap. Multiple languages + multiple repos + multiple solutions-to-common-problems = distributed monolith at the organization level.

Solution

Elevate a small number (1–3) of official languages for a domain (backend, mobile, web, data); deprecate the rest for new work; consolidate repositories into per-language monorepos.

Key design choices:

  • Pick languages with strong type-safety and performance if backend reliability matters — Uber explicitly chose Java + Go over Python + JavaScript "to gain type-safety and better performance".
  • Deprecate, don't delete. Existing services in deprecated languages continue running; no new code is written in them.
  • One monorepo per official language — reduces code discovery + sharing friction.
  • Shared service libraries for tracing, logging, resiliency, networking protocols — a one-time investment per language, not per team.

Canonical instance — Uber Project Ark (2018)

"As a result, we elevated Java and Go as official backend languages to gain type-safety and better performance. And deprecated the use of Python and Javascript for backend services. We embarked on reducing code repos from 12,000 down to just our main languages (Java, Go, iOS, Android, and web). We defined more standardized architectural layers where client, presentation, product, and business logic would have clear homes. We introduced abstractions where we could group a number of services together (service 'domains'). And continued to standardize on a series of service libraries to handle tracing, logging, networking protocols, resiliency patterns, and more."

sources/2024-03-14-highscalability-brief-history-of-scaling-uber

  • Before: Thousands of microservices, 12,000 code repos, Python + JS + Java + Go + others; developer productivity measurably hurting.
  • After: 5 monorepos (Java, Go, iOS, Android, web); Python/JS deprecated for backend; new service-domain abstractions group related services; shared libraries for cross-cutting concerns.

The decision was framed as technical-debt paydown forced by the distributed monolith Uber's decentralized "Let Builders Build" culture had produced.

Why this works

  • Tooling investment compounds. One tracing library per language, not per team. One CI/CD convention. One monorepo setup.
  • Developer mobility. Engineers can move between teams without re-learning an ecosystem.
  • Incident response scales. Oncall engineers debug the same stack types every time.
  • Reduces duplicate-system sprawl. "5 or 6 systems that do incentives that are 75% similar" is easier to consolidate when all 5–6 are in the same language monorepo.

Costs

  • Politically expensive. Deprecating languages people love creates friction and often attrition.
  • Migration cost. Existing services don't migrate themselves; some will run in deprecated languages for years.
  • Loss of niche wins. Some workloads genuinely do benefit from a niche language — the policy has to allow some escape hatches (e.g., Uber retained Python + JS for mobile/web/ML, just not for backend).

When to use

  • Engineering org in the distributed-monolith state: thousands of services, many languages, developer productivity visibly suffering.
  • Senior engineering leadership willing to absorb the political cost of deprecation.
  • Sufficient resources to fund the multi-year migration.

When not to use

  • Small org that still has velocity from language heterogeneity.
  • An org where language choice is an explicit hiring differentiator (some small niche companies).
  • Early-stage product still discovering workload shapes.
Last updated · 517 distilled / 1,221 read