<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1" -->

---
title: High-Frequency Real-Time Data in React: From Ring...
description: A deep architectural walkthrough for rendering high-frequency real-time data (e.g. 19 EEG channels at 1kHz) in React without choking the UI. Covers moving...
canonical: https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: High-Frequency Real-Time Data in React: From Ring Buffers to OffscreenCanvas | daily.dev
og:description: A deep architectural walkthrough for rendering high-frequency real-time data (e.g. 19 EEG channels at 1kHz) in React without choking the UI. Covers moving...
og:url: https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1
og:image: https://api.daily.dev/og/posts/CtLrBbht1.png
og:image:alt: High-Frequency Real-Time Data in React: From Ring Buffers to OffscreenCanvas
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# High-Frequency Real-Time Data in React: From Ring Buffers to OffscreenCanvas

**[freeCodeCamp](https://daily.dev/sources/freecodecamp)** · 32 min read · 33 upvotes · 0 comments

## Summary

A deep architectural walkthrough for rendering high-frequency real-time data (e.g. 19 EEG channels at 1kHz) in React without choking the UI. Covers moving samples out of React state into ring buffers, separating shape from values, offloading work to Web Workers and worker pools, using transferable objects and SharedArrayBuffer with Atomics for lock-free shared memory, rendering via OffscreenCanvas, decimation techniques (min-max, LTTB), wrapping imperative chart libraries like uPlot, escalating to WebGL, and keeping memory flat over multi-hour sessions. Includes a real case study switching from LightningChart to uPlot plus benchmark tables comparing single-thread vs multi-thread+SAB+OffscreenCanvas performance, and details on the COOP/COEP headers required for SharedArrayBuffer.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.freecodecamp.org/news/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas>

## Questions this post answers

### How do I keep a React app responsive when rendering thousands of real-time data points per second?

Keep the samples out of React state entirely and store them in a ring buffer over a typed array outside React, then draw with an imperative requestAnimationFrame loop that reads from the buffer. React should only re-render when the UI shape changes (new plot, layout switch), not on every incoming sample. Batching setState calls once per frame instead of once per sample turns roughly 19,000 renders per second into a manageable 60.

_Developers tuning React rendering strategies can track patterns like this on daily.dev._

### What browser headers are required to use SharedArrayBuffer in a web app?

A page needs Cross-Origin-Opener-Policy set to same-origin and Cross-Origin-Embedder-Policy set to require-corp to become cross-origin isolated, which is required for SharedArrayBuffer to be defined and for Atomics to function. Without these headers SharedArrayBuffer is undefined and performance.now() is throttled to roughly 1ms precision. The require-corp setting also forces every cross-origin resource, like CDN images or embedded widgets, to explicitly opt in via Cross-Origin-Resource-Policy.

_Teams weighing cross-origin isolation tradeoffs for real-time apps can follow this topic on daily.dev._

### When should I use OffscreenCanvas plus SharedArrayBuffer instead of just Web Workers for rendering charts?

Use OffscreenCanvas plus SharedArrayBuffer once a plain worker pool stops being enough, since benchmarks on an M3 MacBook Pro showed a 1M-point chart holding only 28fps with workers and SharedArrayBuffer alone, but reaching a full 60fps once OffscreenCanvas moved rendering off the main thread too. For 19 EEG channels at 1kHz, this combination held 60fps (144fps on capable displays) with main thread utilization under 1%.

_Engineers scaling canvas rendering pipelines can dig into benchmarks like these on daily.dev._

## Similar posts on daily.dev

- [Streaming Backends & React: Controlling Re-render Chaos in High-Frequency Data](https://daily.dev/posts/streaming-backends-react-controlling-re-render-chaos-in-high-frequency-data-lvkyfw1pt) · SitePoint · 0 upvotes · 0 comments
- [Bypassing the DOM: How We Built a 60 FPS GPU Playground in React](https://daily.dev/posts/bypassing-the-dom-how-we-built-a-60-fps-gpu-playground-in-react-bjjoodryo) · Medium · 1 upvotes · 0 comments
- [Real-Time Systems for Web Developers: From Theory to a Live Go \+ React App](https://daily.dev/posts/real-time-systems-for-web-developers-from-theory-to-a-live-go-react-app-4z2t5olbb) · freeCodeCamp · 8 upvotes · 0 comments
- [Sixty Frames for the Record: A Three.js Game, Seven Fly-Throughs, and a Wall of CRTs](https://daily.dev/posts/sixty-frames-for-the-record-a-three-js-game-seven-fly-throughs-and-a-wall-of-crts-tjn34cai4) · Codrops · 3 upvotes · 0 comments
- [Real-Time Data Visualization in Angular: Build Live, Interactive Charts with Syncfusion\[Webinar Show Notes\]](https://daily.dev/posts/real-time-data-visualization-in-angular-build-live-interactive-charts-with-syncfusion-webinar-show-hrjtix1l7) · Syncfusion · 0 upvotes · 0 comments

---

Tags: [#webdev](https://daily.dev/tags/webdev), [#react](https://daily.dev/tags/react), [#performance](https://daily.dev/tags/performance)

[View this post on daily.dev](https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"High-Frequency Real-Time Data in React: From Ring Buffers to OffscreenCanvas","url":"https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1"},"datePublished":"2026-08-19T08:41:32.967Z","dateModified":"2026-09-13T21:59:22.999Z","description":"A deep architectural walkthrough for rendering high-frequency real-time data (e.g. 19 EEG channels at 1kHz) in React without choking the UI. Covers moving...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/5fe25b471d1e441b66f7953328bbee59?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/5fe25b471d1e441b66f7953328bbee59?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"freeCodeCamp","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"freeCodeCamp","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1628412854/logos/freecodecamp","url":"https://daily.dev/sources/freecodecamp"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":33},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"webdev,react,performance","timeRequired":"PT32M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"freeCodeCamp","item":"https://daily.dev/sources/freecodecamp"},{"@type":"ListItem","position":3,"name":"High-Frequency Real-Time Data in React: From Ring Buffers to OffscreenCanvas"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/high-frequency-real-time-data-in-react-from-ring-buffers-to-offscreencanvas-ctlrbbht1#faq","mainEntity":[{"@type":"Question","name":"How do I keep a React app responsive when rendering thousands of real-time data points per second?","acceptedAnswer":{"@type":"Answer","text":"Keep the samples out of React state entirely and store them in a ring buffer over a typed array outside React, then draw with an imperative requestAnimationFrame loop that reads from the buffer. React should only re-render when the UI shape changes (new plot, layout switch), not on every incoming sample. Batching setState calls once per frame instead of once per sample turns roughly 19,000 renders per second into a manageable 60. Developers tuning React rendering strategies can track patterns like this on daily.dev."}},{"@type":"Question","name":"What browser headers are required to use SharedArrayBuffer in a web app?","acceptedAnswer":{"@type":"Answer","text":"A page needs Cross-Origin-Opener-Policy set to same-origin and Cross-Origin-Embedder-Policy set to require-corp to become cross-origin isolated, which is required for SharedArrayBuffer to be defined and for Atomics to function. Without these headers SharedArrayBuffer is undefined and performance.now() is throttled to roughly 1ms precision. The require-corp setting also forces every cross-origin resource, like CDN images or embedded widgets, to explicitly opt in via Cross-Origin-Resource-Policy. Teams weighing cross-origin isolation tradeoffs for real-time apps can follow this topic on daily.dev."}},{"@type":"Question","name":"When should I use OffscreenCanvas plus SharedArrayBuffer instead of just Web Workers for rendering charts?","acceptedAnswer":{"@type":"Answer","text":"Use OffscreenCanvas plus SharedArrayBuffer once a plain worker pool stops being enough, since benchmarks on an M3 MacBook Pro showed a 1M-point chart holding only 28fps with workers and SharedArrayBuffer alone, but reaching a full 60fps once OffscreenCanvas moved rendering off the main thread too. For 19 EEG channels at 1kHz, this combination held 60fps (144fps on capable displays) with main thread utilization under 1%. Engineers scaling canvas rendering pipelines can dig into benchmarks like these on daily.dev."}}]}
```

