Tailwind's just-in-time engine has been the default compilation mode for a while now, and it's fast enough that most projects never think about it. A large, multi-team client application, dozens of contributors across several feature teams sharing one codebase, was the exception, and build times had crept up gradually enough that nobody noticed until a full rebuild was taking long enough to genuinely disrupt the local development loop.
Narrowing the content glob patterns to exclude generated files and third-party component directories cut our full rebuild time nearly in half, a reminder that JIT is fast, not magic, and still scans everything the config tells it to for class name matches. The default, broad glob pattern that ships in most starter configs had been quietly scanning a generated API client directory and a vendored component library that together accounted for tens of thousands of lines the engine never needed to look at, since neither contained a single actual Tailwind class.
Beyond the glob fix, we found real value in splitting the Tailwind config itself along team boundaries where the app's monorepo structure allowed it, letting feature teams that didn't share UI components avoid triggering a full rebuild for changes isolated to their own area. This wasn't a Tailwind-specific fix so much as applying a general monorepo build-scoping principle to a tool that hadn't previously needed it at a smaller scale.
We also audited the safelist, the mechanism for forcing Tailwind to generate classes it can't detect through static analysis, since dynamically constructed class names, common in a codebase this size with a few teams building similar-but-not-identical components independently, are invisible to JIT's content scanning by design. An overly broad safelist inherited from an early, cautious setup was quietly generating hundreds of unused utility classes into the final bundle; trimming it to the actual dynamic patterns still in use reduced final CSS bundle size noticeably alongside the build-time win.
The lesson generalizes past Tailwind specifically: any tool that scans a codebase to decide what to generate is only as fast as the scope you give it, and default configs are tuned for a typical project, not a large, multi-team one. Revisiting content globs and safelists as an application grows past its original scale assumptions is worth doing before build time becomes painful enough that it forces the conversation.
We also standardized how teams extend the shared Tailwind config, since a previous pattern of individual teams adding their own one-off theme values directly into the base config had quietly ballooned the configuration file itself into something nobody wanted to touch without checking with three other teams first. Moving team-specific extensions into clearly namespaced, individually owned config fragments that get merged at build time didn't change build performance directly, but it made the safelist and content-glob audits we'd just done far easier to keep accurate going forward, since it's now obvious which team owns which part of the configuration when something needs revisiting.
Editor performance came up as a related, if secondary, complaint worth mentioning. Tailwind's IntelliSense extension was also slowing down noticeably in the editor for developers working in the largest feature directories, and the same content-glob narrowing that fixed the build largely fixed this too, since the extension relies on similar scanning logic under the hood. It's a good reminder that a JIT-related performance problem rarely shows up in only one place once a codebase reaches this size.