Skip to content

필사 모드: Build Systems & Monorepo Tools 2026 — Bazel 8 · Pants 2 · Buck2 · Nx 20 · Turborepo 2 · Moon · Lerna 8 · Rush · pnpm Workspaces Deep Dive

English
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

Prologue — why build systems got interesting again

A 2026 platform meeting at a typical company.

Junior: "We're a JS monorepo, Turborepo is enough, right?"

Senior: "Then how do we build the Go backend and the Python data team together?"

Junior: "...oh."

That tiny exchange has all of 2026 in it. On one side: **language-native tools** (cargo, gradle, npm scripts). On the other side: **polyglot** systems (Bazel, Buck2, Pants). And between them, the **task runner + cache** layer (Nx, Turborepo, Moon).

This piece is the full map as of May 2026. Bazel 8 with Bzlmod by default, Buck2 settling as OSS, Pants 2 owning Python, the Nx 20 vs Turborepo 2 split, Moon climbing the polyglot ladder, and Gradle 8.10 / Maven 4 / sbt 1.10 in JVM land. Plus what Korean and Japanese big tech actually ships with.

1. The 2026 build-system map — two axes

There's too much packed into the phrase "build system." The easiest cut is two axes.

| Axis 1 / Axis 2 | Single language | Polyglot |

| --- | --- | --- |

| Local cache only | cargo, npm, go build | GNU Make, just, Task |

| Remote cache/exec | Gradle + Develocity, Nx Cloud, Turborepo Remote Cache | Bazel, Buck2, Pants |

Vertical: **language coverage**. Horizontal: **cache/distribution depth**. The 2026 trend is that the bottom-right cell (polyglot + remote) is filling up fast. And within that cell, two camps split: the **Bazel/Buck2/Pants** camp ("declarative graph + interpreted BUILD files") and the **Nx/Turborepo/Moon** camp ("JSON/YAML config + run only affected projects").

Starting point is simple.

1. **Single language + small team** → that language's native tool (cargo, gradle, npm).

2. **Single language + large monorepo** → native tool + remote cache (Develocity, Nx Cloud).

3. **JS/TS-heavy + multiple packages** → pnpm workspaces / Nx / Turborepo.

4. **Polyglot + large scale** → Bazel / Buck2 / Pants.

2. Monorepo vs polyrepo — the 2026 answer

This debate is basically settled. The answer is "both, but monorepo is the default."

**Monorepo wins**: atomic changes (one PR touches library, service, tests at once), single dependency graph, shared infra (build, CI, lint), one-IDE search and refactor.

**Polyrepo wins**: permission isolation, build-time isolation, team autonomy, the simplicity of a small repo.

The 2026 compromise: **"several monorepos inside one company."** For example `platform-monorepo` (infra), `product-monorepo` (services), `data-monorepo` (pipelines). Each one is a monorepo, but company-wide it's polyrepo. Parts of Google, Meta, and Microsoft run this pattern. For a small company, just have one monorepo.

`Trunk-based development` + `feature flags` + `change detection` (see section 21) together erase most of the historical monorepo downsides.

3. Bazel 8 — the polyglot build standard

Bazel is the OSS version of Google's internal Blaze. Stable in May 2026 is **Bazel 8.x**, LTS is 7.x. The major shift: **Bzlmod** (MODULE.bazel) is now the default and WORKSPACE mode is deprecated.

License: Apache 2.0. Used by Google, X (formerly Twitter), Stripe, Pinterest, Spotify, Snap, Dropbox, Coupang, Mercari.

Core concepts.

- **`BUILD.bazel`**: one per directory, declares build targets in that directory.

- **`WORKSPACE` / `MODULE.bazel`**: repo root, declares external deps and toolchains.

- **Starlark**: Python subset, the language for writing build rules.

- **rules**: language-specific rule sets (`rules_go`, `rules_python`, `rules_js`, `rules_rust`, `rules_java`).

- **sandbox**: every action runs in an isolated directory, guaranteeing hermeticity.

