Why I replaced Redux with
raw WebSockets.
We have been taught that the client-side store is the Single Source of Truth. We serialize data into Redux or Zustand, diff the Virtual DOM, and reconcile changes. For 99% of apps, this is perfect.
But when I was building the Vault Dashboard, dealing with 5,000+ market ticks per second, this architecture fell apart. The browser wasn't struggling to render; it was struggling to allow Redux to decide what to render.
Latency impact of State Management overhead at 1000Hz
The "Store" is the Bottleneck
In a high-frequency trading context, the data on the screen is stale the moment it is rendered. Validating that data against a client-side schema, normalizing it for a Redux slice, and then triggering selectors creates a massive backlog on the main thread.
We realized that for the order book and the tick chart, the client does not need to "know" the state. It just needs to display it. We don't need to store the tick history in Redux if we are just painting it to a Canvas.
Bypassing the V-DOM
We switched to a raw WebSocket implementation using `ArrayBuffers` (Protobufs) instead of JSON strings. This reduced the payload size by 60%, but the real win was bypassing React completely for high-frequency components.
const useSocketStream = (canvasRef) => {
useEffect(() => {
const ws = new WebSocket('wss://api.vault.com/stream');
ws.binaryType = 'arraybuffer';
ws.onmessage = (event) => {
// Decode directly in the worker or main thread
const view = new DataView(event.data);
const price = view.getFloat32(0);
// DIRECT PAINT: No state update, no re-render cycle
paintChart(canvasRef.current, price);
};
return () => ws.close();
}, []);
};
By treating the visual layer as a "dumb terminal" for the server's state, we eliminated the Garbage Collection pauses caused by thousands of temporary Redux action objects being created and destroyed every second.
When to ignore this advice
If you are building a Todo app, a dashboard with modest updates, or essentially anything that isn't a real-time game or financial instrument, please use Redux (or Context, or Zustand).
This architecture sacrifices "Predictability" and "Time Travel Debugging" for raw speed. In our case, predictability didn't matter if the user was seeing prices that were 200ms old.
The Takeaway
Don't let "Best Practices" dictate your architecture when you are solving non-standard problems. The browser is incredibly fast if you get out of its way.