Skip to content

Functions

View Markdown

A Function is a Python function that runs on Nodus workers. You decorate it, call it from your own code with .remote(), .map() or .spawn(), and Nodus starts workers when calls arrive, keeps them warm for a while and scales them back down. The pages of this guide cover calling Functions, scaling them and what is billed while a worker waits.

An App is the group of Functions in one file. nodus run creates an ephemeral App, runs your main on your machine and deletes the App when main returns. Every .remote() call runs on a Nodus worker.

examples/functions/map/app.py
"""One Function called three ways, then mapped over a thousand inputs.
Run it with `nodus run examples/functions/map/app.py`.
"""
import nodus
app = nodus.App("fn-map")
@app.function(cpu=1, memory="1Gi", max_workers=4, target_concurrency=8, max_cost=1)
def square(x: int) -> int:
return x * x
@app.function(cpu=1, memory="1Gi", max_cost=1)
def divide(a: int, b: int) -> float:
return a / b
@app.local_entrypoint()
def main(n: int = 1000) -> None:
print("remote:", square.remote(7)) # one call; blocks for the result
call = square.spawn(8) # starts a call and returns a handle
print("spawned:", call.get(timeout=600))
results = list(square.map(range(n))) # one call per input, results in input order
print("map:", len(results), "ordered:", results == [i * i for i in range(n)])
try:
divide.remote(1, 0)
except ZeroDivisionError as exc: # the remote exception comes back as its own type
print("raised:", type(exc).__name__)
Terminal window
$ nodus run examples/functions/map/app.py
remote: 49
spawned: 64
map: 1000 ordered: True
raised: ZeroDivisionError

The directory of the file (minus what .gitignore and .nodusignore exclude) is uploaded once per content hash, so the workers import the same code you ran. The App renews itself while main runs and is deleted shortly after main stops, even when your machine loses its connection.

nodus deploy keeps the App. Its Functions stay available after your program exits, and any program can call them.

examples/functions/warm-pool/app.py
"""A Function that keeps one worker warm, so a call never waits for a start.
Deploy it with `nodus deploy examples/functions/warm-pool/app.py`. The idle worker is billed at the Function's
worker rate for as long as it stays warm; set `min_workers=0` to pay only while calls run.
"""
import nodus
app = nodus.App("fn-warm")
@app.function(cpu=1, memory="1Gi", min_workers=1, max_workers=3, scaledown_window="2m", max_cost=1)
def ping() -> str:
return "pong"
Terminal window
$ nodus deploy examples/functions/warm-pool/app.py
import nodus
ping = nodus.Function.from_name("fn-warm", "ping")
print(ping.remote()) # pong

A deploy updates the App in place. A Function whose code, image or resources changed rolls its workers once, after their in-flight calls finish. A Function you removed from the file is deleted, and the calls it still had queued end as Failed with the reason FunctionDeleted, so no caller waits for a call nobody will run.

Object What it is Look at it with
App The Functions of one file; ephemeral for run, persistent for deploy nodus get apps
Function One decorated function or class, with its image, resources and scaling nodus get functions
FunctionCall One invocation, kept for seven days after it ends nodus get functioncalls -l nodus.dev/function=fn-warm-ping

A Function reports its state in status.phase, how many workers it has in status.workers, how many calls wait in status.queue, and the expected start time in status.estimate.

Terminal window
$ nodus get function fn-warm-ping
NAME PHASE WORKERS QUEUED COST AGE
fn-warm-ping Running 1/3 0 $0.02 3m
Terminal window
$ nodus stop function/fn-warm-ping # drain the workers; new calls wait in the queue
$ nodus start function/fn-warm-ping # start workers again for the calls that waited
$ nodus restart function/fn-warm-ping # replace every worker once, after in-flight calls finish
$ nodus delete app/fn-warm

A stopped Function keeps accepting calls and holds them in the queue, so work you submit while it is stopped runs once it starts. Workers also stop by themselves when your balance cannot cover another renewal; calls queue until you add credit and then run.