- **remote cache / remote execution**: actions are keyed by hash, misses are dispatched to remote workers.

Simplest Go binary.

BUILD.bazel

load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(

name = "hello_lib",

srcs = ["main.go"],

importpath = "example.com/hello",

)

go_binary(

name = "hello",

embed = [":hello_lib"],

)

bazel build //cmd/hello:hello

bazel test //...

bazel query 'deps(//cmd/hello:hello)' | head

Bzlmod dependency declaration.

MODULE.bazel

module(name = "myrepo", version = "0.1.0")

bazel_dep(name = "rules_go", version = "0.55.0")

bazel_dep(name = "gazelle", version = "0.41.0")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")

go_deps.from_file(go_mod = "//:go.mod")

use_repo(go_deps, "com_github_pkg_errors")

Bazel's strength is that **graph + cache + remote execution** are deeply integrated. The weakness is the learning curve and the chore of hand-writing BUILD files (mitigated by generators like Gazelle).

4. Buck2 (Meta) — Buck rewritten in Rust

Buck1 was Meta's Bazel cousin from 2013. In 2023 Meta rewrote it from scratch in Rust and released it OSS — **Buck2**. As of 2026 it's the standard internal build at Meta, and OSS adoption has been growing.

Compared with Bazel.

| Item | Bazel | Buck2 |

| --- | --- | --- |

| Implementation | Java | Rust |

| Config language | Starlark | Starlark |

| Action graph | Determined at rule evaluation | Dynamic Dependencies, can mutate mid-build |

| Remote execution | REAPI (BuildBuddy, EngFlow) | REAPI (BuildBuddy, EngFlow) |

| License | Apache 2.0 | Apache 2.0 |

| Main users | Google, X, Stripe | Meta, Discord |

The biggest difference is **dynamic dependencies**. Bazel separates BUILD evaluation → action graph → execution, so the graph can't change once the build starts. Buck2 lets some nodes declare additional inputs mid-build, which naturally captures things like OCaml `.ml` / `.mli` dependencies driven by compilation output.

BUCK

load("@prelude//rules.bzl", "cxx_binary", "cxx_library")

cxx_library(

name = "hello_lib",

srcs = ["hello.cc"],

headers = ["hello.h"],

)

cxx_binary(

name = "hello",

srcs = ["main.cc"],

deps = [":hello_lib"],

)

buck2 build //cpp/hello:hello

buck2 test //...

buck2 cquery 'deps(//cpp/hello:hello)'

Is migrating from Bazel worth it? Usually no. Only consider Buck2 for **a new polyglot monorepo** + **Meta-influenced org** + **genuine need for dynamic deps**.

5. Pants 2 — the de-facto Python monorepo

Pants v1, from Twitter in 2014, was a Java/Scala build system. Starting with v2, **Toolchain Labs** rebuilt it from scratch as a **Python-first polyglot**. Stable in May 2026 is **Pants 2.27**.

License: Apache 2.0. Used at Slack, IBM, Pico, Toolchain.

What sets Pants 2 apart.

- **Python-first**: first-class support for `pytest`, `mypy`, `ruff`, `pyright`, `black`, `flake8`.

- **Automatic dependency inference**: import graph analysis adds deps to BUILD files automatically.

- **Lockfile-aware**: integrates PEP 621 / pyproject.toml with lockfiles.

- **Remote caching**: compatible with BuildBuddy and EngFlow.

pants.toml

[GLOBAL]

pants_version = "2.27.0"

backend_packages = [

"pants.backend.python",

"pants.backend.python.lint.ruff",

"pants.backend.python.typecheck.mypy",

"pants.backend.docker",

]

[python]

interpreter_constraints = ["==3.12.*"]

src/python/myapp/BUILD

python_sources(name="lib")

python_tests(name="tests", dependencies=[":lib"])

pex_binary(name="bin", entry_point="myapp.main:main")

pants tailor :: # auto-generate BUILD files

