Virke Run

Run JavaScript/TypeScript or Rust at the edge on dedicated Fastly Compute services. Build APIs, server-side rendering, and real-time processing with sub-millisecond warm response times.

Performance

Metric JavaScript/TypeScript Rust
Cold start 50–200ms 10–50ms
Warm response 1–5ms < 1ms
Binary size ~2–5 MB ~500 KB–1.8 MB

Quick Start

Create a compute project

mkdir my-api && cd my-api
virke init --type compute

Write your first edge function

Create src/worker.ts:

import { Hono } from "hono";
import { virke } from "@virke/runtime/hono";

const { fire, middleware, Bindings } = virke({});
const app = new Hono<{ Bindings: typeof Bindings }>();

app.use("*", middleware);

app.get("/", (c) => c.json({ message: "Hello from the edge!" }));

app.get("/headers", (c) => {
  return c.json({
    ip: c.req.header("Fastly-Client-IP"),
    geo: c.req.header("X-Geo-Country"),
    pop: c.req.header("X-Served-By"),
  });
});

fire(app);

Deploy

virke deploy

JavaScript / TypeScript

Virke Run uses Hono as the recommended web framework, with the @virke/runtime/hono adapter providing Virke-specific bindings.

bun add hono @virke/runtime

Hono adapter

The virke() function returns three things:

  • fire — Starts the Fastly Compute fetch handler
  • middleware — Hono middleware that injects Virke bindings into c.env
  • Bindings — TypeScript type for c.env

Full-stack example

import { Hono } from "hono";
import { virke } from "@virke/runtime/hono";

const { fire, middleware, Bindings } = virke({
  db: "my-app-db",
  kv: "my-app-kv",
  os3: "my-app-assets",
});

const app = new Hono<{ Bindings: typeof Bindings }>();
app.use("*", middleware);

// Database queries
app.get("/users", async (c) => {
  const result = await c.env.db.query("SELECT * FROM users");
  return c.json(result.rows);
});

// KV cache
app.put("/cache/:key", async (c) => {
  const body = await c.req.text();
  await c.env.kv.set(c.req.param("key"), body, { ttl: 3600 });
  return c.json({ ok: true });
});

// File uploads
app.put("/files/:key", async (c) => {
  const body = await c.req.arrayBuffer();
  await c.env.os3.put(c.req.param("key"), body);
  return c.json({ ok: true });
});

fire(app);

Without Hono (addEventListener style)

import { virkeEnv } from "@virke/runtime";

const env = virkeEnv({ db: "my-db", kv: "my-kv" });

addEventListener("fetch", async (event) => {
  const url = new URL(event.request.url);

  if (url.pathname === "/users") {
    const result = await env.db.query("SELECT * FROM users");
    event.respondWith(
      new Response(JSON.stringify(result.rows), {
        headers: { "Content-Type": "application/json" },
      })
    );
    return;
  }

  event.respondWith(new Response("Not Found", { status: 404 }));
});

Rust

use fastly::{Error, Request, Response};

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    match (req.get_method_str(), req.get_path()) {
        ("GET", "/") => {
            let body = serde_json::json!({
                "message": "Hello from the edge!",
                "pop": req.get_header_str("X-Served-By")
                    .unwrap_or("unknown"),
            });
            Ok(Response::from_body(body.to_string())
                .with_content_type(fastly::mime::APPLICATION_JSON))
        }
        _ => Ok(Response::from_status(404)),
    }
}

Accessing Storage

Binding Access Pattern Latency
env.db SQL via service chaining to virke-api 9–120ms reads, 430+ms writes
env.kv Direct Fastly KV Store SDK 4–10ms reads, ~450ms writes
env.os3 SigV4-signed HTTP to Object Storage 2–12ms reads (cached)

virke.toml Configuration

[project]
name = "my-api"

[compute]
entry = "src/worker.ts"     # entry point file
language = "javascript"      # "javascript" or "rust"

# Optional: attach storage resources
[database]
name = "my-api-db"

[kv]
namespace = "my-api-kv"

[storage]
bucket = "my-api-assets"

Local Development

virke dev              # starts Viceroy (Fastly's local emulator)
virke dev --port 8080  # custom port

Canary Deployments

Compute projects support canary deployments using Fastly's native service versioning.

virke canary start-compute <weight>   # start with % traffic
  --service-version <version>        #   Fastly service version (required)
  --no-sticky                        #   disable sticky sessions
virke canary adjust <weight> --compute  # adjust traffic
virke canary promote --compute          # promote canary version
virke canary abort --compute            # revert to stable
virke canary status                     # show canary status

Further Reading

  • Framework Support — Next.js, SvelteKit, Remix, and Astro adapters
  • Virke Components — Portable WebAssembly Component Model
  • Virke Cron — Schedule recurring tasks on Virke Run projects
  • Virke DB — Using Virke DB from edge functions
  • Virke KV — Using Virke KV from edge functions
  • Virke OS3 — Using Virke OS3 from edge functions
  • CI/CD Guide — Automated deployment for Virke Run projects