turborepo — Engineering Performance
13 engineers all time · Jan 2025 – Sep 2026 · built 2026-09-30 · GitHub
Performance snapshot
Today's rolling 90-day reading for turborepo, compared with the start of the series. Pick a window to move that comparison point.
Avg. perf / dev / mo
+2082.7%
1.02 → 22.17 ETV
Active engineers
−57.1%
7.0 → 3.0
Features
−1.1pp
35.6% → 34.5%
vs. Vercel
4.4x
0.66x → 4.4x · +340% above
turborepo vs. Vercel
Per-engineer ETV for turborepo against Vercel as a whole. Both lines are 90-day rolling averages scaled to a 30-day month, so they share one axis and can be read against each other at any point. Pick a window to zoom the chart to it.
Performance Composition
Each month's output split by type of work: Features (new value), Maintenance (sustaining systems), Tests, Docs, and Fixes (rework). The yellow line is output per engineer, so when it rises each engineer is delivering more, whatever the team size did. Unit: Engineering Throughput Value (ETV).
Engineering capacity
Effective engineers behind turborepo, against its pre-AI baseline. Each subject has its own: turborepo's is 1.02 ETV / dev / mo, its first reading in Q1 2025. Per-engineer ETV divided by that gives a capacity multiple, and that multiple applied to the engineers active in the trailing 90 days turns it into engineer-equivalents. The line is the real headcount, so the gap between line and area is what the leverage is worth. Because each baseline is its own, every subject opens at 1.0x on its first day: multiples measure improvement and are not comparable between subjects.
Knowledge concentration
How dependent is this repo on a small number of engineers? Higher top-1 share = higher key-person risk.
Anthony Shew owns 91.9 % of commits.
Behind the numbers
Written summary of the work completed each month.
No monthly reports available yet.
Top engineers
Most impactful commits
Top 10 by ETV in the all-time window.
- 6.5ETVfeat: Migrate TUI virtual terminals from vt100 to Ghostty (#13135) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ### Description Migrates Turborepo's TUI task output panes from the vendored `turborepo-vt100` crate to [Ghostty](https://ghostty.org)'s `libghostty-vt` terminal emulator. **Why Ghostty?** Ghostty's VT library is actively maintained, supports modern terminal features, and is the same engine powering the Ghostty terminal. This replaces the older in-repo vt100 implementation and removes the `tui-term` dependency. #### Architecture - **`turborepo-ghostty-sys`** — In-repo FFI against `libghostty-vt`. `build.rs` fetches a pinned Ghostty commit and compiles via Zig 0.15.2; `bindings.rs` is checked in for docs.rs. - **`turborepo-ghostty`** — Safe Rust wrappers (adapted from [libghostty-rs](https://github.com/Uzaaft/libghostty-rs)) plus Turborepo-specific `Parser` and ratatui `TerminalWidget` (adapted from [ratatui-ghostty](https://codeberg.org/jint/ratatui-ghostty)). - **`turborepo-ui`** — Task pane rendering, scroll, and selection updated to use the Ghostty-backed widget. TUI dependencies are gated behind a `tui` feature so lightweight consumers (e.g. `turborepo-telemetry`, `@turbo/repository`) don't pull in Ghostty/Zig. **Removed:** `crates/turborepo-vt100`, `tui-term` dependency. #### Notable fixes included - **Selection/copy** — Ghostty selection grid refs go stale as output streams; viewport endpoints are now persisted and refreshed before render/copy. Selected cells are highlighted during drag. - **`Send` for tokio** — Static Ghostty allocator objects are marked `Send + Sync` so the TUI `App` can be moved into `tokio::task::spawn`. - **CI / Zig** — `setup-zig` detects host arch (`aarch64` vs `x86_64`), uses the correct Windows `.zip`, and sets isolated `ZIG_GLOBAL_CACHE_DIR` to avoid stale linker failures on reused macOS runners. - **`@turbo/repository`** — Gating Ghostty behind `turborepo-ui`'s `tui` feature prevents the NAPI package from building `libghostty-vt` unnecessarily. #### Build requirements Zig 0.15.2+ is now required to build the `turbo` binary (documented in `CONTRIBUTING.md`). CI installs it via `.github/actions/setup-zig`. Optional env vars for local Ghostty development: `GHOSTTY_SOURCE_DIR`, `GHOSTTY_ZIG_SYSTEM_DIR`, `TURBOREPO_GHOSTTY_SYS_OPTIMIZE`. #### Attribution Vendored code is documented in the crate READMEs. Most safe wrappers and FFI patterns come from libghostty-rs; ratatui integration from ratatui-ghostty; `Parser` and Turborepo UI glue are original. ### Testing Instructions 1. Build and run the TUI: `cargo build` then `turbo run <tasks> --ui=tui` in a monorepo with long-running tasks. 2. **Selection/copy** — Click-drag across task output; verify highlight appears and copied text is correct after more output streams in. 3. **Scroll** — Mouse wheel and keyboard scrolling through task scrollback. 4. **Stdin** — Interactive tasks that read from stdin still work in the focused pane. 5. **Resize** — Resize the terminal while the TUI is open; panes should reflow cleanly. 6. **Non-TUI paths** — `turbo run` without `--ui=tui` and `@turbo/repository` tests should work without requiring a Zig build. <!-- CURSOR_AGENT_PR_BODY_END --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Anthony Shew <anthonyshew@users.noreply.github.com>Anthony Shew · b22d3b43 · 2026-06-25
- 5.3ETVfix: Discover native workspace metadata lazily (#14053) ### Description Closes [TURBO-6071](https://linear.app/vercel/issue/TURBO-6071/go-workspaces-defer-toolchain-discovery-until-go-packages-are-in-run). Use generic lazy native discovery across JavaScript, Cargo/Rust, Python/uv, and Go, while preserving each native toolchain's authoritative task and dependency semantics. - Collect a subprocess-free inventory containing only scope identities, manifest paths, and workspace roots. The inventory makes no claims about tasks, dependency edges, or execution contracts. - Use the existing package selector to narrow scope requests. When engine construction reaches unloaded metadata, request its owner and load that contributor's authoritative discovery output. Loading is monotonic, and final task selection happens only after those requests settle. - Load metadata reached through explicit task dependencies, topological dependencies, companion tasks, and root dependencies needed for hashing. Route this through contributor ownership rather than per-language filter checks. - Remove the previous planning-uncertainty framework, staged topology-reconciliation errors, and static Go task/build-constraint and replacement-graph reconstruction. Native Go discovery continues to resolve build tags and version-sensitive replacements. - Keep native resolution fallbacks scoped to their consumers so unrelated task hashes remain stable, and refresh watch snapshots when native metadata has been loaded. - Cover narrow missing-toolchain selections, qualified task arguments, cross-language dependencies, native catalogue queries, missing-task diagnostics, and hash stability with regression tests. ### Discovery contract Narrow JavaScript package or qualified-task selections do not load unrelated native contributors. Queries that reach native scopes or need repository-wide metadata may still require their toolchains, even if no native task ultimately executes. This includes unfiltered runs, dependency-wide or affected queries, strict task-entrypoint catalogue queries, and whole-repository consumers such as package listing and watch discovery. Task catalogues and dependency relationships come from native discovery rather than a partial approximation. Missing tools and invalid native workspaces retain their ordinary diagnostics; there are no new user-facing planning-proof or topology-reconciliation errors.Anthony Shew · 30e02509 · 2026-09-15
- 5.2ETVfix: Refactor `turbo watch` (#13423) ## Summary - replace the shared raw filesystem event broadcast with scoped, demand-driven subscriptions for package changes, hashing, outputs, discovery, cookies, devtools, and daemon root monitoring - model inherited and nested Git ignores, global excludes, tracked exceptions, dynamic Git controls, and explicit ignored input/output interests - prune ordinary ignored trees from Linux inotify coverage while preserving explicit coverage, and route non-mutating backends directly after readiness - add scoped recovery for backend rescans/errors and document the watcher architecture Closes #13402 ## Validation - `cargo test -p turborepo-filewatch --lib` focused and platform-independent coverage - Linux all-feature filewatch test binary in Docker: 68/68 passed - `cargo test -p turborepo-lib package_changes_watcher::test` - `cargo clippy -p turborepo-filewatch --all-targets --all-features -- -D warnings` - `cargo clippy -p turborepo-lib -p turborepo-daemon -p turborepo-devtools --all-targets -- -D warnings` - `cargo check -p turborepo-filewatch --target x86_64-pc-windows-gnu` - original Linux reproduction with three repeated 100,000-file bursts: zero package/hash lag, one package build each, and one web-server start ## Notes Native macOS FSEvents stress was limited by local stream exhaustion after repeated test runs; focused FSEvents path/rescan tests and macOS compilation pass.Anthony Shew · 328b99f4 · 2026-07-21
- 3.1ETVchore: Add `turborepo-log` crate to improve our logging situation (#12285) ## Summary - Introduces `turborepo-log`, a new crate for structured user-facing log events (warnings, errors, informational output), deliberately separate from `tracing` which remains for developer diagnostics. - The global `Logger` dispatches events to pluggable `LogSink` implementations. Ships with two built-in sinks: `CollectorSink` (in-memory buffer for post-run summaries) and `FileSink` (newline-delimited JSON with optional size limiting). - All user-supplied strings are sanitized against ANSI escape sequences and control characters to prevent terminal injection. ## Why Today, user-facing messages in `turbo run` are scattered across ad-hoc `println!`/`eprintln!` calls and tightly coupled to `turborepo-ui`'s terminal rendering. This makes it hard to capture warnings for post-run summaries, write them to structured log files, or route them to the TUI without touching rendering code. `turborepo-log` sits at the bottom of the dependency graph (no dependency on `turborepo-ui`) and provides a clean boundary: subsystems emit structured events, sinks decide how to present or store them. A future terminal sink in `turborepo-ui` can implement `LogSink` to bridge into the existing rendering pipeline. ## Testing ```sh cargo test -p turborepo-log ``` The crate includes unit tests for all public types and an integration test (`tests/global_init.rs`) that exercises the full global logger lifecycle including lazy handle resolution.Anthony Shew · e9434ca4 · 2026-03-13
- 3.1ETVdocs: layout redesign (#10178) ### Description Newly formatted pages for docs content. ### Testing Instructions There are a great many changes in here that probably aren't useful to review as file changes. You'll want to open the preview and make sure all the design holds together.Anthony Shew · ae3db3d1 · 2025-03-21
- 2.8ETVfix: Preserve graceful shutdown output (#12607) ## Summary - Keep signal-driven `turbo run` cleanup alive until task shutdown finishes so TUI and grouped output are not torn down early or truncated. - Route shutdown and cache-flush status through the logging pipeline, distinguish signal vs close shutdowns, and avoid signal-only force timers on normal completion. - Harden process shutdown and parent-death cleanup while adding regression coverage for TUI, process, and signal-handling edge cases.Anthony Shew · 0b5bb210 · 2026-04-13
- 2.6ETVrefactor: Split process child module (#13014) ## Why The process child module mixed public process management, platform-specific handle internals, IO, shutdown semantics, and tests in one large file. Splitting those responsibilities reduces context needed to review future process changes. ## What Moves child handle internals, IO helpers, shutdown types and processing, state manager/channel logic, PTY test guard, and tests into sibling modules under `crates/turborepo-process/src/child/` while preserving the public API from `child.rs`. ## How This is intended as a mechanical refactor. Verified with `cargo fmt -p turborepo-process`, targeted child tests, `cargo test -p turborepo-process -- --test-threads=1`, `git diff --check`, and the repository pre-push hook.Anthony Shew · 24dd7c1f · 2026-06-03
- 2.5ETVperf: Skip work for disabled telemetry (#13972) <!-- startup-recovery-20260908 --> ### Review scope Independent optimization targeting `main`, with exactly one feature commit. No other optimization PR is a prerequisite. Recovered after the bundled #13970 merge was reverted by #13982. The separately merged parser optimization #13971 remains on `main`. This is not part of a cumulative optimization stack. The timing figures below are historical measurements from the original incremental benchmark sequence. They have not been remeasured on these newly independent branches and are not additive. <!-- /startup-recovery-20260908 --> ### Description Make explicitly disabled telemetry inert. Environment opt-out skips config loading; disabled telemetry creates no worker and avoids event UUID generation, formatting, hashing, and shutdown timers. Preserve enabled behavior and distinguish opt-out from missing initialization. ### Testing Instructions The startup investigation traced work performed even when telemetry was disabled. End-to-end run measurements did not establish a consistent standalone speedup for this layer; this removes avoidable opt-out work rather than claiming the combined benchmark gains. Enabled-mode measurements used a closed local proxy to exclude external network variability. #### Measurement limits - Measurements used optimized binaries, randomized paired before/after runs, warm OS/local caches, and synthetic npm fixtures. CPU/heap/syscall profiling was separate from wall-time timing. - Early batches had an unborn Git HEAD; later normalization and matcher-reuse batches used committed fixtures. Results from separate batches are not cumulative. - Windows runtime performance remains unmeasured. No worker-pool sizes or task concurrency defaults are reduced.Anthony Shew · 267ed73b · 2026-09-08
- 2.5ETVfix: Hardening for daemon IPC endpoints (#12742) - Prevent cross-user access to local daemon RPCs by moving daemon IPC into per-user paths and enforcing owner-only socket permissions. - Reject unauthorized Unix peers and validate Windows socket ownership before clients trust a daemon endpoint.Anthony Shew · 13a9a8b1 · 2026-05-07
- 2.3ETVfix: Filter microfrontend proxy environments (#12732) - Prevent microfrontend proxy tasks from inheriting undeclared parent environment variables. - Cover both custom proxy scripts and `@vercel/microfrontends` proxy binaries with regressions for strict env filtering.Anthony Shew · 9b28a75e · 2026-05-05