Configuration

Rule Packs

Pre-built rule configurations for common tech stacks. Install a rule pack to get production-ready radar.yml and rules.yml files in seconds.

Rule Packs

Rule packs are pre-built configurations that bundle a radar.yml template and a complete rules.yml for a specific tech stack and architecture pattern. Instead of writing configuration from scratch, install a pack and customize from there.

# List available packs
radar pack list

# Install a pack
radar pack install nestjs-prisma-ddd-strict

# Search packs by keyword
radar pack search performance

Built-in Packs

Technical Debt Radar ships with 10 built-in rule packs:

PackStackArchitectureStrictness
nestjs-prisma-ddd-strictNestJS + PrismaDDDStrict
nestjs-prisma-ddd-relaxedNestJS + PrismaDDDRelaxed
nestjs-typeorm-feature-moduleNestJS + TypeORMFeature-ModuleStandard
express-sequelize-layeredExpress + SequelizeLayeredStandard
express-mongoose-mvcExpress + MongooseMVCStandard
fastify-prisma-cleanFastify + PrismaCleanStandard
nestjs-starterNestJS (any ORM)NoneMinimal
node-api-securityAny Node.jsAnySecurity-focused
performance-focusedAnyAnyPerformance-focused
reliability-focusedAnyAnyReliability-focused

Pack Details

nestjs-prisma-ddd-strict

Full architecture enforcement for NestJS + Prisma with Domain-Driven Design. Zero-tolerance policy: any layer violation, circular dependency, or critical runtime risk blocks the merge.

Tags: nestjs, prisma, ddd, typescript, strict

Generated layers:

layers:
  - name: api
    path: "src/**/controllers/**"
  - name: application
    path: "src/**/use-cases/**"
  - name: domain
    path: "src/**/domain/**"
  - name: infrastructure
    path: "src/**/infra/**"

Architecture rules:

  • deny: domain -> infrastructure -- Domain must not depend on infrastructure
  • deny: domain -> api -- Domain must not depend on API/controllers
  • deny: domain -> application -- Domain must not import from application layer
  • deny: api -> infrastructure -- Controllers must not directly access infrastructure
  • deny: cross-module direct imports -- No direct cross-module imports
  • allow: cross-module through src/**/contracts/** -- Cross-module through contracts only

Gate thresholds:

GateThreshold
architecture_violations> 0 (blocks)
circular_dependencies_introduced> 0 (blocks)
runtime_risk_critical> 0 (blocks)
reliability_critical> 0 (blocks)
critical_performance_risk> 0 (blocks)
debt_delta_score> 15 (blocks)
complexity_increase> 5 (warns)

Best for: Mature teams with established DDD practices who want strict enforcement from day one.


nestjs-prisma-ddd-relaxed

Same DDD architecture rules as the strict pack but with relaxed gate thresholds. Violations produce warnings instead of blocks, giving teams time to clean up existing debt.

Tags: nestjs, prisma, ddd, typescript, relaxed

Key differences from strict:

GateStrictRelaxed
architecture_violations> 0 (blocks)> 3 (blocks)
circular_dependencies_introduced> 0 (blocks)> 1 (blocks)
reliability_critical> 0 (blocks)> 2 (blocks)
critical_performance_risk> 0 (blocks)> 1 (blocks)
debt_delta_score> 15 (blocks)> 30 (blocks)
complexity_increase> 5 (warns)> 10 (warns)

Best for: Teams adopting DDD incrementally. Start with relaxed, tighten thresholds as violations decrease. Migrate to strict once your codebase is clean.


nestjs-typeorm-feature-module

Co-located feature modules -- the most common NestJS pattern. Each module owns its controller, service, entity, and DTOs. Cross-module imports are allowed through shared code, entities, interfaces, and NestJS module files.

Tags: nestjs, typeorm, feature-module, typescript

Generated layers:

layers:
  - name: controllers
    path: "src/**/*.controller.ts"
  - name: services
    path: "src/**/*.service.ts"
  - name: entities
    path: "src/**/*.entity.ts"
  - name: shared
    path: "src/shared/**"

