I've been conducting a fairly comprehensive evaluation of SAST and SCA tools for our organization's primary codebase, which is a substantial TypeScript monorepo managed with pnpm workspaces (approximately 150+ packages, 1.2 million lines of code). My testing protocol involves a clean install, followed by a full scan from the repository root. While I appreciate Snyk's depth of vulnerability intelligence and its IDE integration, I've consistently observed that its CLI tool (`snyk test --all-projects`) becomes a significant bottleneck in our CI/CD pipeline compared to competitors like Trivy or even GitHub's native Dependabot scans.
The performance degradation seems non-linear as the project graph grows. A scan that takes 4-5 minutes on a smaller service repository balloons to **over 45 minutes** on our main monorepo. This has prompted me to dig into the possible architectural reasons. From my analysis, the slowness appears to stem from several interlocking factors:
* **Project Discovery & Isolation:** Snyk appears to treat each workspace package as a fully isolated project, launching a discrete subprocess for each. The overhead for spawning, analyzing, and tearing down each of these 150+ processes is immense. The tool seems to serialize much of this work, rather than employing aggressive parallelization.
* **Dependency Resolution Overhead:** Even with a lockfile present, Snyk spends considerable time reconstructing the dependency tree for each package. In a pnpm workspace, where dependencies are often hoisted or symlinked, this tree-walking operation seems to be repeated redundantly across packages.
* **File System I/O Saturation:** The tool traverses `node_modules` for each project extensively. In pnpm's symlinked structure, this leads to traversing the same physical paths multiple times from different project contexts, causing significant I/O wait.
To illustrate, here's a simplified view of our monorepo structure and the Snyk command used:
```
monorepo-root/
├── package.json
├── pnpm-workspace.yaml
├── packages/
│ ├── core-lib/
│ │ └── package.json
│ ├── api-service/
│ │ └── package.json
│ └── ... (150+ more)
└── pnpm-lock.yaml
```
I've attempted to mitigate this with concurrency flags and targeting only modified packages, but the results are inconsistent. Has anyone else in the community performed a similar side-by-side benchmark on a comparable scale? I'm particularly interested in:
* Whether you've observed similar performance characteristics and if you've pinpointed other contributing factors.
* Any effective configuration patterns or workarounds for Snyk in large monorepos (beyond the obvious "scan only changed packages," which has its own blind spots).
* How alternative tools (e.g., Trivy, Grype, OWASP Dependency-Check) architecturally handle monorepo workspaces and whether their approaches inherently avoid this type of performance cliff.
My hypothesis is that tools designed with a "monorepo-first" mentality, which build a unified dependency graph before scanning, would have a distinct advantage here. I'm compiling a detailed feature and performance matrix and would value any data points from this group.
Data is the source of truth.
Yep, that project discovery overhead is brutal. I've seen the same thing in a similar pnpm setup. The subprocess per project model creates immense overhead, especially when combined with the network latency of checking each manifest against Snyk's database.
One workaround we had moderate success with was generating a lockfile per service and scanning that directly, bypassing the `--all-projects` discovery. It's a hack, but it cut scan time by about 60%. Have you tried that, or are you locked into the full monorepo scan requirement?
You've nailed a key architectural constraint. That per-project subprocess overhead isn't just about spawn time - it serializes a lot of I/O and network calls that could be batched. I think the non-linear scaling hits a wall because each subprocess is also loading and processing its own chunk of the vulnerability database, which is a lot of redundant work.
Have you experimented with the `--detection-depth` flag? In some monorepo layouts, you can limit the crawl to speed up the discovery phase, though it sounds like you need full coverage.
Review first, buy later.