This document outlines the design, architecture, and roadmap for building a Workers-like serverless runtime in Rust using deno_core. It includes all major components, goals, and a detailed TODO list.
A serverless runtime allows developers to write small JS/TS functions that respond to events (HTTP requests, timers, messages) in an isolated environment. This runtime will be self-hosted, portable, embeddable, and provide Web-like APIs similar to Cloudflare Workers but fully open-source.
- JS/TS function execution inside Rust runtime (deno_core)
- Async support
- Host ops (
fetch,KV, logging, etc.) - Hot-reload and local dev
- Isolate pooling and resource limits
- ES module / TypeScript support
- Optional WASM plugin support
HTTP(S) ──> Router ─┬─> Worker Isolate 1 (JS/TS)
│ - module loader
│ - async execution
│ - host ops (fetch, KV, crypto)
├─> Worker Isolate 2 (JS/TS or WASM)
└─> Worker Isolate N
-
Host server (Rust + axum/hyper)
- Accept HTTP requests
- Route requests to appropriate module
- Metrics, logging
-
Isolate manager
- Pools
deno_core::JsRuntimeisolates - Manages per-request execution
- Enforces memory/time limits
- Pools
-
JS Engine (deno_core)
- Embeds V8 engine
- Handles async JS execution
-
Module loader
- Loads ES modules
- Supports TypeScript via transpile (esbuild/swc)
- Handles caching and hot-reload
-
Host Ops
fetch(url): async HTTPconsole.log(...): loggingKV.get/set: simple key-value store (sled/SQLite)- Optional WebSocket, timers, crypto
-
Storage / KV
- sled/SQLite for persistent storage
- Durable Objects / per-resource actor pattern
-
Scheduler / Queue
- Timer events
- Background jobs / cron
-
CLI / Dev workflow
dev: local server with hot-reloadbuild: transpile/bundle TSpublish: package module
-
Deployment
- Self-hosted binary / container
- Optional edge deployment
- Registry for module sharing
export default {
fetch: function(req: Request){
const res = await fetch("https://api.example.com/data");
const json = await res.json();
await KV.put("last", JSON.stringify({ ts: Date.now() }));
return new Response(
JSON.stringify({ ok: true, data: json }),
{
headers: {
"Content-Type": "application/json"
}
}
);
}
}fetch(url: string) => Promise<Response>KV.get(key: string)KV.put(key: string, value: any)console.log(...args)crypto(optional)WebSocket(optional)- Timers:
setTimeout,setInterval
- Memory and execution time limits
- Network egress restrictions
- Filesystem isolation / VFS ops
- Secrets management (never inject into global scope)
- Per-tenant isolation
- Module integrity verification (signatures)
- Decide JS engine:
deno_core(V8) ✅ - Prototype embedding small runtime, executing
console.log('hi') - Benchmark startup and memory usage
- Setup axum/hyper HTTP server
- Load JS/TS files
- Execute JS module default export
- Return JSON response
- Add simple logging
- Implement
fetchhost op - Implement
console.logop - Implement persistent KV op with sled
- Implement secrets environment
- Make host ops async compatible
- Isolate worker
localhostand/or host address access - Make a config for db settings and alike called
worky.toml
- Integrate esbuild or swc for transpiling TS → JS
- Support source maps for better dev experience
- Hot-reload TS modules
- Properly load ES modules using
deno_coremodule loader - Support async default exports
- Handle errors and exceptions properly
- Create isolate pool
- Enforce per-isolate memory limit
- Enforce per-request timeout
- Support concurrent requests
-
devcommand: run local server with hot-reload -
buildcommand: bundle TS modules -
publishcommand: package module for deployment
- Implement per-resource KV namespaces
- Optional actor pattern for durable objects
- Evaluate SQLite/sled/RocksDB backend
- Add tracing for request/response
- Metrics: latency, active isolates, KV ops
- Optional Prometheus integration
- Support WASM modules as plugins
- Integrate with isolate pool
- Provide host ops to WASM modules
- Containerize runtime
- Define bundle manifest.json for modules
- Registry for module sharing and versioning
- CLI commands for uploading/downloading modules
- Start small: Milestone 1–2 is enough for a working local dev runtime.
- Use QuickJS or V8 in
deno_coredepending on performance needs. - Hot reload is critical for TS/JS development iteration.
- Host ops are the bridge between Rust and JS; async ops allow real-world usage (HTTP, KV, timers).
- Security must be considered from day 1: isolation, memory limits, secrets, egress policy.