Architecture rules:

  • deny: cross-module direct imports -- Feature modules must not directly import from each other
  • allow: cross-module through src/shared/** -- Cross-module through shared module

Best for: Teams using the default NestJS CLI scaffold with TypeORM. No strict layers, pragmatic cross-module boundaries.


express-sequelize-layered

Classic layered architecture for Express backends with Sequelize ORM. Enforces a strict Controller -> Service -> Repository flow with downward-only dependencies.

Tags: express, sequelize, layered, typescript, javascript

Generated layers:

layers:
  - name: routes
    path: "src/routes/**"
  - name: controllers
    path: "src/controllers/**"
  - name: services
    path: "src/services/**"
  - name: repositories
    path: "src/repositories/**"
  - name: models
    path: "src/models/**"

Architecture rules:

  • deny: models -> controllers -- Models must not depend on controllers
  • deny: models -> services -- Models must not depend on services
  • deny: repositories -> controllers -- Repositories must not depend on controllers
  • deny: services -> controllers -- Services must not depend on controllers
  • deny: services -> routes -- Services must not depend on routes
  • deny: controllers -> repositories -- Controllers must use services, not repositories directly

Best for: Express projects with a traditional layered structure. Prevents common mistakes like controllers querying the database directly or models importing from controllers.


express-mongoose-mvc

Classic MVC pattern for Express + Mongoose stacks. Models are independent, controllers orchestrate views and models.

Tags: express, mongoose, mvc, typescript, javascript, mongodb

Generated layers:

layers:
  - name: routes
    path: "src/routes/**"
  - name: controllers
    path: "src/controllers/**"
  - name: models
    path: "src/models/**"
  - name: views
    path: "src/views/**"
  - name: middleware
    path: "src/middleware/**"

Architecture rules:

  • deny: models -> controllers -- Models must not depend on controllers
  • deny: models -> views -- Models must not depend on views
  • deny: models -> routes -- Models must not depend on routes
  • deny: views -> controllers -- Views must not depend on controllers

Best for: Express + Mongoose projects following the MVC pattern, including server-rendered applications and REST APIs with MongoDB.


fastify-prisma-clean

Clean Architecture for Fastify + Prisma backends. Strict concentric dependency rule: inner layers never depend on outer layers.

Tags: fastify, prisma, clean, typescript

Generated layers:

layers:
  - name: domain
    path: "src/domain/**"
  - name: use-cases
    path: "src/use-cases/**"
  - name: adapters
    path: "src/adapters/**"
  - name: infrastructure
    path: "src/infrastructure/**"
  - name: routes
    path: "src/routes/**"

Architecture rules:

  • deny: domain -> use-cases -- Domain must not depend on use cases
  • deny: domain -> adapters -- Domain must not depend on adapters
  • deny: domain -> infrastructure -- Domain must not depend on infrastructure
  • deny: domain -> routes -- Domain must not depend on routes
  • deny: use-cases -> adapters -- Use cases must not depend on adapters
  • deny: use-cases -> infrastructure -- Use cases must not depend on infrastructure
  • deny: use-cases -> routes -- Use cases must not depend on routes

Best for: Teams choosing Fastify for performance and wanting strict architectural boundaries. The layer structure ensures domain purity and framework independence.


nestjs-starter

Minimal rule set for NestJS projects. Basic runtime safety and reliability rules with relaxed gates. No architecture rules -- just catches dangerous patterns.

Tags: nestjs, typescript, starter, minimal

Generated layers:

layers:
  - name: controllers
    path: "src/**/*.controller.ts"
  - name: services
    path: "src/**/*.service.ts"