pants lint test check :: # lint/test/typecheck everything

pants --changed-since=main test # only what changed

pants package src/python/myapp:bin

For a Python monorepo Pants 2 is nearly the default. Caching mypy/ruff results is what seals the deal.

6. Remote execution backends — BuildBuddy / EngFlow / NativeLink

Bazel, Buck2, and Pants all speak the **Remote Execution API** (REAPI), a gRPC standard. Cache (action result, CAS) and execution (workers) are decoupled: on a cache miss the client delegates execution to a remote worker.

Main 2026 backends.

| Product | Company | Notes |

| --- | --- | --- |

| BuildBuddy | BuildBuddy Inc | Open-core, great UI, GCP/AWS SaaS + self-host |

| EngFlow | EngFlow | Enterprise focus, used by Spotify, Tesla |

| NativeLink | TraceMachina | OSS, Rust, still maturing but fast |

| Buildbarn | OSS | Fully open source, run it yourself |

BuildBuddy config example (`.bazelrc`).

build --bes_results_url=https://app.buildbuddy.io/invocation/

build --bes_backend=grpcs://remote.buildbuddy.io

build --remote_cache=grpcs://remote.buildbuddy.io

build --remote_executor=grpcs://remote.buildbuddy.io

build --remote_header=x-buildbuddy-api-key=YOUR_API_KEY

That single block turns on cache + execution + Build Event Stream (BES, web UI for tracing builds). On a big monorepo, build times often drop 5–10x.

7. Nx 20 — the JS/TS monorepo heavyweight

Nx is the JS/TS monorepo tool from Nrwl (now Nx). Stable in May 2026 is Nx 20.x. License MIT. The hosted offering is Nx Cloud (paid SaaS).

Two core wins.

1. **Local + remote cache**: hash-keyed cache of task outputs (build, test, lint).

2. **affected**: run only the projects impacted by a git diff.

npx create-nx-workspace@latest myorg --preset=ts

cd myorg

nx g @nx/react:app web

nx g @nx/node:app api

nx g @nx/js:lib shared

// nx.json

{

"tasksRunnerOptions": {

"default": {

"runner": "nx-cloud",

"options": {

"cacheableOperations": ["build", "lint", "test", "e2e"],

"accessToken": "YOUR_NX_CLOUD_TOKEN"

}

}

},

"namedInputs": {

"default": ["{projectRoot}/**/*"],

"production": ["default", "!{projectRoot}/**/*.spec.ts"]

}

}

nx run-many -t build # build everything

nx affected -t test # test only affected projects

nx graph # visualize project dep graph

nx release # version, changelog, publish

New in Nx 20: **Atomizer** (test splitting), **Custom Conformance Rules** (monorepo rule checks), **Self-Healing CI** (auto-retry + analyze failed e2e). After the Lerna acquisition the integration is essentially done — Lerna is now closer to an alias for Nx.

8. Turborepo 2 — Vercel's JS monorepo tool

Turborepo was built by Jared Palmer in 2021. Acquired by Vercel in 2022. **Turborepo 2.0** (2024) rewrote the core in Rust, and 2.x is the May 2026 stable.

Versus Nx.

| Item | Nx | Turborepo |

| --- | --- | --- |

| Philosophy | "Smart" workspace (generators, plugins, graph) | "Simple" task runner + cache |

| Config | nx.json + project.json | turbo.json |

| Code gen | Rich generators | Almost none |

| Cache | Local + Nx Cloud | Local + Remote Cache (Vercel free tier, self-hostable) |

| Distributed exec | Nx Agents | None (use CI shards) |

| Language | JS/TS focus, some polyglot | JS/TS only |

| Learning curve | Medium-high | Low |

// turbo.json

{

"$schema": "https://turbo.build/schema.json",

"tasks": {

"build": {

"dependsOn": ["^build"],

"outputs": [".next/**", "!.next/cache/**", "dist/**"],

"inputs": ["src/**", "package.json", "tsconfig.json"]

},

"test": { "dependsOn": ["^build"], "outputs": ["coverage/**"] },

"lint": { "outputs": [] },

"dev": { "cache": false, "persistent": true }

}

}

