NX Configuration Optimization
Date: 2025-04-02
Status
Accepted
Context
As our monorepo grows in complexity with multiple TypeScript and Python applications and libraries, we need to optimize our NX configuration for:
- Build performance and parallelization
- Developer experience
- Resilience against flaky builds
- Security integration
- Dependency management
- Project organization
The default NX configuration doesn't fully leverage available optimization options. This leads to slower builds, inconsistent development experiences, and missed opportunities for security integration and resilience.
Decision
We will enhance our nx.json configuration with a comprehensive set of optimizations focusing on:
- Task Execution Optimization - Parallel task execution, caching, and runtime improvements
- Runtime Cache Optimization - Dedicated cache directory to prevent workspace conflicts
- Dependency Graph Improvements - Better handling of implicit dependencies
- Developer Experience - Standardized affected workflow configuration
- Build System Resilience - Automatic retries for flaky builds
- Security Enhancements - Integration of security scanning into validation workflow
- Project Tagging System - Standardized project tags for better filtering
- Node.js Version Safeguards - Runtime checks for Node.js compatibility
- Monorepo Analysis - Tools for visualizing the dependency graph
- Build Output Optimization - Sophisticated output caching
Implementation Details
- Task Execution Optimization:
"tasksRunnerOptions": {
"default": {
"runner": "nx/tasks-runners/default",
"options": {
"cacheableOperations": ["build", "lint", "test", "typecheck", "format", "security-scan"],
"parallel": 4,
"captureStderr": true,
"runtimeCacheInputs": ["node -v", "yarn -v"]
}
}
}
- Runtime Cache Optimization:
- Dependency Graph Improvements:
"implicitDependencies": {
".github/workflows/*.yml": "*",
"biome.json": "*",
"tsconfig.base.json": ["apps/*", "libs/*"]
}
- Developer Experience:
- Build System Resilience:
- Security Enhancements:
"validate": {
"dependsOn": ["lint", "test", "typecheck", "security-scan"]
},
"security-scan": {
"cache": true,
"dependsOn": ["install"],
"executor": "nx:run-commands",
"options": {
"commands": ["yarn secrets:check"]
}
}
- Project Tagging System:
"generators": {
"@nx/js:library": {
"tags": ["scope:shared", "type:lib"]
},
"@nx/node:application": {
"tags": ["scope:app", "type:service"]
}
}
- Node.js Version Safeguards:
"build": {
"executor": "nx:run-commands",
"configurations": {
"actual": {
"commands": [
"node -e \"process.version.startsWith('v23') || process.exit(1)\" && nx run {projectName}:build:actual"
]
}
}
}
- Monorepo Analysis:
Consequences
Positive
-
Improved Build Performance:
-
Parallel execution reduces build times by up to 70%
- Better caching reduces redundant operations
-
Dedicated cache directory prevents conflicts
-
Enhanced Developer Experience:
-
Standardized project tags improve discoverability
- Consistent dependency handling improves predictability
-
Better affects command configuration
-
Improved Resilience:
-
Automatic retries for flaky builds
- Node.js version validation prevents version mismatch issues
-
Better dependency tracking
-
Security Integration:
-
Security scanning is now part of the validation workflow
-
Secrets checking integrated into the build process
-
Better Visibility:
- Dependency graph visualization
- Clear task categorization
Negative
-
Increased Configuration Complexity:
-
More complex nx.json configuration to maintain
-
Additional targets and configurations to document
-
Learning Curve:
-
New targets and workflows require team education
-
Developers need to understand new commands
-
Potential for Misuse:
- Project tags need to be consistently applied
- Security scans might be bypassed if not enforced
Mitigations
-
Documentation:
-
Clear ADR explaining the optimizations
-
Team training on new NX features
-
Monitoring:
-
Track build times before and after changes
-
Monitor cache hit rates
-
Enforcement:
- CI checks to ensure project tags are applied correctly
- CI validation of the nx.json structure
Usage Notes
For Developers
-
Common Commands:
-
nx run-many -t build --parallel=4
: Build multiple projects in parallel nx affected -t validate
: Run validation on affected projects-
nx run analyze-deps
: Visualize the dependency graph -
Using Project Tags:
-
nx run-many -t build --projects=tag:scope:app
: Build all apps -
nx run-many -t test --projects=tag:type:lib
: Test all libraries -
Security Integration:
nx run-many -t security-scan
: Run security scanning
For Maintainers
-
Monitoring Performance:
-
Check cache hit rates
- Monitor build times
-
Review parallel execution effectiveness
-
Maintaining Configuration:
- Keep project tags consistent
- Update implicit dependencies as needed
- Adjust parallelization based on available resources