Fixing VS Code IntelliSense Slowdowns and Crashes in Large TypeScript Monorepos
Autocomplete feels instant in a small TypeScript project, but on a large monorepo it takes seconds to respond, or tsserver crashes with an out-of-memory error. Here's why, and the definitive fix with memory limits and project references.
The Problem
In a small TypeScript project, VS Code's IntelliSense (autocomplete, hover types, go-to-definition) feels instant. On a large monorepo with many packages and thousands of files, the same features become sluggish, autocomplete takes seconds to appear, or the TypeScript language server (tsserver) crashes and restarts repeatedly with a "JS heap out of memory" style error in the Output panel.
This isn't VS Code being slow in general — it's tsserver, a single Node.js process with a default memory ceiling, trying to type-check and hold in memory far more of the codebase than the file you're actually editing needs.
Why It Happens
tsserver's default memory limit is too small for a large monorepo
tsserver runs as a single process with a Node.js memory limit that, by default, is often lower than what a large project's full type graph actually requires. Once it hits that ceiling, it either slows to a crawl doing excessive garbage collection or crashes outright.
A single, unpartitioned tsconfig.json covering the whole monorepo
Without TypeScript's project references, editing one file in one package can force tsserver to load and type-check the entire dependency graph across every package, instead of just the packages that file actually depends on.
Editors open across many unrelated packages at once
Every open tab from a different, unrelated part of the monorepo adds more files tsserver keeps "hot" in memory, even if you're not actively editing most of them.
The Fix
1. Raise tsserver's memory limit explicitly
// .vscode/settings.json
{
"typescript.tsserver.maxTsServerMemory": 4096
}
This is the fastest fix and often enough on its own for monorepos that were simply hitting the default ceiling rather than having a deeper structural issue.
2. Split the monorepo's TypeScript config using project references
// packages/api/tsconfig.json
{
"compilerOptions": { "composite": true, "outDir": "./dist" },
"references": [{ "path": "../shared" }]
}
Project references let tsserver type-check each package against the others' already-compiled .d.ts output instead of re-parsing every package's full source on every edit, which is the single biggest structural fix for monorepo IntelliSense performance.
3. Exclude build output and generated files from the TypeScript program
// tsconfig.json
{
"exclude": ["**/dist/**", "**/build/**", "**/*.generated.ts", "**/node_modules/**"]
}
If compiled output or generated type files are sitting alongside source and aren't excluded, tsserver may end up type-checking both the source and its own build artifacts, doubling the work for no benefit.
4. Use the "Restart TS Server" command as a diagnostic, not a permanent fix
Running TypeScript: Restart TS Server from the command palette clears a temporarily bloated process, but if it needs restarting every few minutes, that's a sign of one of the structural issues above, not something to live with long-term.
Why This Works
None of these changes make TypeScript itself faster to check — they reduce how much of the codebase tsserver has to hold in memory and re-check on every keystroke. A higher memory ceiling buys headroom for genuinely large projects; project references let each package's boundary act as a cache; and excluding generated files stops redundant work that was never adding useful type information.
Conclusion
IntelliSense slowdowns and tsserver crashes in a large TypeScript monorepo almost always come down to a memory ceiling that's too low for the project's actual size, combined with a TypeScript config that isn't partitioned along package boundaries. Raise the memory limit, adopt project references, and exclude generated output, and IntelliSense stays fast even as the monorepo keeps growing.
