The Code Organization Crisis
Before exploring Turborepo solutions, let's understand why code organization matters and how companies typically fail at it.The Polyrepo Problem
Most companies start with polyrepo: separate Git repository for each application, library, or service.Example polyrepo structure:- web-app (customer-facing website)
- mobile-app (iOS/Android applications)
- admin-dashboard (internal tools)
- shared-ui-library (React components)
- shared-utils-library (helper functions)
- api-gateway (backend services)
- auth-service (authentication microservice)
- payment-service (payment processing)
- Clear ownership boundaries (each team owns their repo)
- Independent deployment (ship web app without touching mobile)
- Simple access control (restrict who can commit to what)
- Standard Git workflows (familiar to all developers)
- Dependency Hell
- Update web app to use 2.0
- Update mobile app to use 2.0
- Update admin dashboard to use 2.0
- Coordinate three separate PRs across three repos
- Manage version mismatches if one app doesn't update
- Code Duplication
- Authentication logic (copied with slight variations)
- API client code (duplicated across web and mobile)
- Configuration files (similar ESLint, TypeScript configs repeated)
- CI/CD pipelines (nearly identical GitHub Actions across repos)
- Cross-Repo Changes Are Painful
- Update API service (one repo)
- Update frontend to match (another repo)
- Update mobile app (third repo)
- Update documentation (fourth repo)
- Create 4 PRs, wait for 4 CI runs, coordinate 4 merges
- Inconsistent Tooling
- Node.js versions (web app uses 18, mobile uses 16)
- Package managers (some use npm, others yarn, others pnpm)
- Linting rules (different ESLint configs)
- Testing frameworks (Jest vs Vitest vs Mocha)
The Basic Monorepo Problem
Companies recognize polyrepo problems and consolidate into a monorepo: single Git repository containing all projects.Structure:monorepo/ apps/ web/ mobile/ admin/ packages/ ui-library/ utils/ api-client/ services/ api-gateway/ auth-service/Advantages:- Atomic changes (single PR updates API and all consumers)
- Shared tooling (one ESLint config, one TypeScript config)
- No version synchronization (packages always use latest)
- Easier refactoring (find all usages across entire codebase)
- Slow Builds
- Rebuild of UI library (2 minutes)
- Rebuild of web app (5 minutes)
- Rebuild of mobile app (8 minutes)
- Rebuild of admin dashboard (4 minutes)
- Total: 19 minutes for one-line change
- Inefficient CI
- Test all packages (15 minutes)
- Test all apps (30 minutes)
- Lint everything (5 minutes)
- Total CI time: 50 minutes per PR
- No Incremental Computation
- No caching of unchanged packages
- No parallelization across projects
- No awareness of dependency graph
Turborepo: The Enterprise Solution
Turborepo solves monorepo scaling problems through three core concepts: intelligent caching, task orchestration, and dependency-aware builds.Core Concept 1: Remote Caching
Turborepo caches task outputs (builds, tests, lints) and shares them across machines.How it works:- Developer A runs build command
- Turborepo executes build, caches output
- Developer B pulls latest code (same as Developer A had)
- Developer B runs build command
- Turborepo retrieves cached output instead of rebuilding
- Build completes in 0.5 seconds instead of 5 minutes
| Scenario | Without Turborepo | With Turborepo |
| Fresh checkout, run tests | 18 minutes | 18 minutes (first run) |
| Teammate runs same tests | 18 minutes | 2 seconds (cache hit) |
| CI runs on unchanged code | 18 minutes | 2 seconds (cache hit) |
Core Concept 2: Task Orchestration
Turborepo understands your project dependencies and runs tasks in optimal order.Example dependency graph:- web depends on ui-library
- mobile depends on ui-library
- ui-library depends on utils
- Build utils (no dependencies)
- Build ui-library (depends on utils)
- Build web and mobile in parallel (both depend on ui-library)
Core Concept 3: Incremental Builds
Turborepo only rebuilds what changed.Scenario: You modify mobile app (nothing else).Turborepo behavior:- Skip building utils (unchanged, use cache)
- Skip building ui-library (unchanged, use cache)
- Skip building web (unchanged, use cache)
- Build only mobile (2 minutes)
Real-World Implementation: Enterprise SaaS Company
Client profile:- 80 engineers across 5 teams
- 25 applications (web apps, mobile apps, microservices)
- 40 shared packages (component library, utilities, API clients)
- Polyrepo structure (65 separate repositories)
- 3-4 hours per week managing dependency updates
- 45-minute average CI time blocking PRs
- Inconsistent tooling causing onboarding delays
- Feature velocity decreasing (shipping 30% fewer features than 12 months prior)
- Developer satisfaction dropping (40% considering leaving due to tooling frustration)
- Cross-team collaboration difficult (shared code changes required coordinating 5-8 repos)
Migration to Turborepo Monorepo
Phase 1: Planning and Structure (2 weeks)Designed monorepo structure:enterprise-monorepo/ apps/ customer-portal/ merchant-dashboard/ admin-tools/ mobile-ios/ mobile-android/ packages/ ui-components/ api-client/ utils/ types/ services/ api-gateway/ auth-service/ payment-service/ notification-service/Phase 2: Migration (6 weeks)Migrated repositories incrementally:- Week 1-2: Core shared packages
- Week 3-4: Customer-facing apps
- Week 5-6: Internal tools and services
- build tasks depend on dependencies being built first
- test tasks depend on local build completing
- lint can run independently
- deploy requires build, test, and lint completion
- Developers authenticate with cache
- CI/CD authenticates with cache
- All build/test outputs cached remotely
Results After 6 Months
Build Performance:| Metric | Before (Polyrepo) | After (Turborepo) | Improvement |
| Local build time | 12 minutes | 2 minutes (90% cache hit) | 83% faster |
| CI time (unchanged code) | 45 minutes | 3 minutes (cache hit) | 93% faster |
| CI time (changed code) | 45 minutes | 12 minutes (parallel + incremental) | 73% faster |
| Developer wait time/week | 6 hours | 1.5 hours | 75% reduction |
| Metric | Before | After | Improvement |
| Cross-repo changes (time) | 4 hours | 30 minutes | 87% faster |
| Dependency updates (time) | 3 hours | 20 minutes | 89% faster |
| Onboarding new developers | 5 days | 1 day | 80% faster |
| Features shipped per sprint | 12 | 19 | 58% increase |
- CI compute costs: $8,200/month reduced to $2,400/month (71% reduction)
- Developer time saved: 360 hours/month (equivalent to 2 full-time engineers)
- Value: $72,000/month in productivity gains
Turborepo Configuration Best Practices
1. Pipeline Definition
Structure your pipeline to maximize parallelization:Good pipeline (parallel where possible):{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**", ".next/**"] }, "test": { "dependsOn": ["build"] }, "lint": {}, "type-check": {} }}lint and type-check run in parallel because they don't depend on each other.Bad pipeline (unnecessary serialization):{ "pipeline": { "build": { "dependsOn": ["^build", "lint", "type-check"] } }}This forces lint and type-check to complete before build starts, even though they're independent.2. Cache Configuration
Specify what files affect task outputs:{ "pipeline": { "build": { "dependsOn": ["^build"], "inputs": ["src/**", "package.json", "tsconfig.json"], "outputs": ["dist/**"] } }}Turborepo only invalidates cache when inputs change. Changing README.md doesn't trigger rebuild.3. Remote Cache Strategy
For teams under 50 developers: Vercel Remote Cache (free tier sufficient)For larger teams: Self-hosted cache (AWS S3, Google Cloud Storage)Setup with AWS S3:# Configure environment variablesTURBO_API=https://your-cache-endpointTURBO_TOKEN=your-auth-tokenTURBO_TEAM=your-team-idCache hit rate target: 80%+ (means 80% of builds use cache instead of rebuilding)4. Workspace Organization
Apps vs Packages:- apps/: Deployable applications (websites, mobile apps, services)
- packages/: Shared libraries (not deployed independently)
When Turborepo Makes Sense
Ideal Candidates
- Multiple related applications (web, mobile, admin sharing code)
- 10+ developers (small teams may not justify setup complexity)
- Shared component libraries used across apps
- Frequent cross-project changes (API + frontend updates together)
- Microservices architecture (many services with shared types/utilities)
- CI taking 20+ minutes without caching
- SaaS companies with customer app, merchant dashboard, admin tools
- eCommerce platforms with storefront, admin, mobile apps, backend services
- Fintech companies with web app, mobile apps, API gateway, payment services
- Agencies managing multiple client projects with shared component library
Not a Good Fit
- Completely unrelated projects (consulting firm with 20 different client apps)
- Very small teams (1-3 developers) (overhead not worth it)
- Projects using different tech stacks (Python backend + React frontend + mobile apps in different languages)
- Strong organizational boundaries (separate companies, strict IP separation)
- CI already fast (under 5 minutes) (optimization not needed)
Alternative Solutions
Nx (by Nrwl)
Similarities to Turborepo:- Monorepo build system
- Remote caching
- Task orchestration
- More opinionated (generates code, enforces structure)
- Larger ecosystem (Nx plugins for Angular, React, Node.js)
- More complex (steeper learning curve)
- Better for Angular projects (created by Angular consulting firm)
Bazel (by Google)
What it is: Google's internal build system, open-sourced.Advantages:- Extremely powerful (builds anything, any language)
- Battle-tested at massive scale (Google's entire codebase)
- Very complex (steep learning curve)
- Requires significant DevOps investment
- Overkill for most companies
Lerna
What it is: Original JavaScript monorepo tool (2016).Status: Maintenance mode (community-maintained, not actively developed).Why Turborepo is better:- Lerna doesn't cache (slow)
- No task orchestration (no parallelization)
- No remote caching
Migration Strategies
Strategy 1: Big Bang Migration (4-8 weeks)
Move all repositories to monorepo simultaneously.Pros:- Fastest time to benefits
- No maintaining two systems simultaneously
- Risky (everything changes at once)
- Requires full team coordination
- Deployment freeze during migration
Strategy 2: Incremental Migration (3-6 months)
Migrate repos gradually while maintaining polyrepo temporarily.Phase 1: Core shared packages Phase 2: Less critical applications Phase 3: Customer-facing applications Phase 4: Backend servicesPros:- Lower risk (rollback if issues)
- Team learns gradually
- No deployment freeze
- Longer time to full benefits
- Maintaining two systems (polyrepo + partial monorepo)
Strategy 3: Hybrid Approach (Permanent)
Keep some repos separate, consolidate related projects.Example:- Monorepo 1: Customer-facing products (web, mobile, shared components)
- Monorepo 2: Backend services (microservices, shared utilities)
- Separate repos: Legacy applications, third-party integrations
Common Pitfalls and Solutions
Pitfall 1: Not Configuring Cache Properly
Problem: Low cache hit rates (under 50%) mean builds still slow.Causes:- Non-deterministic builds (outputs differ between runs)
- Missing cache inputs (not specifying which files matter)
- Too aggressive cache outputs (caching things that shouldn't be cached)
- Ensure builds are reproducible (same inputs = same outputs)
- Configure inputs explicitly in turbo.json
- Regularly monitor cache hit rates (Turborepo provides analytics)
Pitfall 2: Over-Shared Dependencies
Problem: Changing shared package triggers rebuilding 50 apps.Solution:- Keep shared packages focused (multiple small packages vs one large package)
- Use dependency inversion (apps depend on interfaces, not implementations)
- Consider if code really needs to be shared (sometimes duplication is better)
Pitfall 3: Ignoring CI Optimization
Problem: Turborepo speeds up local development but CI still slow.Solution:- Configure remote cache in CI (don't rebuild what's already built)
- Use GitHub Actions cache or similar
- Split CI jobs (lint in parallel with tests)
Pitfall 4: Poor Package Boundaries
Problem: Circular dependencies between packages.Example:- ui-components imports from utils
- utils imports from ui-components
- Build fails due to circular dependency
- Enforce one-way dependencies (packages depend on more primitive packages, not siblings)
- Use Turborepo's dependency graph visualization to catch cycles
- Consider splitting packages differently
Key Takeaways
- Monorepos with Turborepo deliver 70-85% faster builds through intelligent caching and parallelization
- Remote caching is the killer feature saving 400+ developer hours monthly for 50-person teams
- Polyrepo causes dependency hell and duplication that compounds as codebases grow
- Basic monorepos without tooling are too slow (45-minute CI times kill productivity)
- Turborepo simpler than alternatives (Nx more opinionated, Bazel more complex)
- ROI positive within 3-4 months for teams of 20+ developers
- Not suitable for all organizations (small teams, unrelated projects better in polyrepo)
How Askan Technologies Implements Turborepo
We've migrated 15+ enterprise organizations from polyrepo to Turborepo monorepo, reducing build times 70-85% and improving developer productivity 40%.Our Monorepo Migration Services:- Monorepo Assessment: Analyze your repos and determine if monorepo makes sense
- Architecture Design: Structure apps, packages, and services optimally
- Migration Execution: Move repositories with Git history preservation
- Turborepo Configuration: Set up pipelines, caching, and CI/CD integration
- Team Training: Hands-on workshops for developers and DevOps
- Performance Optimization: Tune cache hit rates, parallelization, and task orchestration
- SaaS company (80 engineers, 25 apps): 83% faster builds, 58% more features shipped
- eCommerce platform (40 engineers, 15 apps): 73% CI time reduction, $70K monthly savings
- Fintech startup (25 engineers, 12 services): 89% faster dependency updates





Monorepo Strategies with Turborepo: Managing Enterprise Codebases at Scale
Enterprise engineering organizations face a fundamental code organization challenge: as applications grow from 5 projects...
Share this link via
Or copy link