Article
Feb 12, 2025

Scaling Tach to Large Codebases

Tach is fast, but making it effective in larger organizations requires more than just quick execution. These organizations face concrete challenges like:

  • How can we minimize disruption when teams are pushing >1k commits per day?
  • How do we incrementally improve the architecture of projects with >1k modules?

We recently released support for layers and distributed configuration which specifically address these challenges.

Layers - A Practical Approach

By default, Tach assumes that you will manage all cross-module dependencies explicitly. This is great for smaller projects, since tach.toml then provides centralized documentation on how modules fit together, but it is untenable for projects with 100s of interdependent modules.

Layers are a lightweight alternative approach. Tach supports an arbitrary number of ‘vertically stacked’ layers, which could be “API”, “Product”, “Platform”, and “Persistence” for example. The only rule in a layered architecture is: dependencies point downward.

This is often a much more practical architecture to adopt, since it requires far less configuration maintenance (no need to tach sync for every new dependency) and is much easier for developers to reason about if they run into an error in CI.

Distributed Configuration - Teams own their Modules

In most cases, Tach is used with a single tach.toml file in the root of a project. This file defines all modules, interfaces, layers, and other rules which apply throughout the codebase.

The centralization is useful for smaller projects, since every detail can be seen at-a-glance. When many teams work on the same project though, this model is prone to merge conflicts and configuration drift.

Tach now supports splitting out module and interface configuration into tach.domain.toml files which live alongside the associated source code. This means teams can use tools like CODEOWNERS to maintain their own Tach configuration. Since these files are also much shorter and have a specific context, they serve as better documentation for other developers.

Pragmatic Progress

Taming the complexity of a legacy codebase is daunting, and an incremental approach is often the best option. Tach lets you start with permissive configuration, and gradually ratchet up toward a well-defined modular monolith.