{"slug": "your-browser-is-quietly-an-operating-system-the-4-webassembly-engines-in-our", "title": "Your browser is quietly an operating system: the 4 WebAssembly engines in our extension", "summary": "AWFlow, a browser-native automation tool, runs four WebAssembly engines inside a single Chrome extension with no backend for its core features: SurrealDB (compiled from Rust) as a local database persisting to IndexedDB, ONNX Runtime Web (C++) for task models via transformers.js, WebLLM from the MLC project for chat LLMs on the user's GPU via WebGPU, and Pyodide (CPython) for a Python Code node. The AI engines run in dedicated Web Workers so downloading or compiling a 2 GB model does not freeze the UI, and ONNX Runtime Web uses WebGPU where the GPU path is known to work for a task and WASM otherwise. The architecture means workflows, run history, agents and knowledge stay in the user's browser, with no server to run and no account required.", "body_md": "Your browser is quietly an operating system: the 4 WebAssembly engines in our extension\n\nOne Chrome extension, no backend for its core features: a real database, two AI inference engines and a full Python interpreter, all running as WebAssembly. What each engine does, how it's wired, and what it costs.\n\nUnder the hood is a series about how AWFlow, a browser-native automation tool, works inside. This is #2.\n\nAWFlow has no backend for its core features. Yet a single Chrome extension runs a real database, two AI inference engines and a full Python interpreter. All four are possible because of WebAssembly. Here’s what each one does, how it’s wired up, and what it costs.\n\nThe browser has the parts of an OS\n\nWebAssembly (WASM) is a binary format that languages like Rust, C and C++ compile to. The browser runs it at close to native speed, inside the same sandbox as any web page: no install and no system access. If you want the plain-words tour of how that works, WebAssembly, explained covers it; this post is about what we built on top.\n\nFor a product like ours, it changes the architecture. Instead of running engines on a server and sending users’ data to them, we ship the engines to the user. And the browser already has the pieces an engine expects from an operating system:\n\nHere are the four engines, from the bottom of the stack to the top:\n\nEngine\n\nCompiled from\n\nWhat it does in AWFlow\n\nSurrealDB\n\nRust\n\nThe local database: workflows, run history, agents, knowledge\n\nONNX Runtime Web\n\nC++\n\nLocal AI tasks via transformers.js: classify, summarize, translate, transcribe, embed\n\nWebLLM (MLC)\n\nWASM runtime + WebGPU\n\nChat LLMs on the user’s GPU\n\nPyodide\n\nCPython\n\nReal Python for the Code node\n\nThree engines that used to need a server\n\nSurrealDB: a database you ship to the user\n\nSurrealDB’s WASM build includes a storage engine that persists to IndexedDB. Using it looks like using a remote database, except the address is local:\n\n``` js\nimport { Surreal } from 'surrealdb';\nimport { createWasmEngines } from '@surrealdb/wasm';\n\nconst db = new Surreal({ engines: { ...createWasmEngines() } });\nawait db.connect('indxdb://<local-db-name>');\nawait db.use({ namespace, database });\n```\n\nTwo design choices worth copying:\n\nOne long-lived connection. The local database is a singleton that stays open for the life of the app. The init promise is cached, so concurrent callers share one connection instead of racing to create two.\n\nSame engine, more uses. The same SurrealDB setup also backs our local knowledge bases and vector search.\n\nThis is the reason AWFlow works with no account: your workflows and history live in your browser from the first second.\n\nTwo places engines can live\n\nThe classic way: the database, the AI and the code runner sit on a server.\n\nYour data travels\n\nEvery query, prompt and script goes over the network to that server.\n\nResults come back\n\nThe server answers, every time.\n\nSomeone runs that server\n\nSo there is a server to scale and secure, and an account to create before you start.\n\nShip the engines instead\n\nPut the engines in the browser and the trip disappears: no server for us to run, no account to start, no data to send.\n\nONNX Runtime Web and WebLLM: two AI engines, each in a worker\n\nONNX Runtime Web, through transformers.js, runs task models: classification, summarization, translation, speech-to-text, embeddings. For each task it uses WebGPU if the GPU path is known to work for that task, and WASM otherwise.\n\nWebLLM (from the MLC project) runs chat models. Its runtime is WebAssembly, and the heavy math runs as WebGPU kernels on the user’s graphics card.\n\nBoth run in dedicated Web Workers, so downloading or compiling a 2 GB model never freezes the UI. (TensorFlow.js is in the mix too, for a few vision and classic models, but it uses WebGPU, WebGL or CPU backends, so it isn’t one of the four WASM engines.)\n\nThe MV3 trap we hit is covered in detail in Running LLMs inside a Chrome extension: ONNX Runtime fetches its WASM files from a CDN by default, and an extension’s CSP (script-src 'self' 'wasm-unsafe-eval') forbids that. You have to ship the runtime files inside the extension and point the library at them.\n\nReal Python, locked in a box\n\nRunning user-supplied Python (possibly from a workflow someone else shared) inside your browser needs isolation, so the design is layered:\n\nIn more detail:\n\nIts own worker. Python never runs in the app page. A worker has no DOM, no chrome.* APIs and no page state.\n\nA restricted js module. Pyodide normally exposes the host’s globalThis to Python. We replace it with a tiny allow-list, and stub out pyodide.http.\n\nCapabilities removed after boot. Once the interpreter has loaded, the worker’s own network, storage, messaging and nested-worker globals are deleted, as defense in depth.\n\nA fresh interpreter per run. Reusing one and resetting its namespace would let one run’s code hook the next run’s input. So every run gets a new interpreter.\n\nTimeouts that actually stop the code. On timeout or abort, the worker is terminated. We don’t just stop waiting for it.\n\nA fresh interpreter takes about 2 seconds to boot with a warm cache (around 5 seconds cold), so we keep one pre-warmed spare: a worker that has loaded Pyodide but never run user code. Each run takes the spare and immediately starts warming the next one. An unused spare is shut down after a minute.\n\nWhat it costs, and what it buys\n\nShipping engines to the browser isn’t free. Here is what it costs us and how we handle each cost:\n\nCost\n\nHow we handle it\n\nExtensions can’t load code from a CDN\n\nEvery WASM runtime ships inside the extension\n\nEngines are heavy\n\nEach one is lazy-loaded the first time it’s used (a test checks the heavy dependencies stay out of the main bundle)\n\nModels are big downloads\n\nDownloaded once, cached, visible and deletable in a Local Models page\n\nNot every machine has WebGPU\n\nAlways a WASM or CPU fallback\n\nAnd what it buys:\n\nNo server for us to run, scale or secure, and none for users to trust.\n\nNo account needed to start.\n\nNo data sent: prompts, pages and workflow data can stay on the machine.\n\nThe easiest way to see the local database at work is to build a first workflow without signing in. This docs example reads the text you select on a page and shapes it into fields; it is saved in the browser’s local database the moment you create it.\n\nIf you’re building a browser extension or a local-first web app, the takeaway is that the browser is now a credible runtime for “server” components.\n\nNext in the series: how WebLLM turns your GPU into an AI server. AWFlow is free to install.", "url": "https://wpnews.pro/news/your-browser-is-quietly-an-operating-system-the-4-webassembly-engines-in-our", "canonical_source": "https://awflow.io/blog/your-browser-is-quietly-an-operating-system", "published_at": "2026-10-15 00:00:00+00:00", "updated_at": "2026-10-21 22:12:57.374473+00:00", "lang": "en", "topics": ["ai-tools", "ai-infrastructure", "large-language-models", "developer-tools"], "entities": ["AWFlow", "SurrealDB", "ONNX Runtime Web", "WebLLM", "MLC", "Pyodide", "transformers.js", "Chrome"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/your-browser-is-quietly-an-operating-system-the-4-webassembly-engines-in-our", "markdown": "https://wpnews.pro/news/your-browser-is-quietly-an-operating-system-the-4-webassembly-engines-in-our.md", "text": "https://wpnews.pro/news/your-browser-is-quietly-an-operating-system-the-4-webassembly-engines-in-our.txt", "jsonld": "https://wpnews.pro/news/your-browser-is-quietly-an-operating-system-the-4-webassembly-engines-in-our.jsonld"}}