turbo run build # full build (cache hits skipped)

turbo run test --filter=...[origin/main] # changed only

turbo run dev --parallel # parallel dev servers

turbo prune --scope=web # slice down for Docker build

Turborepo's killer combo is **simplicity + Vercel integration**. Set `TURBO_TOKEN` + `TURBO_TEAM` in CI and Vercel Remote Cache turns on automatically. For Next.js / Remix-shaped teams, Turborepo is the lowest-friction path.

9. Moon (moonrepo) — Rust-built polyglot dark horse

Moon appeared in 2022 as a Rust-based build system. Built by Miles Johnson, formerly of Lerna and Yarn. License MIT. Goal: unify JS/TS, Python, Rust, Go, Deno, and Bun under one tool.

Difference from Nx/Turborepo.

- **Language-agnostic**: `lang.toml` pins toolchain (Node, Deno, Bun, Rust, Python) versions.

- **Project graph**: directory-scoped like Bazel, but configured in YAML.

- **Affected**: same concept as Nx.

- **Mise integration**: pairs with the Mise version manager to bootstrap toolchains.

.moon/workspace.yml

projects:

- 'apps/*'

- 'packages/*'

vcs:

manager: 'git'

defaultBranch: 'main'

runner:

cacheLifetime: '7 days'

archivableTargets: ['build', 'test']

apps/web/moon.yml

language: 'typescript'

type: 'application'

dependsOn:

- 'shared'

tasks:

build:

command: 'next build'

outputs: ['.next']

test:

command: 'vitest run'

moon run web:build

moon ci # every affected task

moon dep-graph

Moon is still small, but **Rust speed + polyglot + YAML config** is an attractive combo. Worth a look for teams who find Bazel heavy and Turborepo too JS-only.

10. Lerna 8 · Rush · pnpm workspaces — three lightweight JS options

There are still three lightweight JS monorepo options.

**Lerna 8**: acquired by Nrwl in 2022, now effectively part of Nx. For a new project just use Nx directly, but existing Lerna repos can opt into Nx's cache and affected logic.

// lerna.json

{ "version": "independent", "npmClient": "pnpm", "useNx": true }

lerna run build --since=origin/main

lerna publish

**Rush (Microsoft Rush Stack)**: built on top of pnpm with strict policies (no phantom deps, change-file checks). Used inside Microsoft, Office Online, parts of Azure. Pick it when a big JS monorepo needs strong guardrails.

rush install

rush build

rush change # author a change file before PR

rush publish

**pnpm workspaces (9.x)**: the simplest. `pnpm-workspace.yaml` + `package.json` `workspaces` field. No cache or affected, but great for small monorepos (under 20 packages).

pnpm-workspace.yaml

packages:

- 'apps/*'

- 'packages/*'

pnpm install

pnpm -r build # build every workspace

pnpm --filter=@org/web build # one package

pnpm --filter='...[origin/main]' test # affected only (pnpm 9+)

Quick guide: **small team + JS only + want simple** → pnpm workspaces. **Mid–large + Vercel-friendly** → Turborepo. **Mid–large + rich tooling/policies** → Nx. **Large + strict policies + MS-friendly** → Rush.

11. JVM camp — Gradle 8.10 + Maven 4

The JVM has its own deep build-tool ecosystem. Stable versions in May 2026.

**Gradle 8.10+**: Groovy/Kotlin DSL, dependency management, multi-project. Two core cache features.

- **Build cache**: caches task outputs (local + remote).

- **Configuration cache**: caches the configuration phase itself (saves seconds-to-tens-of-seconds on big projects).

- **Develocity** (formerly Gradle Enterprise): remote cache + build scan + test insights SaaS.

// build.gradle.kts

plugins {

java

application

id("org.springframework.boot") version "3.4.1"

}

