Memory footprint reduced in instance-ai module
Memory optimizations address heap profiling findings in instance-ai: storage-only Mastra singletons prevent agent closure leakage, Brotli compression is disabled to free ~8.6 MB per connection, node types now read from static JSON instead of a 31 MB registry rebuild, and a regex-based JSON highlighter is replaced with a structural walker.
Heap profiling revealed multiple memory leaks and inefficient patterns in the instance-ai module. The most severe: Mastra singletons were storing agent objects with their closures (tools, prompts, thread context) in the internal #agents dict — in multi-user environments this meant User A's agent got pinned in shared memory for all subsequent users. The fix creates Mastra with only storage, while agents get the back-reference needed for suspend/resume via __registerMastra() without being added to the agents dictionary.
A separate bottleneck: collectTypes() triggers a full rebuild of the node type registry, costing ~31 MB each time. The adapter service now reads from the static JSON file that FrontendService writes at startup instead.
Brotli compressors from Express response compression retained ~8.6 MB of native memory each via keep-alive connections. A middleware now strips br from Accept-Encoding to downgrade to gzip, and SSE streams have compression disabled entirely.
The Mastra upgrade brings lazy tiktoken loading, avoiding ~15 MB of WASM allocation on import. A global stub in prevents Mastra's workspace tools from eagerly loading the 66 MB BPE table — a character-based estimate is sufficient for truncation.
On the tracing side, LangSmith requests now use a gzipFetch wrapper that forces gzip encoding and suppresses noisy 409 "payloads already received" errors on retries.
A bug fix: DaytonaFilesystem.stat() threw DaytonaNotFoundError which Mastra didn't recognize, causing write_file to fail on new files. The error is now translated to FileNotFoundError.
In the frontend, a regex-based JSON syntax highlighter was vulnerable to catastrophic backtracking on large tool outputs. It has been replaced with a structural character walker.
View Original GitHub Description
Summary
Fixes several memory and stability issues in instance-ai discovered during heap profiling.
Memory fixes
-
The cached Mastra singleton in
registerWithMastra()andensureMastraRegistered()was passing agents to the constructor, which stored the first agent's closures (tools, prompts, thread context) permanently in Mastra's internal#agentsdict. In a multi-user environment this means User A's agent gets pinned in the singleton shared by all subsequent users. Fixed by creating Mastra with only storage. Agents get the back-reference for suspend/resume via__registerMastra()without being added to#agents. -
InstanceAiAdapterServicewas callingcollectTypes()which triggerspostProcessLoaders(), an expensive rebuild of the full node type registry (~31 MB). Switched to reading from the static JSON file thatFrontendServicewrites at startup. -
Brotli compressors from Express response compression were costing ~8.6 MB of native memory each, retained via keep-alive connections. Added a controller middleware that strips
brfromAccept-Encodingto downgrade to gzip, and disabled compression entirely on instance-ai SSE streams. -
Upgraded Mastra packages to get lazy tiktoken loading (avoids ~15 MB WASM allocation on import) and a token growth fix. Also patched the module loader to prevent Mastra from eagerly importing tiktoken and tokenizer (~60 MB combined).
-
LangSmith tracing now uses a
gzipFetchwrapper that forces gzip encoding for both proxy and direct client paths, avoiding the brotli decompressor overhead on the tracing side.
Other fixes
-
LangSmith
patchRunwas logging noisy 409 "payloads already received" errors on retries. ThegzipFetchwrapper now returns a synthetic 200 for 409 responses since the data already landed. -
Mastra's
wrapWithReadTrackercallsstat()before file writes and catchesFileNotFoundErrorfor new files. ButDaytonaFilesystem.stat()was throwing Daytona SDK'sDaytonaNotFoundErrorwhich Mastra didn't recognize, causingwrite_fileto fail on new files that don't exist yet. Now translates Daytona 404s to Mastra'sFileNotFoundError. -
The regex-based JSON syntax highlighter in
ToolResultJson.vuewas vulnerable to catastrophic backtracking on large tool outputs. Replaced with a structural character walker.
Review / Merge checklist
- PR title and summary are descriptive. (conventions) <!-- **Remember, the title automatically goes into the changelog. Use `(no-changelog)` otherwise.** -->
- Docs updated or follow-up ticket created.
- Tests included. <!-- A bug is not considered fixed, unless a test is added to prevent it from happening again. A feature is not complete without tests. -->
- PR Labeled with
Backport to Beta,Backport to Stable, orBackport to v1(if the PR is an urgent fix that needs to be backported)