Skip to content

Limits

Each number on this page is a constant in the source, named so you can check it. Where a number is a measurement rather than a constant, the page names the test or benchmark that measures it.

LimitValueWhere it livesAbove it
Stored payload512 KB of JSON per eventMAX_PAYLOAD_BYTES, packages/schema/src/shrink.ts (re-exported by packages/cli/src/storage.ts)The event is still stored and shown. Its largest fields are shrunk and keep their JSON type (a string becomes a shorter string, an array []), and the payload gains __graphmindTruncated: true, the original size and a 2,000-character preview. The live view and a reload show the same truncated payload. The TypeScript client applies the same shrink before it sends, with a rate-limited warning.
WebSocket frame, server side16 MiB per frame, on both /ingest and /ws/uiMAX_FRAME_BYTES, packages/cli/src/storage.ts (applied in server.ts)The server refuses the frame while assembling it and closes the socket (code 1009) without reading the rest. The TypeScript client never sends a frame that large; the Python and Ruby SDKs can (see below).
JSON-RPC frame, graphmind mcp-proxy64 MiB per newline-delimited frame by default; --max-frame-bytes <n> changes itDEFAULT_MAX_FRAME_BYTES, packages/cli/src/mcp-proxy/proxy.tsThe proxy stops parsing that direction and relays raw bytes for the rest of the session. The MCP session keeps working; the graph stops updating. It prints: graphmind mcp-proxy: a server frame exceeded 67108864 bytes (… buffered); relaying raw from here on — the graph will stop updating but the session keeps working (raise --max-frame-bytes). Tested by packages/cli/test/mcp-proxy-relay.test.ts (“degrades to a raw pipe … when a frame passes the ceiling”).
Server stderr kept by the proxylast 200 lines / 32 KBSTDERR_RING_MAX_LINES, STDERR_RING_MAX_BYTES, packages/cli/src/mcp-proxy/stderr-ring.tsOlder lines are dropped. When a server exits before answering, the terminal shows the last 40 lines; the session node carries the whole ring.
stdout noise recorded by the proxythe first 25 non-JSON-RPC lines become nodes; each is quoted up to 200 bytesSTDOUT_NOISE_MAX_RECORDED, STDOUT_NOISE_QUOTE_BYTES, packages/cli/src/mcp-proxy/reporter.tsFurther lines are counted, not recorded.

The two frame ceilings are different on purpose. The server ceiling protects a long-running process from a single oversized frame. It is 32 times the storage budget, so a payload big enough to be worth a preview still gets through and is truncated. The proxy ceiling sits on your editor’s tool traffic, where dropping a frame would break the session. So above it the proxy stops recording instead of dropping anything.

BufferDefaultWhereWhen it fills
Replay ring buffer, TypeScript client5,000 events or 8 MiB, whichever comes first (bufferSize, maxBufferBytes)packages/client/src/session.tsOldest events are dropped. On the next attach the client sends a gap marker naming how many events were lost and their seq range, and it warns once. Test: packages/client/test/gap.test.ts.
Replay ring buffer, Python2,000 events (buffer_size)python/graphmind/session.pyOldest events are dropped
Replay ring buffer, Ruby2,000 events or 8 MiB (buffer_size:, max_buffer_bytes:)ruby/lib/graphmind/session.rbOldest events are dropped
Loop-hold stateone streak (node, fingerprint, count) per node kind per run, for up to 64 runs (least recently used are evicted)MAX_LOOP_RUNS, packages/client/src/loop-guard.tsAn evicted run’s streak starts again
Redaction kind tracking10,000 open executionsDEFAULT_MAX_TRACKED_INSTANCES, packages/client/src/redaction.tsFalls back to the node’s latest kind, then to the tool: id prefix
Stored runs200 runs / 30 days, pruned at server startDEFAULT_RETENTION, packages/cli/src/storage.tsOlder runs are deleted (GRAPHMIND_KEEP_RUNS, GRAPHMIND_KEEP_DAYS, GRAPHMIND_RETENTION=off)
WhatDefaultWhere
A held gateHeld until resumed. pauseTimeoutMs (TS), pause_timeout (Python, Ruby) auto-continues after that long and emits exec.resumed.session options
A debugger that disconnects mid-holdEvery held gate continues within 100 msasserted by packages/client/test/session.test.ts (“auto-continues held gates within 100ms of the viewer dying”) and python/tests/test_failopen.py
Connect to the server300 ms (connectTimeoutMs); Python 0.3 sTS session.ts, Python session.py
Handshake1,000 ms (handshakeTimeoutMs); Python 1.0 ssame
Retry while detachedevery 10 s (retryIntervalMs)same
gm.ready()2,000 ms; waitForAttach: true means 2,000 mssame
graphmind mcp-proxy --wait-for-attachholds the first frame for up to 3 sATTACH_WAIT_MS, mcp-proxy/proxy.ts
A proxied server that fails to start, with no --wait-for-attachthe proxy waits up to 1 s for GraphMind before exiting, so the failure reaches the graphSPAWN_FAILURE_ATTACH_MS, mcp-proxy/proxy.ts
@graphmind-ai/mcp long-hold warningprinted once when a hold passes 1 s, because the MCP host has its own timeoutHOLD_WARN_MS, packages/mcp/src/gate-flow.ts
A run whose app disconnected mid-flightmarked abandoned after 15 s without a reconnect (GRAPHMIND_ABANDON_GRACE_MS)DEFAULT_ABANDON_GRACE_MS, packages/cli/src/hub.ts

A held gate stops your code, not the other side. An MCP host, an HTTP client or a framework with its own timeout can still give up while you are looking at a paused node. The TypeScript adapters neutralise their SDK’s per-request timeouts while a debugger is attached; the Python SDK does not yet. See each integration page.

“Handles large graphs” is only as true as the largest graph a test runs. These are the ones in the repository:

SizeWhat is checkedWhere
300 nodes, ~5,000 eventsReducer, projection, layout and timeline each finish inside a frame on a warm pass (budget 16 ms, observed well under); the auto-folded view has at most 60 cardsapps/viewer/test/stress.test.ts
300 nodes in a browserIngests, folds itself, stays interactive; the palette finds one node; the minimap pansapps/viewer/e2e/stress.spec.ts
301-node layout, 300-node stress run folded and unfoldedZero edges through cards, zero overlapping cardsapps/viewer/test/geometry.test.ts
100 → 1,600 nodesLayout time sweep; a canvas of ~800 nodes lays out in under 50 mssoak viewer scenario, run in CI (examples/soak)
?stress=<n>Accepts 8 to 4,000 nodes for trying larger shapes yourselfapps/viewer/src/connection/StressConnection.ts

Above a few hundred nodes, fold. A run with more than 70 nodes opens folded on its own, and large graphs covers the rest.