group = "com.example"

version = "0.1.0"

repositories { mavenCentral() }

dependencies {

implementation("org.springframework.boot:spring-boot-starter-web")

testImplementation("org.springframework.boot:spring-boot-starter-test")

}

tasks.test { useJUnitPlatform() }

./gradlew build --build-cache --configuration-cache

./gradlew :api:test

./gradlew dependencies

**Maven 4** (GA in 2025): keeps pom.xml stable while strengthening the build graph, parallelism, and the daemon (`mvnd`). Still the first choice thanks to Spring's gravitational pull. `mvnd` (Maven Daemon) avoids JVM warmup, getting close to Gradle in perceived speed.

./mvnw -T 1C clean install # 1 thread per CPU core in parallel

mvnd -T 1C clean install # daemon mode

For a JVM monorepo: new projects pick Gradle + Develocity, legacy/SI projects stay with Maven 4 + mvnd.

12. sbt 1.10 · Mill — Scala camp

There's a separate Scala post, but briefly from a build perspective.

**sbt 1.10**: the Scala default, incremental compile is its strength. The eternal complaint is the steep learning curve.

// build.sbt

ThisBuild / scalaVersion := "3.6.0"

lazy val root = (project in file("."))

.settings(

name := "myapp",

libraryDependencies ++= Seq(

"org.typelevel" %% "cats-effect" % "3.5.4",

"org.scalatest" %% "scalatest" % "3.2.19" % Test,

)

)

**Mill (Lihaoyi)**: a Scala/Java/JS build expressed in Scala. Cleaner and faster than sbt, in the consensus view. Not mainstream, but new Scala teams sometimes pick it.

// build.mill

package build

object app extends ScalaModule {

def scalaVersion = "3.6.0"

def ivyDeps = Agg(ivy"org.typelevel::cats-effect:3.5.4")

}

A genuinely large Scala monorepo basically only has Bazel + `rules_scala` as the answer, but few teams ever reach that size.

13. C/C++ — CMake 3.31 + Ninja 1.12 / Meson / Bazel

C/C++ had the longest build-system warring states. The 2026 summary.

**CMake 3.31 + Ninja 1.12**: the de-facto standard. CMake isn't a build system — it's a build-system **generator** (produces Makefiles, Ninja, MSBuild). Ninja runs the result fastest.

CMakeLists.txt

cmake_minimum_required(VERSION 3.31)

project(myapp CXX)

set(CMAKE_CXX_STANDARD 23)

add_library(mylib STATIC src/foo.cc src/bar.cc)

target_include_directories(mylib PUBLIC include)

add_executable(myapp src/main.cc)

target_link_libraries(myapp PRIVATE mylib)

cmake -S . -B build -G Ninja

cmake --build build -j

ctest --test-dir build

**Meson + Ninja**: CMake's cousin, cleaner syntax (Python-ish). Used by GNOME, systemd.

**Bazel + rules_cc**: the answer for large polyglot C/C++ monorepos. The C++ services at Google, Stripe, and Pinterest live on this path.

**GNU Make**: still the first pick for small projects. Lowest learning curve.

14. Rust — Cargo workspaces + cargo-nextest

A Rust monorepo is almost always fine with **Cargo workspaces**.

Cargo.toml (root)

[workspace]

resolver = "2"

members = ["crates/*", "services/*"]

[workspace.dependencies]

tokio = { version = "1.42", features = ["full"] }

serde = { version = "1.0", features = ["derive"] }

cargo build --workspace

cargo test --workspace

cargo nextest run --workspace # faster test runner

cargo metadata --format-version 1 # dep graph

If you need a remote cache, `sccache` (Mozilla) is standard. Backends: S3, GCS, Redis, memcached, local disk.

export RUSTC_WRAPPER=sccache

export SCCACHE_BUCKET=my-sccache-bucket

cargo build --release

sccache --show-stats

