08-Jun-2026 — memory & heap diagnostics, per-VM heap sizing, plus websocket send reliability ref #257
Tooling to investigate per-site memory and get area sites onto 512MB,
plus a websocket reliability fix found during testing.
Memory diagnostics (ref #257):
- GET /api/health/memory (public, numbers only): process.memoryUsage() and
v8.getHeapStatistics() in MB - rss, heapUsed, external, arrayBuffers, heap
size limit. Tells us at a glance whether a site is heap-bound (objects/caches)
or external-bound (buffers) without a full snapshot.
- GET /api/health/memory/heap-snapshot (authenticated): streams a V8 heap
snapshot straight to S3 (diagnostics/heap-snapshots/-) without
buffering it in process memory, returns the key for offline analysis.
- Diagnostics tab under Admin > System Settings: Refresh reads the memory
endpoint and shows RSS, heap used/total, heap size limit, external buffers,
ArrayBuffers, uptime and Node version; Capture heap snapshot calls the
authenticated endpoint and reports the S3 object key.
WebSocket send reliability:
- sendMessage called WebSocket.send() while the socket was still CONNECTING
(connect() resolves immediately when reusing an in-progress connection),
throwing "InvalidStateError: Still in CONNECTING state" - seen on the backup
history page. Messages sent before the connection opens are now queued and
flushed in onopen, protecting every consumer (backup, environment
setup/create, migration, walks-manager sync, image resize, legacy-redirect
scrape).
Heap sizing:
- Remove the fixed --max_old_space_size cap from the server start
command. It dated from the Heroku era, where Node read the host
machine's RAM rather than the dyno quota and had to be capped by hand.
On Fly each machine is a VM whose real RAM Node reads directly, so Node
now sizes the old-space heap from the machine it runs on: a 1GB site
gets more headroom than a 512MB site without every environment sharing
one hardcoded ceiling. worker-server keeps its explicit cap so its
browser and Serenity subprocesses retain room outside the Node heap.