Sovereign serverless compute

The cloud,
without the cloud.

Decorate a Python function. It runs on hardware you own — no Dockerfile, no cluster, no bill. The Modal model, pointed at your fleet.

trainer.py
# one decorator. your node. the answer comes home.
import roost

app = roost.App("trainer")

@app.function(gpu="fleet:jl1")
def train(shard):
    import platform
    return {"ran_on": platform.node(), "shard": shard}

train.remote(shard=0)          # blocks, hands you the result
train.map([0, 1, 2, 3])        # fans out across the fleet
job = train.spawn(shard=7)     # detached; job.get() later
ran_on jl1 venv cached · source shipped · result pickled home
It runs on the metal you already own
your laptop
jl1
jl2
Nova
AXeServer
the whole fleet
Why it feels like nothing

You write the function. That’s the whole job.

Everything the cloud made you do — the image, the registry, the cluster, the YAML — roost simply removes.

01

Bring your code. Nothing else.

No image to build. No registry to push. The function ships as source, your data pickles, the result comes home. A laptop on Python 3.11 can drive a node on 3.14 — because roost never ships a code object, only what runs everywhere.

@app.function(gpu="fleet:jl1")
def embed(batch):
    from model import encode  # local import, shipped
    return encode(batch)

embed.remote(batch)
02

One node, or all of them.

Call it once and block. Or fan a whole sweep across the fleet in parallel — results returned in order. Or spawn it, pocket the receipt, and let your laptop go back to being a laptop.

.remote(x)one node, one answer
.map([…])the sweep, in parallel, in order
.spawn(x)a handle; .get() when you want it
03

Provisioned once. Reused forever.

An image spec hashes to a venv, cached on each node. Change nothing and it never builds again. Change one line and only that node reprovisions. No warm pools to babysit, no cold-start tax to pay twice.

Image(pip=[torch]) a1f9c2… venv, cached per node
The bill, in full
$0
metered to the cloud, ever
1
decorator to make a function fleet-callable
0
bytes that leave your SSH mesh
nodes, when the nodes are yours

The whole surface.

Small enough to hold in your head. That’s the point.

roost.App(name)A namespace for related functions that share a default image.
@app.function(…)Makes a function fleet-callable. Set gpu, image, volumes, timeout.
.remote(*a)Run it on the fleet. Block for the result.
.map(iter)Fan inputs across nodes in parallel; results returned in order.
.spawn(*a)Fire and forget. Returns a handle; .get() collects it later.
roost.ImageA content-addressed env: base + apt + pip, hashed to a venv cached per node.
roost.Volume(name)A directory that persists on a node across runs — weights, datasets, caches.

Your laptop is the dashboard.

Every call is written to a local ledger — metadata, timing, results, and the worker’s full stdout and stderr, on success or on failure. No web console to log into. It is all on the machine you already trust.

$ roost runs
StatusTargetDurFuncRun
successfleet:jl127.6straintrain-jl1-1787892153-1
runningfleet:jl2traintrain-jl2-1787892160-2
successlocal0.5sevaleval-local-1787892102-0
$ roost logs train-jl1-1787892153-1  ·  meta.json + stdout + stderr, retained

Your fleet is waiting.

One decorator away from serverless on the hardware you already own.