NOETRION

Browse by topic

← All articles
TECHNOLOGY · 12 MIN READ

WebAssembly explained: how a database, editor, or game can run inside your browser

Understand Wasm modules, JavaScript glue, linear memory, workers, browser security, performance, and practical limits.

Reviewed September 30, 2026. This guide reflects WebAssembly 3.0 and current browser APIs. Individual features still require compatibility checks.

Editorial illustration of compiled code running in a protected browser sandbox to power local analytics.
WebAssembly is a portable executable format inside a host environment. The browser still controls its memory, network, storage, and device access.

A web page can now run a SQL database, video codec, image editor, scientific simulation, or language runtime without sending every computation to a server. One technology behind these applications is WebAssembly, or Wasm.

WebAssembly is a safe, portable, low-level code format with a compact binary representation. It is a compilation target for languages such as C, C++, Rust, C#, and others. It complements JavaScript rather than replacing HTML, CSS, browser APIs, or application design.

From source code to a browser feature

Source language
Rust, C++, or another language
→Compiler
Produces .wasm
→Browser engine
Validates and instantiates
⇄JavaScript and Web APIs
UI, files, network
A Wasm module exposes functions and can receive imported capabilities from the host. It does not directly control the page by default.

The browser fetches the binary module, validates it, compiles it for the current machine, and creates an instance. JavaScript can call exported Wasm functions. A module can call functions deliberately imported from JavaScript.

Four pieces to understand

PieceRolePractical meaning
ModuleCompiled, stateless Wasm code.Can be cached or shared before instantiation.
InstanceA module plus its runtime state and imports.Exposes callable exports to JavaScript.
MemoryA linear array of bytes.JavaScript and Wasm can exchange structured data through agreed layouts.
TableA typed collection of references.Supports indirect calls and integration patterns.

Strings, objects, and browser elements do not automatically cross the boundary as rich JavaScript values. Toolchains generate “glue” code to encode data into linear memory, call Wasm, and decode the result. Crossing that boundary has a cost, so a useful design performs meaningful batches of work rather than bouncing tiny operations back and forth.

Why Wasm can be fast—but is not automatically faster

The format is designed for efficient decoding, validation, and execution using common hardware capabilities. Compilers can bring mature native libraries to the web. Predictable numeric loops, codecs, compression, database operators, and simulations are strong candidates.

Performance still depends on the workload and implementation:

  • Modern JavaScript engines already optimize hot code aggressively.
  • Copying data and converting strings across the JS–Wasm boundary can dominate small tasks.
  • A large module increases download, compilation, and startup time.
  • Memory limits and single-thread defaults may constrain browser builds.
  • Threads require workers and, for shared memory, additional security headers and browser support.

Benchmark the complete user task on representative devices. A microbenchmark of one function cannot capture loading, parsing, memory transfer, and rendering.

The sandbox is a boundary, not a magic shield

WebAssembly runs inside the browser's security model. It follows same-origin and permissions policies. A module does not receive arbitrary filesystem, camera, network, or DOM access merely because native code was compiled into it. The host must import or expose capabilities.

ClaimAccurate interpretation
“Wasm is sandboxed.”The engine confines execution and mediates host access. Vulnerabilities in the surrounding application, imported functions, or browser still matter.
“Data stays local.”Only if the application does not upload it. Wasm code can use network functions that the host provides.
“It is memory safe.”The sandbox protects the host from arbitrary native memory access. A program can still contain logic errors or corrupt data inside its own linear memory.
“Wasm replaces JavaScript.”Most browser apps use JavaScript or a framework for UI and Web APIs, with Wasm for selected computation.

Why heavy work belongs in a Web Worker

The browser's main thread handles input, layout, and painting. A long database query on that thread can freeze scrolling and buttons even if the code itself is fast. Web Workers run scripts in a separate thread and communicate through messages.

Main thread
  1. Render controls
  2. Receive user input
  3. Send a query message
  4. Display returned rows
Worker
  1. Own the Wasm instance
  2. Load or register data
  3. Run the heavy operation
  4. Return compact results

This separation improves responsiveness, but transferring large data can still cost time and memory. Prefer transferable buffers, streaming, or compact result sets when the library supports them.

A concrete example: DuckDB-Wasm

DuckDB-Wasm compiles the analytical DuckDB engine to WebAssembly. Its documentation describes a browser client that executes SQL locally with no server round-trip. It uses Apache Arrow to exchange typed columnar data with JavaScript and can read CSV, JSON, and Parquet through its virtual filesystem.

This architecture powers Noetrion's SQL Playground: the browser loads the engine, registers a local dataset, runs a query in a worker, and renders the returned table. The dataset is not uploaded to a Noetrion database.

// Simplified architecture, not a complete application
const worker = new Worker(workerUrl)
const db = new duckdb.AsyncDuckDB(logger, worker)
await db.instantiate(wasmModule)

const connection = await db.connect()
const result = await connection.query(
  "SELECT category, AVG(price) FROM dataset GROUP BY category"
)

Browser limits still apply. DuckDB documents single-thread operation by default, experimental multithreading, memory limits, and CORS rules for remote files. A native server remains better for datasets that exceed the user's device or need shared concurrency.

Good and poor fits

Strong candidateWhyPossible alternative
Image, audio, and video processingCompute-heavy kernels and reusable native libraries.Web APIs or server processing for small or occasional tasks.
Database and analytical enginesTyped, vectorized computation close to local data.Server database for shared, large, or concurrent work.
Games and simulationsExisting engines and predictable numeric workloads.JavaScript for lightweight scenes.
Editors, compilers, and language runtimesPort mature tooling to a browser workspace.Server execution when secrets or controlled infrastructure are required.

A simple form, content page, or small JSON transformation rarely needs Wasm. Shipping a multi-megabyte runtime for a task JavaScript can finish instantly makes the experience worse.

Deployment checklist

  1. Measure module size, startup time, peak memory, and end-to-end task time.
  2. Feature-detect the required Wasm capabilities and provide a clear fallback.
  3. Serve the correct MIME type and configure caching deliberately.
  4. Use a worker for long operations and design cancellation where possible.
  5. Define which imports grant network, storage, clock, randomness, or device access.
  6. Apply Content Security Policy and cross-origin isolation only with an understood threat model.
  7. Keep third-party runtimes updated and publish their licenses.
  8. Tell users accurately whether files remain local and which resources load from third parties.

WebAssembly expands what a browser can execute efficiently. The best applications use it as one component in a transparent architecture: JavaScript coordinates the interface and Web APIs, workers protect responsiveness, and the host grants only the capabilities the module actually needs.