When Rust joins a large polyglot stack, Bazel + `rules_rust` is on the table, but the onboarding cost is real. Without a company-wide Bazel standard, sccache + Cargo is almost always the answer.

15. Go — go modules + gomonorepo patterns

Go's module system is simple, which makes monorepos natural. One `go.mod` at the repo root, with `internal/` for package boundaries.

myrepo/

go.mod

cmd/

api/main.go

worker/main.go

internal/

auth/

storage/

pkg/

publicapi/

go build ./...

go test ./...

go vet ./...

go test -count=1 -run TestFoo ./internal/auth

When caching and remote execution matter, Bazel + `rules_go` + `gazelle` is the most mature combo. Gazelle generates `BUILD.bazel` from `go.mod`.

bazel run //:gazelle

bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%go_dependencies

The Go services at Pinterest, Twitter, and Coupang live on this path.

16. Mise (formerly rtx) · just · Task — lightweight task runners

Separate from build systems, there's the **"call repeated commands by short names"** family. Successors to shell scripts and Makefiles.

**Mise** (formerly rtx): asdf-compatible version manager + task runner. Written in Rust. One tool pins Node, Python, Go, Rust, Ruby, and Bun versions, and defines tasks.

mise.toml

[tools]

node = "22"

python = "3.12"

go = "1.23"

[tasks.build]

description = "Build all"

run = "pnpm -r build"

[tasks.test]

description = "Run tests"

depends = ["build"]

run = "pnpm -r test"

mise install # install the toolchain

mise run build

mise run test

**just**: a modern Make. Clean syntax, no dependencies.

justfile

default:

@just --list

build:

pnpm -r build

test: build

pnpm -r test

release version:

git tag v{{version}}

git push origin v{{version}}

**Task** (taskfile.dev): YAML-based task runner, written in Go.

Taskfile.yml

version: '3'

tasks:

build:

cmds:

- pnpm -r build

test:

deps: [build]

cmds:

- pnpm -r test

These three are **not graph-aware build tools** — they're command shorthands. Great as the entry point even on large monorepos: `just ci` can call `bazel test //...` or `nx affected -t test` under the hood.

17. Remote cache — Bazel BES vs Nx Cloud vs Turborepo Remote Cache

The three tools cache remotely in different ways.

| System | Cache key | Storage | Backend |

| --- | --- | --- | --- |

| Bazel | action hash (inputs + command + env) | CAS (Content Addressable Storage) | BuildBuddy, EngFlow, Buildbarn |

| Nx Cloud | task hash (inputs + command + env) | Nx Cloud SaaS or self-host | Nx Cloud (proprietary) |

| Turborepo Remote Cache | task hash | Vercel SaaS or self-host | Vercel, Turborepo Server (OSS) |

**Bazel strengths**: REAPI standard, multi-backend, cache hits are reliable thanks to sandboxing.

**Nx Cloud strengths**: web UI, failed-build insights, Nx Agents (distributed execution) integration.

**Turborepo strengths**: easiest setup (two env vars), automatic Vercel CI integration.

All three offer self-hosting, but ops effort scales BuildBuddy/Buildbarn >> Nx Cloud (Helm chart) >> Turborepo Server (one Docker container).

18. Hermetic builds + content-addressed cache — the essence of reproducibility

"It worked yesterday, broken today" almost always comes from **hidden inputs** (env vars, system libraries, the clock, the network). The fix is hermetic builds + content-addressed caching.

**Hermetic**: explicitly declare an action's inputs (sources + tools + env vars) and block external access (sandbox). Bazel, Buck2, and Pants do this by default.

**Content-addressed**: assume that identical input hashes produce identical outputs. Any byte of input change forces a rebuild; identical inputs hit the cache.

input_hash = sha256(sources + tools + env + command)

output: stored under output_hash

cache_key: input_hash -> output_hash

Nix follows the same philosophy (different tool from Bazel, same idea). Reproducible CI/CD becomes actually achievable.

19. Container build — BuildKit / Buildah / Kaniko / Earthly

