Engineering Quality
How do you know the codebase is healthy — not from reading the code, but from measuring it?
Every threshold below is pass/fail. If a number is above threshold, the system is degrading and the fix has higher priority than new features. These benchmarks parallel the UI Design thresholds but measure structural and runtime health of the code itself.
Benchmark Context
Use this page with Performance to connect engineering quality gates to business outcomes. A codebase that passes these thresholds ships faster, breaks less, and costs less to change.
STANDARDS (this page) → defines "module count < 200 per route"
↓
BUILD (best practices) → developer follows checklists
↓
DETECT (anti-patterns) → catch violations before they compound
↓
MEASURE (metrics) → track trends over time
↓
IMPROVE → update the standard
Module Budget
Every page has a practical ceiling. Exceeding it degrades dev-server startup, HMR speed, and production bundle size.
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 1.1 | Modules per route | <= 200 | next build output or custom module count script |
| 1.2 | No single import pulls entire dependency graph | 0 transitive barrel blowouts | Trace import chain from page to leaf |
| 1.3 | Module count trend | Flat or declining per sprint | Track per-route counts in CI |
Root cause of blowout is almost always a barrel import from a composition library that transitively pulls everything into every page that touches it.
Bundle Size
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 2.1 | Initial page load | <= 1MB transfer size | Network tab, throttled to 3G |
| 2.2 | JavaScript per route | <= 200KB gzipped | next build output per page |
| 2.3 | No bundle regression | Size unchanged or reduced per deploy | CI diff against previous build |
| 2.4 | Tree-shaking verified | Unused exports not in production bundle | Bundle analyzer |
Type Safety
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 3.1 | Full monorepo typecheck passes | 0 errors on tsc --build | CI typecheck step |
| 3.2 | No any or @ts-ignore added | 0 new instances per PR | Grep diff for any and @ts-ignore |
| 3.3 | composite: true on all library tsconfigs | 100% compliance | Grep tsconfig.lib.json files |
| 3.4 | rootDir aligned with include | 0 mismatches | Compare fields in each tsconfig |
| 3.5 | No skipLibCheck: true in root config | Absent from tsconfig.base.json | Direct check |
TypeScript project references live or die by composite and rootDir alignment. Disabling them silences errors temporarily but creates cascading failures in CI.
Dependency Graph
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 4.1 | Layer boundaries enforced | 0 violations on nx lint | @nx/enforce-module-boundaries |
| 4.2 | eslint-disable count for boundary rules | Trending to 0 | Grep and count per PR |
| 4.3 | Every library has tags | 100% of project.json files have non-empty tags | Automated check |
| 4.4 | No wildcard dependency constraints | 0 "*" in onlyDependOnLibsWithTags | Grep eslint config |
| 4.5 | Domain depends on nothing external | 0 framework imports in domain layer | bannedExternalImports |
The dependency direction for hexagonal architecture: Composition → Application → Domain ← Infrastructure. Domain is the center. Everything points inward.
Barrel Hygiene
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 5.1 | No export * outside entry-points | 0 instances | Grep for export * excluding entry-points/ |
| 5.2 | Consumers use subpath imports | 0 root barrel imports from apps | no-restricted-imports lint rule |
| 5.3 | No nested internal barrels | 0 index.ts files in src/lib/*/ | Find internal re-export files |
| 5.4 | No cross-boundary src/ imports | 0 imports via ../libs/*/src/ paths | Grep for src/ path imports |
Barrels are not inherently bad — undisciplined barrels are. The rule: barrels as curated public API only, never as convenience re-exports.
Build Performance
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 6.1 | Full typecheck | <= 120 seconds | CI timing |
| 6.2 | Affected build | <= 60 seconds for typical PR | nx affected --target=build timing |
| 6.3 | Dev server cold start | <= 15 seconds | Local measurement |
| 6.4 | HMR update | <= 2 seconds | Local measurement |
| 6.5 | CI cache hit rate | >= 80% on non-first builds | Nx Cloud or CI cache stats |
Core Web Vitals
Runtime performance of shipped pages. See Next.js Performance for the full checklist.
| # | Check | Threshold | How to Measure |
|---|---|---|---|
| 7.1 | Largest Contentful Paint | <= 2.5s | Lighthouse |
| 7.2 | Interaction to Next Paint | <= 200ms | Lighthouse |
| 7.3 | Cumulative Layout Shift | <= 0.1 | Lighthouse |
| 7.4 | First Contentful Paint | <= 1.8s | Lighthouse |
| 7.5 | Total Blocking Time | <= 200ms | Lighthouse |
Enforcement Layers
Stack these so violations are caught progressively earlier. Each layer catches what the previous missed.
| Layer | What It Catches | When |
|---|---|---|
| ESLint module boundaries | Cross-layer imports, banned externals | IDE + build |
| ESLint import restrictions | Root barrel usage, src/ path imports | IDE + build |
| ESLint syntax restrictions | export * usage | IDE + build |
| Pre-commit hooks | Architecture grep checks, eslint-disable count | Before push |
| Full typecheck | TS6305, TS6059, TS2305 cascades | Before push / CI |
| Module count script | Per-page module budget regression | CI |
| Production build | Bundle size, tree-shaking verification | CI |
How This Works
| Concept | Application |
|---|---|
| Standard | This page defines "healthy codebase" in measurable terms |
| Protocol | Lint rules, CI checks, and audits recreate expected outcomes |
| Benchmark | A codebase passes with 0 violations across all 7 categories |
| Trigger | Any FAIL triggers a fix before shipping new features |
Context
- Engineering Anti-Patterns — What to detect and eradicate
- UI Design Benchmarks — Parallel thresholds for visual quality
- Next.js Performance — CWV checklist and optimization patterns
- Hexagonal Architecture — The structural pattern these benchmarks enforce
- Nx Monorepo — Build system and boundary tooling
- Software Development Metrics — Tracking trends over time