Skip to content

About Hybrid Compute ​

Hybrid Compute is a flexible, modular compute orchestration framework that dispatches computational tasks to the most appropriate backend - whether that's:

  • The local JS thread (for fast, simple tasks)
  • A dedicated Web Worker (for multi-threaded offloading)
  • Or a remote compute service over HTTP or WebSocket

All you do is define tasks and call runTask(). Hybrid-Compute takes care of the rest.

Use Cases ​

Low-Latency UI, Zero Jank ​

Problem:Solution:Backends:
Heavy logic blocks the main thread and hurts UX.Run cheap, synchronous logic locally, push CPU-intensive work to a Web Worker, and only call remote when needed.local → worker → remote (fallback)

Why use Hybrid-Compute?

auto strategy + canRun lets you route without if/else sprawl.

Heavy Data Crunching (CSV/JSON/Parquet) ​

Problem:Solution:Backends:
Large file parsing/transformations freeze the UI or time out remotely.Parse/transform in a worker; optionally batch and upload results to remote.worker, optionally remote

Why use Hybrid-Compute?

Clean separation of CPU work (worker) and I/O (remote).

AI Prompt Pre/Post-Processing ​

Problem:Solution:Backends:
Prompts and responses need cleaning, schema checks, and formatting.Local rules/regex/JSON validation; worker for token post-processing (e.g., markdown/HTML transforms).local, worker

Why use Hybrid-Compute?

Keep trivial logic at the edge; save LLM quota and latency.

Token Streaming & Live Rendering ​

Problem:Solution:Backends:
You want live UI updates while the model streams tokens.Use remote (WebSocket) to stream, worker to aggregate/refine chunks, local to render progressively.remote(ws) + worker + local

Why use Hybrid-Compute?

Each stage runs where it's best; a single runTask call coordinates it.

Hybrid Agent Tooling (LLM "tools") ​

Problem:Solution:Backends:
Agents need diverse tools (local utilities, remote services).Register tools as tasks across backends. Quick utilities local, CPU/IO-heavy worker, SaaS APIs remote.local, worker, remote

Why use Hybrid-Compute?

Tools become portable tasks with uniform invocation.

Media & Numeric Processing (WebAssembly) ​

Problem:Solution:Backends:
Images/vectors/audio transforms must be fast and portable.Compile to WebAssembly and run it in a worker (or local for quick calls) for native-like speed; remote only for large/batch jobs. See the WebAssembly guide.worker, local, remote

Why use Hybrid-Compute?

Swap implementations without changing call sites.

Offline-First & Flaky Networks ​

Problem:Solution:Backends:
Users lose connectivity mid-task.Run local/worker first; queue results and reconcile with remote when online.local, worker, remote

Why use Hybrid-Compute?

auto + capability checks enable graceful degradation.

Cost-Aware Routing ​

Problem:Solution:Backends:
Cloud compute is expensive; not all work needs a server round-trip.Prefer local/worker for pre-processing and summarization; call remote only for high-value tasks.local, worker, remote

Why use Hybrid-Compute?

Centralized routing policy; easy A/B on strategy.

Compliance & Data Locality ​

Problem:Solution:Backends:
PII/regulated data must not leave the device/region.Hash/aggregate/filter locally; send only safe aggregates to remote.local (guard rail), remote

Why use Hybrid-Compute?

Task boundaries become privacy boundaries.

Progressive Enhancement ​

Problem:Solution:Backends:
Users' devices differ widely in capabilities.Try worker; if unsupported, run local; if still insufficient, fall back to remote.worker → local → remote

Why use Hybrid-Compute?

The same runTask call adapts to the environment.

Multi-Tenant & Edge Offload ​

Problem:Solution:Backends:
You want tenant-isolated compute or edge acceleration.Route to nearest remote region; keep light transforms local/worker.local, worker, remote(fetch/ws)

Why use Hybrid-Compute?

Pluggable transports (HTTP/WS) and per-tenant endpoints.

Testability & Observability ​

Problem:Solution:Backends:
It's hard to test distributed logic.Swap in a mock local backend during tests; assert routing decisions and payloads.local (mock)

Why use Hybrid-Compute?

Backends are interfaces; DI by design.

Visual overviews ​

High-Level Package Architecture ​