The build-systems story ends with containers because in 2026 every service ships as an OCI image, and **build-system output → container image** is the final step of the pipeline.

| Tool | Daemon needed | Notes |

| --- | --- | --- |

| Docker BuildKit | Yes (dockerd) | Standard, cache mounts, SBOM, provenance |

| Buildah / Podman build | No | Daemonless, Red Hat |

| Kaniko | No | Build containers inside a container, K8s CI-friendly |

| Earthly | Uses daemon | Dockerfile + Makefile hybrid, strong caching |

| ko (Go only) | No | Pack Go binaries into distroless images instantly |

| Jib (JVM only) | No | Maven/Gradle plugin, image build without Docker |

Bazel uses `rules_oci` (successor to `rules_docker`) to build OCI images hermetically. Image layers stay byte-identical across rebuilds when inputs match.

BUILD.bazel

load("@rules_oci//oci:defs.bzl", "oci_image")

oci_image(

name = "api_image",

base = "@distroless_base",

entrypoint = ["/api"],

tars = [":api_layer"],

)

20. Build systems at global big tech

| Company | Primary build |

| --- | --- |

| Google | Blaze (internal Bazel) |

| Meta | Buck2 |

| Microsoft | Rush + internal systems |

| Amazon | Brazil (internal) + Cargo / Maven |

| X (formerly Twitter) | Bazel (migrated from Pants) |

| Pinterest | Bazel (Python/Java/Go) |

| Stripe | Bazel |

| Spotify | Bazel + EngFlow |

| Snap | Bazel |

| Dropbox | Bazel (some Python on Pants) |

| Slack | Pants (Python, TS) |

| Vercel | Turborepo |

| Shopify | Bazel (services), nx/turborepo (storefront) |

| GitHub | Internal + Bazel |

| Discord | Buck2 |

Polyglot + large scale converges on Bazel/Buck2/Pants.

21. Korean and Japanese examples

**Korea**

- **Coupang**: heavy Bazel adoption. Search, logistics, parts of iOS/Android. The C++ search infra runs on Bazel hermeticity.

- **Toss / Viva Republica**: frontend on Turborepo. Backend is Gradle-heavy.

- **Naver**: broad usage. Some Bazel in NHN/Naver Pay; many frontend teams on Turborepo or Nx.

- **Kakao**: Gradle/Maven-centric, frontend on Turborepo / pnpm workspaces.

- **Woowa Brothers (Baemin)**: Gradle + Spring-centric. Frontend on Nx/Turborepo.

- **Karrot (당근)**: pnpm workspaces + Turborepo is the standard. Some Nx adoption.

**Japan**

- **Mercari**: heavy Bazel. Go/Java microservices on Bazel + BuildBuddy.

- **LINE Yahoo**: Bazel (LY) and Gradle (LINE legacy). Search/ads infra on Bazel.

- **CyberAgent / Ameba**: Nx + Turborepo. Bazel on parts of the ad platform.

- **Recruit / Indeed**: heavy Bazel. Indeed has published frequently on monorepo + Bazel.

- **DeNA**: Gradle-centric with some Bazel.

- **Rakuten**: Gradle + Maven, some Bazel.

Worth noting: Japanese big tech adopts Bazel at a higher rate than Korea, with Mercari, Indeed, and LY leading.

22. When to pick what — the decision tree

Putting it all together.

1. **Small JS team (~5 people, ~10 packages)** → `pnpm workspaces` alone.

2. **Mid-size JS/TS team (~30 people, ~50 packages) + Vercel/Next.js-heavy** → `Turborepo 2` + Vercel Remote Cache.

3. **Mid-size JS/TS team + need rich tooling/policies** → `Nx 20` + Nx Cloud.

4. **JS + Python + Go polyglot monorepo** → `Moon` or `Bazel`.

5. **Python monorepo (data/ML team)** → `Pants 2`.

6. **New JVM project** → `Gradle 8.10` + Develocity.

7. **Legacy/SI JVM project** → `Maven 4` + `mvnd`.

