Introduction
Technical Debt Radar is a PR safety gate that blocks architecture drift, event-loop blockers, and dangerous ORM patterns before they reach production.
Introduction
Technical Debt Radar is a PR merge gate for Node.js backends. It analyzes every pull request for architecture violations, runtime safety issues, and dangerous database patterns, then physically blocks the merge until violations are fixed.
It is not a suggestion engine. It is not a dashboard of recommendations you can ignore. It is enforcement --- the PR cannot merge until the code is safe.
Developer opens PR
→ Radar analyzes changed files (< 30 seconds)
→ Debt Report posted as PR comment
→ Merge blocked if policy violated
→ Developer fixes violations
→ PR passes → Merge allowed
The Problem
Modern codebases face three compounding risks that existing tools miss:
Architecture drift. Layer violations and circular dependencies creep in one PR at a time. A controller imports a repository directly. A domain model depends on an ORM entity. Six months later, the codebase is unmaintainable.
Event-loop blockers. fs.readFileSync in a request handler. crypto.pbkdf2Sync in an auth middleware. JSON.parse on unbounded user input. These work fine in development and cause cascading timeouts in production under load.
Dangerous ORM patterns. prisma.order.findMany() without pagination on a table with 2 million rows. N+1 queries inside a Promise.all. An unbounded SELECT * hidden behind a clean repository abstraction.
AI coding tools make this worse. Claude Code, Cursor, and Copilot generate syntactically correct code without awareness of your architecture rules, your data volumes, or the Node.js event loop. Radar catches what they miss.
How It Works
Radar uses a two-stage analysis pipeline:
┌─────────────────────────────────────────────────────────────┐
│ RADAR PIPELINE │
│ │
│ radar.yml + rules.yml │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Policy Engine │ Parse config → Compile rules │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Stage 1: Deterministic Analysis │ │
│ │ (7 AST analyzers running in parallel) │ │
│ │ │ │
│ │ Phase 1 (parallel): │ │
│ │ Import Graph · Complexity · Runtime Risk │ │
│ │ Performance · Reliability │ │
│ │ │ │
│ │ Phase 2 (needs import graph): │ │
│ │ Boundary Checker · Circular Detector │ │
│ └──────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Stage 2: AI Analysis (optional) │ │
│ │ Top 10 suspect functions → Claude API │ │
│ │ Cross-file reasoning · Fix suggestions │ │
│ └──────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Debt Score Calculator │ │
│ │ Violations → Points → Gate Decision │ │
│ │ debt_delta_score > 15 → BLOCK MERGE │ │
│ └──────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Output │ │
│ │ PR Comment · Status Check · CLI Report │ │
│ │ Dashboard Update · Badge │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Stage 1 is deterministic. Seven analyzers built on ts-morph parse your TypeScript and JavaScript AST. No network calls, no AI costs, no variability. This stage catches all violations with zero false positives.
Stage 2 is optional. When enabled, Radar sends the top 10 suspect functions to the Claude API for cross-file reasoning, contextual explanations, and fix suggestions. AI analysis never blocks merges --- it adds context to the deterministic findings.
The Six Debt Categories
Radar organizes violations into six categories, each with distinct enforcement behavior:
1. Architecture Debt --- Blocks Merge
Layer violations, circular dependencies, cross-module bypasses, and forbidden framework imports in domain layers. Detected using AST import analysis and Tarjan's algorithm.
// VIOLATION: domain layer importing from infrastructure
// File: src/orders/domain/order.service.ts
import { PrismaClient } from '@prisma/client'; // ← Architecture violation
2. Runtime Risk Debt --- Blocks on Critical
Synchronous I/O, sync crypto, ReDoS-vulnerable regex, busy-wait loops, and unbounded JSON parsing inside request handlers. Detection is scope-aware --- it only flags patterns inside HTTP handlers, guards, interceptors, and middleware, not in cron jobs or startup code.
// VIOLATION: sync file read in request handler
@Get('export')
async exportData() {
const template = fs.readFileSync('./template.html', 'utf-8'); // ← Blocks event loop
}
3. Performance Debt --- Blocks on XL/XXL Tables
N+1 queries, unbounded findMany calls, missing pagination, and raw SQL without LIMIT. Severity scales with the data volume you declare in radar.yml --- an unbounded query on a 10K-row table is a warning, but the same query on a 2M-row table blocks the merge.
// VIOLATION: unbounded query on XL table (1M+ rows)
const allEvents = await prisma.event.findMany(); // ← No take/skip, no where
4. Reliability Debt --- Blocks on Critical
Fire-and-forget promises, missing try/catch in use cases, HTTP calls without timeouts, empty catch blocks, and retry logic without exponential backoff.
// VIOLATION: fire-and-forget promise (unhandled rejection)
sendNotification(user.email); // ← No await, no .catch()
5. Maintainability Debt --- Warns (Configurable)
Cyclomatic complexity exceeding thresholds and oversized files or functions. Configurable severity --- you decide whether high complexity blocks merges or just warns.
6. AI Cross-File Analysis --- Advisory
When AI is enabled, Radar traces call paths across files to find violations hidden behind abstractions. A readFileSync buried in a utility function is invisible to per-file analysis but dangerous when called from a request handler. AI connects the dots.
Supported Stacks
Radar works with the most common Node.js backend stacks:
| Category | Supported |
|---|---|
| Frameworks | NestJS, Express, Fastify, Koa, Hapi |
| ORMs | Prisma, TypeORM, Sequelize, Mongoose, Drizzle, Knex, MikroORM |
| Languages | TypeScript, JavaScript (ES modules and CommonJS) |
| Architecture Presets | DDD, Hexagonal, Clean, Layered, MVC, Event-Driven, Feature-Module |
Each framework has dedicated handler-scope detection. Each ORM has dedicated query pattern recognition. Architecture presets define layer rules, cross-module policies, and allowed import paths.
Tip: You do not need to configure any of this manually.
radar initauto-detects your framework, ORM, layer structure, module boundaries, and architecture pattern.
Who Is Radar For
| Role | How They Use Radar | Key Value |
|---|---|---|
| Backend Developers | See violations in PR feedback, fix before merge | Clear, actionable feedback on every PR |
| Tech Leads | Define radar.yml, monitor architecture trends | Architecture rules enforced 24/7, not just during reviews |
| CTOs / Engineering Managers | Dashboard for system health across repos | Governance without reading every line of code |
| Agencies | Consistent quality across client projects | Standardized enforcement, portable config |
Next Steps
- Quickstart --- Install, scan, and fix in 5 minutes.
- Installation --- CLI, GitHub App, GitHub Action, and GitLab CI setup.
- Your First Scan --- Interpret your first scan report and reduce your initial debt score.