Backend runtime · Rust · WebAssembly

The backend that shows its work.

Write operations in Rust. fncosmos runs each one in its own sandbox, records every step it takes, and puts the values right next to your code.

trigger POST /notes { "text": "ship it" }
notes:add
let db = ctx.resource("db")?;
db.transaction("insert", |tx| {
  tx.query_opt("insert …", …)
})
✓ attempt 1 · 4.2 ms
journal #0 sql1 row reply201 · id 42

How it works

An operation is a function and what triggers it.

src/lib.rs
// Declared with a builder, read when you deploy.
operation("my-notes")
    .http("GET", "/me/notes")
    .authenticated()
    .handler(|ctx, _: ()| {
        let user = ctx.require_auth()?;
        ctx.resource("db").query_as::<Note>(
            "select * from notes where owner = $1",
            &[user.subject.into()],
        )
    })
web/src/app.ts
import { createAuthClient } from "@fncosmos/client";
import { createClient } from "./fncosmos.ts"; // generated

const auth = createAuthClient({ url: AUTH_URL });
const api = createClient({ baseUrl, token: auth.token });

auth.signInWith("github");
const notes = await api.notes.myNotes(); // Note[]
  1. Deploy a module compiled to WebAssembly. Its routes and schedules go live at once.
  2. Trigger it over HTTP, on a schedule, or from the CLI. Every trigger is a run.
  3. Watch each attempt: its steps, logs, values and how it ended. Rerun any run on new code.

Durable by default

Steps, fetches, SQL and sleeps are journaled. A retry replays what already happened instead of doing it twice, and a run can sleep for days and survive restarts.

A sandbox per attempt

Every attempt runs in a fresh WebAssembly instance with its own memory and CPU limits. Outgoing requests pass a network fence. Many projects share one process safely.

HTTP, cron, or by hand

One builder declares an operation and what triggers it: its own route, a schedule, or a call from the CLI. Public, keyed, signed-in or internal-only.

Postgres, built in

Pooled connections, queries journaled like any other step, transactions that replay once committed, migrations on deploy, and row types generated from the database.

Typed end to end

Argument and result types come from your Rust code. One command writes a TypeScript client where a wrong argument is a compile error.

Sign-in included

Passwords, Google and GitHub, from fncosmos auth or any OpenID provider. Mark an operation .authenticated() and read the user with ctx.auth().

Coming next

The canvas.

The journal, the attempts and every step's values are exactly what a canvas needs: code next to the data it saw, wires between triggers and tables, and replay of any request. That's where fncosmos is headed.

Join the early access