8. **Rust monorepo** → `Cargo workspaces` + `sccache` + `cargo-nextest`.

9. **Go monorepo** → single `go.mod`, add Bazel + Gazelle when needed.

10. **C/C++** → `CMake + Ninja` (small) or `Bazel` (large).

11. **Scala** → `sbt` or `Mill`, only `Bazel + rules_scala` if truly huge.

12. **Massive polyglot + remote execution required** → `Bazel` + BuildBuddy/EngFlow, or `Buck2`.

The most common mistake is "adopt Bazel because it's trending, regret it six months later." Only consider a polyglot build system when **build time is genuinely a bottleneck**, **the bottleneck is solvable by remote cache/execution**, and **you have maintainers**. Otherwise, that language's native tool is almost always correct.

References

- Bazel docs — https://bazel.build/

- Bazel Bzlmod (MODULE.bazel) — https://bazel.build/external/module

- Buck2 — https://buck2.build/

- Buck2 GitHub — https://github.com/facebook/buck2

- Pants 2 docs — https://www.pantsbuild.org/

- Nx docs — https://nx.dev/

- Nx Cloud — https://nx.app/

- Turborepo — https://turbo.build/repo

- Turborepo 2 launch — https://vercel.com/blog/turborepo-2-0

- Moon (moonrepo) — https://moonrepo.dev/

- Lerna — https://lerna.js.org/

- Rush Stack — https://rushjs.io/

- pnpm Workspaces — https://pnpm.io/workspaces

- Yarn Workspaces — https://yarnpkg.com/features/workspaces

- Gradle — https://gradle.org/

- Develocity (formerly Gradle Enterprise) — https://gradle.com/develocity/

- Apache Maven — https://maven.apache.org/

- mvnd (Maven Daemon) — https://github.com/apache/maven-mvnd

- sbt — https://www.scala-sbt.org/

- Mill — https://mill-build.org/

- CMake — https://cmake.org/

- Ninja — https://ninja-build.org/

- Meson — https://mesonbuild.com/

- BuildBuddy — https://www.buildbuddy.io/

- EngFlow — https://www.engflow.com/

- NativeLink — https://www.nativelink.com/

- Buildbarn — https://github.com/buildbarn

- Mise (formerly rtx) — https://mise.jdx.dev/

- just — https://github.com/casey/just

- Task (taskfile.dev) — https://taskfile.dev/

- Cargo Workspaces — https://doc.rust-lang.org/cargo/reference/workspaces.html

- cargo-nextest — https://nexte.st/

- sccache — https://github.com/mozilla/sccache

- Remote Execution API (REAPI) — https://github.com/bazelbuild/remote-apis

- BuildKit — https://github.com/moby/buildkit

- rules_oci — https://github.com/bazel-contrib/rules_oci

- Mercari Engineering / Bazel — https://engineering.mercari.com/en/blog/

Epilogue — "Builds are graphs, always"

If you compress 30 years of build systems into one line, it's **"a directed graph from inputs to outputs — reuse the nodes whenever you can."** What Make tried to do, Bazel does with sandboxing + remote execution, Turborepo does with a JS-only simplification, and Pants does in a Python-friendly way.

The tools rotate, but the principle is constant: **"know the exact inputs to your build, cache the outputs, never rerun on identical inputs."** 2026's polyglot build systems apply that principle **across multiple languages and machines**. Small teams have it covered by tools that implement the principle closest to home (pnpm + Turborepo, Cargo, Gradle); huge teams may not be able to avoid Bazel.

One last note — a build system's success depends on **"who maintains the BUILD files,"** not the tool itself. People, not tooling. Bazel or Nx, without a **dedicated build-infra owner (one or two engineers)**, success is roughly halved. Without the headcount budget, the right build system for that company is usually a simpler one.

현재 단락 (1/483)

A 2026 platform meeting at a typical company.

작성 글자: 0원문 글자: 24,456작성 단락: 0/483