Use the device thoughtfully
Move useful work to workers and optional runtimes with explicit resource budgets and fallbacks.
The endpoint here is the user’s phone, tablet or laptop. Its processors, memory, storage and sometimes GPU can shorten interactions, avoid unnecessary uploads and keep work possible during a lost connection. The device also belongs to someone who needs its battery, memory and attention for other things.
Start with a useful server-rendered application, identify one expensive interaction and measure the smallest local implementation that helps. This article proposes an engineering approach; no benchmark or deployed compute feature is claimed.
Choose a bounded task
Good candidates include searching a downloaded reference set, previewing a report, resizing a selected image or calculating a scenario from inputs already on the device. Their inputs and outputs are understandable. They can often avoid network round trips after their code and data have loaded.
Keep authorization, authoritative persistence, shared coordination and secrets on the server. A local invoice preview can help someone explore options; Rails must validate prices and permissions before recording a transaction. Client results remain untrusted inputs even when both ends use the same algorithm.
Compare complete paths. Count a local library’s download, initialization, decoding, processing and peak memory against upload and server processing. Repeat on a modest phone and a development laptop, including cold downloads. A warm-cache result hides the first visitor’s cost.
Give heavy work a worker
A dedicated Web Worker runs separately from the page’s execution context, exchanges messages and cannot directly manipulate the DOM. For local catalog search, keep one permitted catalog in a worker; send queries and return small result sets. Render in the page. Detect availability and handle startup failure, retaining a Rails search form as a fallback.
Use complete operations, such as “search these indexed records,” rather than thousands of comparison messages. Give each request an identifier so a late response cannot overwrite a newer query. Bound outstanding work and discard obsolete results.
A cancellation message cannot interrupt a long synchronous loop before the worker returns to its event loop. Split work into interruptible chunks, or terminate and recreate the worker when losing its memory is safe. Termination does not prove a storage transaction rolled back. Tie cleanup to the page or controller lifecycle so navigation does not leave unnecessary computation running.
Count copying as work
Messages containing large object graphs can incur copying and allocation. For binary data, transferable objects allow an ArrayBuffer to transfer ownership. Its sender’s buffer becomes detached; that ownership change must be explicit.
For a photo tool, transfer a bounded buffer and return a bounded result. Avoid simultaneously retaining the original, multiple decoded copies, a full-resolution preview and an export unless the budget allows it. A local-processing feature that crashes the tab has not reduced the user’s cost.
SharedArrayBuffer adds coordination and security requirements, including cross-origin isolation for the usual browser-sharing path. Review resource and integration consequences before selecting it. This series changes no server headers; one worker with coarse messages is the initial design.
Use Wasm for a measured reason
WebAssembly’s documented use cases include media processing and simulation. It can reuse a computational library or provide a suitable execution format; it does not automatically speed up every algorithm.
Compare correctness, download, compilation, initialization, memory and JavaScript/Wasm boundary costs with straightforward JavaScript and the server path. Batch operations. For CRuby packaging and Rails compatibility, read our Ruby applications in the browser companion instead of assuming an ordinary Rails server runs unchanged.
Ruby-first can still mean Rails owns the application while a small JavaScript worker performs a browser-specific task. Shared input formats and test vectors may be simpler than shipping a second runtime to reuse a short calculation.
Treat resources as a budget
Start with one worker, bounded file sizes and smaller previews. Increase concurrency only after measurement. hardwareConcurrency is a hint, and browsers may report fewer processors than exist. It is not permission to occupy every processor.
The Device Memory API reports approximate capacity and has limited availability; the Battery Status API also has limited availability as checked for this article. Responsible behavior must work without either. Use conservative limits, cancellation and an optional lower-resource mode.
Page visibility can signal when optional work should pause. Do not rely on a background tab finishing an important operation at a precise time. Persist progress where appropriate and show when work requires the application to remain open.
Local processing can keep selected content off the network. Verify that promise by inspecting requests, including analytics and crash reports. Keep input content out of diagnostics, explain local retention and provide deletion controls. Origin scripts can access the data you give them.
Keep GPU acceleration optional
As checked 16 October 2026, MDN marks WebGPU as limited availability and requiring a secure context. Browser, operating system, hardware and adapter availability all matter. Detect the API, attempt initialization and handle failure: requestAdapter can return no adapter. Device loss after startup also needs recovery.
For suitable tasks, provide a worker or Wasm CPU fallback. Otherwise offer a smaller local task or an explicit server option. Never silently upload a private file because acceleration failed. A privacy promise constrains the fallback, not just the preferred path.
Release one improvement with evidence
A useful first experiment is search over a small public reference set. Keep Rails search available, load the index on demand, use one worker and measure cold start, query latency, memory behavior and failure rates on representative devices. Check result equivalence, stale-result handling, keyboard use and cancellation alongside speed.
Publish the measured benefit and its limits when those measurements exist. The next part decides which data survives a disconnected session and how the person recovers their work.