Hybrid-Compute Core is the orchestration layer. It doesn't execute work itself; it routes tasks to whichever backend is available and appropriate. The Local backend runs tasks on the calling thread for minimal overhead, the Worker backend offloads work to a Web Worker to keep the UI responsive, and the Remote backend calls out to a server over HTTP or WebSocket. Each backend is pluggable and can be added or omitted depending on your deployment needs: each one depends on core and implements its ComputeBackendInterface, and core imports none of them.

The packages and their dependencies The local, worker and remote packages each depend on core and implement its ComputeBackendInterface. Core has no runtime dependencies. @hybrid-compute/core HybridCompute · interfaces @hybrid-compute/local LocalCompute @hybrid-compute/worker ThreadedCompute @hybrid-compute/remote RemoteCompute
Arrows point to what a package depends on. Each backend implements ComputeBackendInterface from core; core imports no backend.

Task Dispatch Flow (@hybrid-compute/core) ​

runTask(taskName, input, strategy) accepts a routing strategy. If you pass local, worker, or remote, the call goes to that backend, as long as it can run the task (its canRun returns true). With auto, Hybrid-Compute checks backend capabilities (i.e., whether a backend can run the named task) and selects one accordingly. In the diagram, the fallback order for auto is worker → local → remote. No matter which backend runs the work, you always get a Promise<Output> and a consistent error surface if no backend can handle the task.

How runTask reaches a backend The application calls runTask on core. With the local, worker or remote strategy, core uses that backend if it is configured and its canRun returns true. With auto, it uses the first backend whose canRun returns true, in the order worker, local, remote. If no backend matches, runTask rejects with a NoBackendError. Application runTask(name, input, strategy) core local · worker · remote that backend, if it is setand canRun(name) is trueautothe first backend whosecanRun(name) is true,in order: worker, local,then remoteno matchrejects with NoBackendError auto 1st auto 2nd auto 3rd worker Web Worker · postMessage local same thread remote fetch or WebSocket NoBackendError nothing can run the task
Every backend returns a Promise of the task's output.

Threaded Worker Lifecycle (@hybrid-compute/worker) ​

When the Worker backend is selected, Hybrid-Compute packages your request and posts a message to the Web Worker with { id, task, input }. The worker performs the computation and posts back { id, result } (or { id, error }); exposeTasks does that part for you. The Worker backend then resolves the original promise on the main thread, or rejects it with a WorkerTaskError. The worker starts on the first task, and a new one starts if it crashes. This separation keeps heavy computations off the UI thread while preserving a simple, promise-based API.

A task through the worker backend Your code calls runTask on ThreadedCompute, which posts a message with the task, input and an id to your worker script. The worker script posts back the id with a result or an error, and ThreadedCompute resolves or rejects the Promise. Your code main thread ThreadedCompute @hybrid-compute/worker Worker script your file runTask('resize', input) postMessage({ task, input, id }) { id, result } or { id, error } resolve(result) or reject(error)
The id matches each reply to its call, so several tasks can be in flight at once.

Remote Compute Flow (@hybrid-compute/remote) ​

The Remote backend abstracts transport details behind the same runTask() call. For Fetch, it sends a POST to the endpoint you configured, with JSON { task, input }, and resolves with the server's { result } (or surfaces { error }). For WebSocket, it sends { id, task, input } and correlates responses { id, result|error } to the originating request. In both cases an error in the reply rejects the Promise, so the calling code doesn't care how the work was transported.

The remote backend's two transports With fetch, RemoteCompute posts the task and input as JSON to the endpoint you configured, and reads a result or an error from the response. With WebSocket, it sends the task, input and an id on a socket it opens for the first task and reuses, and matches replies with the same id, carrying a result or an error. Both reject with a RemoteTaskError on failure, and time out after 30 seconds by default. transport: 'fetch' RemoteCompute runTask(name, input) POST { task, input } { result, error? } Your endpoint the URL you configured transport: 'websocket' RemoteCompute runTask(name, input) send { task, input, id } { id, result, error? } Your endpoint socket opened by the first task
An error in the reply, a failed request or the timeout (30 seconds by default) rejects the task with a RemoteTaskError.

Developer Experience ​

Hybrid Compute is a collection of ESM packages, served through npm.

It is Open Source, and easy to use.