Skip to content

[discussion]: nest analyze --unused-routes β€” detect backend routes not consumed by the frontendΒ #3294

@mateo-maza

Description

@mateo-maza

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

As NestJS backends grow, it's common to accumulate HTTP routes that were once needed but are no longer called by the frontend. There is currently no automated, static way to detect these "dead routes". Teams rely on manual API doc reviews or runtime traffic analysis, neither of which works in local or CI environments.

Describe the solution you'd like

A new nest analyze --unused-routes command that statically detects backend routes not consumed by a given frontend codebase.

How it works (working PoC already exists):

  • Uses ts-morph to walk the backend AST and extract all route definitions: @Controller() prefixes combined with @Get(), @Post(), @Put(), @Patch(), @Delete(), @All() method decorators, accounting for @Version() and the global prefix in nest-cli.json
  • Uses the same ts-morph pipeline on the frontend source to find HTTP client call sites (string/template literals matching route patterns, calls to fetch, axios, HttpClient, useSWR, useQuery, etc.)
  • Diffs both sets and reports routes present in the backend but never referenced in the frontend

Proposed CLI interface:

# Frontend in same monorepo
nest analyze --unused-routes --frontend ./apps/web

# Private remote frontend repo (GitHub PAT for auth)
nest analyze --unused-routes \
  --frontend https://github.com/org/frontend-repo \
  --frontend-token 

# Machine-readable output for CI
nest analyze --unused-routes --format json

Example output:

βœ– Unused routes detected (3):

  DELETE /api/v1/reports/:id        β†’ ReportsController#remove
  GET    /api/v1/exports/csv        β†’ ExportsController#getCsv
  POST   /api/legacy/notifications  β†’ NotificationsController

βœ” 47 routes verified as consumed by frontend.

Considered drawbacks:

  • Frontend call-site detection via string matching can produce false positives if routes are constructed dynamically at runtime (e.g. computed URL strings). This is a known limitation and can be documented.
  • Cloning a remote frontend repo adds I/O overhead; the PAT is never persisted or logged.
  • Scope of frontend framework support needs community input (plain fetch/axios vs framework-specific wrappers for v1).

Teachability, documentation, adoption, migration strategy

Usage would follow the same pattern as other nest CLI commands β€” no app bootstrap required, purely static analysis.

Docs entry (draft):

Analyzing unused routes

nest analyze --unused-routes --frontend  [--frontend-token ] [--format json]
Flag Description
--frontend Path to the frontend source (local) or GitHub repo URL (remote)
--frontend-token GitHub PAT for private frontend repos (never stored)
--format Output format: text (default) or json for CI consumption

Adoption: Zero config for monorepos β€” reads existing nest-cli.json for entry file, source root, and global prefix. No additional setup needed.

Video of the PoC output (delayed on purpose):

Image

What is the motivation / use case for changing the behavior?

Concrete use cases:

  • A team refactors a large feature and removes the frontend calls, but forgets to clean up the backend controllers. The dead routes accumulate silently.
  • A monorepo using Nx or Turborepo wants to enforce "no orphaned routes" as a CI check β€” today there is no nest-native way to do this.
  • A developer inherits a legacy NestJS backend and wants to understand which routes are actually in use before attempting a cleanup.

Why nest-cli specifically? It already reads nest-cli.json (entry file, source root, global prefix), so it has the project context needed to resolve routes correctly. No need to re-configure paths or bootstrap the NestJS app.

Alternatives considered and why they fall short:

  • Runtime traffic analysis β€” requires production traffic; not suitable for local or CI environments
  • OpenAPI diffing β€” tells you what's documented vs deployed, not what the frontend actually calls; also requires Swagger to be set up
  • ESLint plugin β€” harder to correlate across repos; separate config burden
  • Standalone ts-morph script β€” exists as community gists but not integrated into the CLI toolchain and requires per-project setup

I have a working PoC and am ready to submit a PR once there is alignment on the command interface, naming, and whether this belongs in nest-cli core or a separate @nestjs/analyze package.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions