Keep the Ruby shape
A familiar call(env) entrypoint and a Rack response tuple let application code stay recognizably Ruby.
A small Ruby runtime for a very large edge
Write a Rack-style application in PicoRuby. Compile it to WebAssembly. Run it inside Cloudflare Workers, close to every request.
class App
def self.call(env)
[200, { "content-type" => "text/plain" },
["Hello from the edge"]]
end
end
01 — THE POSSIBILITY
PicoRuby brings a compact Ruby implementation to WebAssembly. The adapter connects familiar Ruby application shapes to Cloudflare’s global runtime and request-scoped platform bindings.
A familiar call(env) entrypoint and a Rack response tuple let application code stay recognizably Ruby.
Use D1, KV, R2, Workers AI, Vectorize, Queues, Durable Objects, Access, and Web Crypto from request-scoped Ruby wrappers.
Precompiled bytecode, one VM per request, and explicit compatibility boundaries make the runtime understandable and testable.
02 — GETTING STARTED
Install the generator gem and create a minimal Worker project. The CLI writes the Ruby app, build configuration, Worker entrypoint, package manifests, and Wrangler configuration for you.
gem install picoruby-cloudflare-templatepicoruby-cloudflare new hello-edgecd hello-edge
bundle install && npm installexport PICORUBY_ROOT=/path/to/picoruby
npm run dev03 — RACK & SINATRA
The runtime implements the Rack application protocol—an environment Hash in, a [status, headers, body] tuple out. It is not the complete CRuby Rack distribution.
class App
def self.call(env)
name = env["PATH_INFO"].split("/").last
[200,
{ "content-type" => "text/plain" },
["Hello, #{name}!"]]
end
end
Rackup::Handler::CloudflareWorker.run(App)
class App < Sinatra::Base
get "/hello/:name" do
content_type "text/plain"
"Hello, #{params[:name]} from PicoRuby"
end
end
Rackup::Handler::CloudflareWorker.run(App)
The Sinatra profile intentionally disables sessions, rack-protection, logging middleware, static files, templates, and development reloading.
04 — CLOUDFLARE BINDINGS
Bindings stay in the Worker env. The request receives typed Ruby wrappers through env["cloudflare.env"], with asynchronous calls bridged by JSPI.
Keep SQL and values separate with an explicit prepared-statement flow.
Query, insert, upsert, inspect, and delete vectors using JSON-compatible values.
Send UTF-8 messages and process batches with ack, retry, and Rack-style middleware.
Store JSON-compatible POJOs in named Durable Object instances.
Resolve Cloudflare Access identity and place it in the Rack environment.
Use Web Crypto-backed random bytes and AES-GCM instead of pseudo-randomness.
Make buffered HTTP calls and read variables or secrets from request scope.
05 — EXAMPLES
The repository includes runnable applications that combine PicoRuby, Sinatra, Static Assets, and Cloudflare resources.
Static Assets serves the UI; the Worker routes /api/* to Sinatra and D1.
Pass a host-owned SSE stream straight to the browser, including cancellation.
Embed documents, retrieve sources, and stream a grounded answer with citations.
06 — KEEP EXPLORING