Skip to content

Quickstart

This guide deploys a small Python handler and calls it from your laptop. You need Python 3.11 or newer, Docker, a Surfra account, and a cloud account such as RunPod or Salad connected under Credentials → Cloud accounts. The dashboard’s Get started page walks through the same steps and checks each one off as you go.

  1. Install the SDK and set your key.

    Create an API key in the dashboard under Credentials → API Keys, then:

    Terminal window
    pip install surfra
    export SURFRA_API_KEY=sfk_...
  2. Write a handler.

    @surfra.warmup runs once when a worker starts. @surfra.handler runs once per request. request.input is the JSON object the caller sent. Return anything JSON can encode.

    app.py
    import surfra
    greeting = None
    @surfra.warmup
    def load():
    global greeting
    greeting = "hello" # load model weights here
    @surfra.handler
    def predict(request: surfra.Request):
    name = request.input.get("name", "world")
    return {"text": f"{greeting} {name}"}
  3. Build an image.

    The image needs the surfra package and your file. Surfra starts the container with surfra worker, which imports app.py and runs the handler.

    Dockerfile
    FROM python:3.12-slim
    RUN pip install surfra
    WORKDIR /app
    COPY app.py .
    CMD ["surfra", "worker"]
    Terminal window
    docker build -t ghcr.io/you/hello:1 .
    docker push ghcr.io/you/hello:1

    A private registry needs a saved login. See Secrets and registries.

  4. Deploy.

    The name identifies the app. Deploying the same name again updates it in place.

    deploy.py
    import surfra
    app = surfra.App("hello")
    app.deploy(
    image="ghcr.io/you/hello:1",
    entrypoint="app.py",
    runtime={"engine": "python"},
    autoscale={
    "min_replicas": 0,
    "max_replicas": 2,
    "idle_timeout_sec": 300,
    "providers": [
    {"provider": "salad", "gpu": "cpu", "priority": 1, "vcpu": 2, "ram_gb": 4},
    {"provider": "runpod", "gpu": "cpu", "priority": 2, "vcpu": 2, "ram_gb": 4},
    ],
    },
    )

    The dashboard does the same thing. Open Serverless → New App, pick machines, and copy the generated SDK code from the side panel.

  5. Call it.

    print(app.run({"name": "Surfra"}, timeout=600))
    # {'text': 'hello Surfra'}

    The first call starts a replica, so it waits for the image to pull and warmup to finish. Later calls go to the warm replica until it has been idle for idle_timeout_sec.