Key characteristics:

  • No architecture rules (no layer boundary enforcement)
  • Most dangerous runtime rules still block (sync-fs-in-handler, sync-crypto, busy-wait-loop, unhandled-promise)
  • Some runtime rules moved to warn (sync-compression, redos-vulnerable-regex)
  • Reduced performance rule set (4 rules instead of 8)
  • Relaxed gates: only runtime_risk_critical > 0 and debt_delta_score > 30 block

Gate thresholds:

GateThresholdAction
runtime_risk_critical> 0Block
debt_delta_score> 30Block
architecture_violations> 0Warn
complexity_increase> 10Warn
debt_delta_score> 15Warn

Best for: New projects or teams just starting with Technical Debt Radar. Catches the most dangerous patterns without overwhelming the team with violations. Upgrade to a stricter pack once the team is comfortable.


node-api-security

Security-focused rule pack for any Node.js API. All synchronous operations blocked, ReDoS detection enabled, strict runtime enforcement. Architecture rules are intentionally relaxed to focus entirely on security.

Tags: security, node, api, typescript, javascript, redos, owasp

Key characteristics:

  • All runtime rules that can cause DoS are promoted to block (including unbounded-json-parse and dynamic-buffer-alloc)
  • Reliability rules promoted to block: missing-try-catch, external-call-no-timeout, empty-catch-block
  • No architecture rules
  • Elevated scoring: runtime_risk_critical: 12, reliability_critical: 8

Runtime rules (block):

runtime_rules:
  block:
    - sync-fs-in-handler
    - sync-crypto
    - sync-compression
    - redos-vulnerable-regex
    - busy-wait-loop
    - unhandled-promise
    - unbounded-json-parse      # promoted from warn
    - dynamic-buffer-alloc      # promoted from warn
  warn:
    - large-json-stringify
    - cpu-heavy-loop-in-handler
    - unbounded-array-operation

Reliability rules (block):

reliability_rules:
  block:
    - unhandled-promise-rejection
    - missing-try-catch           # promoted from warn
    - external-call-no-timeout    # promoted from warn
    - empty-catch-block           # promoted from warn
  warn:
    - retry-without-backoff
    - missing-error-logging
    - transaction-no-timeout
    - missing-null-guard

Best for: Public-facing APIs, financial services, healthcare, or any system where a ReDoS or event loop block is a security incident. Combine with an architecture pack by installing this pack, then manually adding architecture rules.


performance-focused

Performance-focused rule pack. Every ORM anti-pattern is detected. N+1 queries and unbounded queries always block. Architecture and runtime rules are relaxed.

Tags: performance, orm, n-plus-one, pagination, typescript, javascript

Key characteristics:

  • All 8 performance rules enabled
  • Only critical_performance_risk > 0 blocks merges
  • Runtime and architecture violations produce warnings instead of blocks
  • Elevated scoring: performance_risk_critical: 12, performance_risk_warning: 5

Gate thresholds:

GateThresholdAction
critical_performance_risk> 0Block
debt_delta_score> 15Block
architecture_violations> 0Warn
runtime_risk_critical> 0Warn
complexity_increase> 5Warn

Best for: Teams with large datasets where performance is the primary concern. Database-heavy applications (analytics, reporting, e-commerce with millions of products) where a missing LIMIT clause can take down production.


reliability-focused

Reliability-focused rule pack. All reliability rules block merges: unhandled rejections, missing try-catch, missing timeouts, null guards. No warnings -- everything is a blocker.

Tags: reliability, error-handling, timeouts, null-safety, typescript, javascript

Key characteristics:

  • All 8 reliability rules promoted to block (zero in warn)
  • Architecture and performance violations produce warnings instead of blocks
  • Elevated scoring: reliability_critical: 10, reliability_warning: 5

Reliability rules (all block):

reliability_rules:
  block:
    - unhandled-promise-rejection
    - missing-try-catch
    - external-call-no-timeout
    - retry-without-backoff
    - empty-catch-block
    - missing-error-logging
    - transaction-no-timeout
    - missing-null-guard
  warn: []    # Everything blocks

