tezvyn:

Design a selective build strategy for a large monorepo

AI-drafted, machine-checkedintermediate

Tests monorepo dependency graph reasoning. Good answers model a DAG, compute reverse deps of the changed library, rebuild only affected targets via Bazel or Nx, and cache remotely. Red flag: directory triggers, full rebuilds, or testing the library alone.

WHAT THIS TESTS: This question probes your understanding of build system theory and incremental CI pipelines in large monorepos. The interviewer wants to see if you think in terms of directed acyclic graphs rather than folders, and whether you can distinguish between building, testing, and caching at scale. It also tests your familiarity with monorepo-native tooling and your ability to reason about transitive dependency propagation without resorting to brute force.

A GOOD ANSWER COVERS: First, represent the repository as a DAG where nodes are libraries, services, or build targets and edges are declared dependencies. Second, on a pull request, compute the changed targets from the diff, then walk the graph in reverse to find all downstream consumers that transitively depend on those targets. Third, rebuild and test only that affected subgraph, using a build system like Bazel, Nx, Rush, Pants, or Turborepo that supports precise affected-target detection. Fourth, layer a remote distributed cache so that artifacts from unaffected upstream targets are reused without local recomputation. Fifth, acknowledge the nuance that while tests can be scoped aggressively, builds often must include transitive dependents because their compiled inputs have changed; you might tier test execution with fast unit and integration tests for direct consumers and broader regression suites on trunk.

COMMON WRONG ANSWERS: Using directory-level triggers or CODEOWNERS files to guess what to build, which breaks when shared libraries cross boundaries. Rebuilding the entire monorepo on every change, which destroys compute budgets and developer velocity. Testing only the changed library and ignoring downstream breakage. Relying on manual dependency lists that drift out of sync. Assuming Git diff alone is sufficient without mapping files to build targets, which misses build configuration changes and generated code.

LIKELY FOLLOW-UPS: How would you handle a change to the compiler or base Docker image that theoretically affects every target? What happens if the dependency graph has cycles or diamond dependencies? How do you prevent cache poisoning in a shared remote cache? At what scale would you shard the affected set across multiple CI runners, and how? How do you manage external consumers outside the monorepo?

ONE CONCRETE EXAMPLE: Imagine a monorepo with five hundred packages. A developer modifies //libs/auth. The CI system queries the build graph and discovers twelve services and three intermediate libraries that transitively depend on //libs/auth. It schedules builds for those fifteen targets, skips the other four hundred eighty five, and pulls cached artifacts for unchanged upstream dependencies. It runs unit tests for the three intermediate libraries and integration tests for the twelve services, but does not launch the end-to-end suite for unrelated products. The build finishes in minutes instead of hours because the graph was precise and the cache was warm.

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.