$ case open sfera-memory

How we roughly halved memory use in a real-time portal

An engineering breakdown of a long-lived React interface: from a dedicated Puppeteer tool and a fuite fork to automated heap snapshots and verification under the same workload.

≈10/s
events in the real-time stream
≤5,000
events kept in history
400–500+
MB before optimization
150–250
MB after optimization

01 / Context

The problem appeared over time, not in a single render

The SFERA monitoring portal handled a continuous event stream and live WebSocket charts. For this kind of system, first-load speed is not enough: the tab must remain stable through long sessions and repeated user flows.

My role

Senior frontend engineer responsible for application structure, core UI flows, integrations, and performance.

System workload

About 10 events per second, up to 5,000 historical events, and WebSocket-driven charts.

Engineering goal

Turn a one-off memory-growth symptom into a repeatable test and a verifiable result.

02 / Investigation

From a reproducible scenario to verified fixes

Four stages connect the same workload, automated heap snapshots, retained-object analysis, and a repeat run after the fixes.

memory-investigation.logInvestigation replay
01 / 04
Tab memorymeasured ranges
Before400–500+ MB
After150–250 MB

Memory ranges compared under the same workload before and after the fixes.

Scenario

Lock down a reproducible path

Start with a stable long-session scenario rather than a random browser snapshot.

  • A real-time stream of about 10 events per second
  • Up to 5,000 retained events and WebSocket charts
  • The same sequence of actions for every measurement

03 / Decisions

Three decisions that made the result verifiable

01

One scenario for every run

Optimization runs used the same user path so a random memory fluctuation could not be mistaken for an improvement.

Slower than a single manual reading, but reproducible.
02

Fork fuite instead of working around it

Resource cleanup via dispose was fixed in the fork so the diagnostic runner itself would not distort the result.

A fork to maintain, but measurements that can be trusted.
03

Validate a long-lived session

The final run repeated the event stream and history close to the portal’s real operating mode.

Slower than a micro-test, but representative of the product flow.
Investigation toolchain
ReactTypeScriptMobXWebSocketChrome DevToolsReact ProfilerfuitePuppeteer

04 / Outcome

Tab memory dropped from 400–500+ to 150–250 MB

The main outcome is not only a smaller number, but a repeatable way to find and verify similar regressions in a real-time interface.

Before400–500+ MB
After150–250 MB

Performance

Long-lived state and runtime profiling—not just a Lighthouse score.

Tooling

A dedicated Puppeteer tool, a fuite fork with dispose, and automated heap snapshots.

Engineering judgment

Hypothesis → reproduction → comparison → verification with the same scenario.

$ next

Continue with the architecture case study

Next: a banking onboarding platform built around a shared React/TypeScript library for five applications.