Gate thresholds:

GateThresholdAction
reliability_critical> 0Block
runtime_risk_critical> 0Block
debt_delta_score> 15Block
architecture_violations> 0Warn
critical_performance_risk> 0Warn

Best for: Mission-critical services where uptime is paramount. Payment processing, infrastructure services, or any system where an unhandled error means lost revenue or data.


Installing a Pack

Interactive Installation

radar pack install

When run without a pack name, the CLI presents an interactive selection menu filtered by your detected stack.

Direct Installation

radar pack install nestjs-prisma-ddd-strict

This generates two files:

  • radar.yml -- populated with the pack's layer definitions (customize paths to match your project)
  • rules.yml -- complete enforcement rules, gates, and scoring

Warning: Installing a pack overwrites existing radar.yml and rules.yml files. Back up your configuration first, or use --dry-run to preview changes.

Dry Run

radar pack install nestjs-prisma-ddd-strict --dry-run

Prints the generated configuration to stdout without writing files.


Searching Packs

List All Packs

radar pack list

Output:

  nestjs-prisma-ddd-strict       NestJS + Prisma + DDD (Strict)
  nestjs-prisma-ddd-relaxed      NestJS + Prisma + DDD (Relaxed)
  nestjs-typeorm-feature-module   NestJS + TypeORM + Feature-Module
  express-sequelize-layered       Express + Sequelize + Layered
  express-mongoose-mvc            Express + Mongoose + MVC
  fastify-prisma-clean            Fastify + Prisma + Clean Architecture
  nestjs-starter                  NestJS Starter
  node-api-security               Node API Security Focus
  performance-focused             Performance Focus
  reliability-focused             Reliability Focus

Search by Keyword

radar pack search prisma

Searches pack names, display names, tags, and descriptions.

Filter by Stack

radar pack search --framework NestJS --orm Prisma

Returns packs matching the specified framework and ORM.


Pack Selection Guide

Use this decision tree to pick the right pack:

What is your framework?

  • NestJS + Prisma:
    • Team has DDD experience -> nestjs-prisma-ddd-strict
    • Adopting DDD incrementally -> nestjs-prisma-ddd-relaxed
    • No architecture yet -> nestjs-starter
  • NestJS + TypeORM:
    • Feature-module structure -> nestjs-typeorm-feature-module
    • No architecture yet -> nestjs-starter
  • Express + Sequelize:
    • Layered structure -> express-sequelize-layered
  • Express + Mongoose:
    • MVC structure -> express-mongoose-mvc
  • Fastify + Prisma:
    • Clean Architecture -> fastify-prisma-clean

Cross-cutting concerns:

  • Security is top priority -> node-api-security (combine with architecture pack)
  • Performance is top priority -> performance-focused (combine with architecture pack)
  • Reliability is top priority -> reliability-focused (combine with architecture pack)

Customizing After Installation

After installing a pack, you own the generated files. Common customizations:

Adjust Layer Paths

The pack generates generic paths. Update them to match your project:

# Generated
layers:
  - name: api
    path: "src/**/controllers/**"

# Customized for your project
layers:
  - name: api
    path: "apps/backend/src/**/controllers/**"

Add Modules

Packs don't generate module definitions (they're project-specific):

# Add after pack installation
modules:
  - name: billing
    path: "src/billing/**"
  - name: identity
    path: "src/identity/**"

Adjust Gate Thresholds

Tighten or relax thresholds based on your team's tolerance:

gates:
  block_merge:
    - architecture_violations > 0    # Keep strict
    - debt_delta_score > 25          # Was 15, relaxed for migration period

Add Exceptions

Add temporary exceptions for existing violations:

exceptions:
  - rule: "domain -> infrastructure"
    file: "src/billing/domain/legacy-adapter.ts"
    expires: "2026-06-01"
    reason: "Legacy migration — tracked in JIRA-1234"

Combine Cross-Cutting Packs

To combine a security or performance pack with an architecture pack, install the architecture pack first, then manually merge rules from the cross-cutting pack:

# Step 1: Install architecture pack
radar pack install nestjs-prisma-ddd-strict

# Step 2: View the security pack
radar pack install node-api-security --dry-run

# Step 3: Manually merge security-specific rules into your rules.yml
# - Promote unbounded-json-parse and dynamic-buffer-alloc to block
# - Promote missing-try-catch, external-call-no-timeout, empty-catch-block to block
# - Increase runtime_risk_critical scoring to 12

Creating Custom Packs

Custom packs follow the same structure as built-in packs. Create a TypeScript file that exports a RulePack object:

// my-custom-pack.ts
import { RulePack } from '@radar/shared';
import { DEFAULT_SCORING } from '@radar/shared';

export const myCustomPack: RulePack = {
  name: 'my-company-standard',
  displayName: 'My Company Standard',
  description: 'Company-wide engineering standards for all Node.js services.',
  version: '1.0.0',
  author: 'Platform Team',
  tags: ['company', 'standard', 'nestjs', 'typescript'],
  stack: {
    framework: 'NestJS',
    orm: 'Prisma',
    language: 'TypeScript',
    architecture: 'DDD',
  },
  radarConfig: {
    stack: {
      framework: 'NestJS',
      orm: 'Prisma',
      language: 'TypeScript',
      runtime: 'node',
    },
    architecture: 'ddd',
    layers: [
      { name: 'api', path: 'src/**/controllers/**' },
      { name: 'application', path: 'src/**/use-cases/**' },
      { name: 'domain', path: 'src/**/domain/**' },
      { name: 'infrastructure', path: 'src/**/infra/**' },
    ],
  },
  rulesConfig: {
    architecture_rules: [
      {
        type: 'deny',
        source: 'domain',
        target: 'infrastructure',
        description: 'Domain must not depend on infrastructure',
      },
      // ... your rules
    ],
    runtime_rules: {
      block: [
        'sync-fs-in-handler',
        'sync-crypto',
        'sync-compression',
        'redos-vulnerable-regex',
        'busy-wait-loop',
        'unhandled-promise',
      ],
      warn: [
        'unbounded-json-parse',
        'large-json-stringify',
        'cpu-heavy-loop-in-handler',
      ],
    },
    reliability_rules: {
      block: ['unhandled-promise-rejection', 'missing-try-catch'],
      warn: [
        'external-call-no-timeout',
        'empty-catch-block',
        'missing-error-logging',
      ],
    },
    performance_rules: [
      'unbounded-find-many',
      'n-plus-one-query',
      'fetch-all-filter-in-memory',
    ],
    gates: {
      block_merge: [
        { metric: 'architecture_violations', operator: '>', value: 0 },
        { metric: 'runtime_risk_critical', operator: '>', value: 0 },
        { metric: 'debt_delta_score', operator: '>', value: 20 },
      ],
      warn: [
        { metric: 'complexity_increase', operator: '>', value: 8 },
        { metric: 'debt_delta_score', operator: '>', value: 10 },
      ],
    },
    scoring: { ...DEFAULT_SCORING },
    exceptions: [],
  },
};

RulePack Interface

FieldTypeRequiredDescription
namestringYesUnique pack identifier (kebab-case)
displayNamestringYesHuman-readable name
descriptionstringYesWhat the pack does and who it's for
versionstringYesSemver version
authorstringYesPack author
tagsstring[]YesSearchable tags
stackobjectYesStack requirements (framework, orm, language, architecture)
radarConfigobjectYesPartial radar.yml template (stack, architecture, layers)
rulesConfigobjectYesComplete rules.yml content

Tip: Use DEFAULT_SCORING from @radar/shared as your base scoring, then override specific weights. This ensures forward compatibility when new scoring keys are added.

Technical Debt Radar Documentation