Skip to Content
We are live but in Staging 🎉
ComputeQuickstart

Quickstart

Five minutes from here you’ll have a Python app running as an auto-scaled pod, published as an immutable version, and answering invokes — over both the API and the app’s own direct FQDN.

We’ll use the managed Python runtime: you write one file with a handler function, the platform compiles it and runs the HTTP server for you. (For bring-your-own-image — your own FastAPI/Flask server in a container — see Concepts → Code source.)

Prerequisites

  • The dodil CLI installed and authenticated — set your token and endpoint with dodil ignite config set token <token> and dodil ignite config set api_endpoint rpc.dev.dodil.io:443 (or export DODIL_TOKEN=<token>). See CLI Basics.
  • Your org name. App IDs are org:name on the CLI (the org: prefix is optional once your org is in config). We’ll use acme-corp below.

1. Write the handler

The managed runtime loads a top-level handler from handler.py. The contract is:

def handler(payload: bytes, ctx: dict) -> Any
  • payload is the raw request body (bytes) — you parse JSON yourself.
  • ctx carries the execution context: execution_id, function_id (org/name), organization_id.
  • The return value is encoded for you: a dict/list becomes JSON, a str becomes UTF-8 text, bytes are sent as-is.

Create handler.py:

import json from datetime import datetime, timezone def handler(payload, ctx): # The runtime hands you the raw body; parse it yourself. try: event = json.loads(payload) if payload else {} except (TypeError, ValueError): event = {} name = event.get("name", "world") return { "greeting": f"Hello, {name}!", "execution_id": ctx.get("execution_id", ""), "received_at": datetime.now(timezone.utc).isoformat(), }

That’s the whole app. You do not write an HTTP server, bind a port, or import an SDK — the managed runtime wraps handler in its own server and binds $PORT for you.

Only packages pre-installed in the runtime (numpy, pandas, requests, httpx, pydantic, boto3, …) are importable in the default pool mode. To add your own dependencies, see Recipes → Deploy a Python app.

2. Create the app

This registers the app’s metadata (name, runtime, resources) — no code yet.

dodil ignite app create greet --runtime python

The app id is now acme-corp:greet. Use that ID for every command that follows.

3. Save the code to the draft slot

draft save uploads your code into the mutable draft (version 0):

dodil ignite draft save acme-corp:greet -c ./handler.py

4. Publish

Publishing snapshots the draft into an immutable, numbered version and points the app’s active_version at it. Python needs no separate compile step.

dodil ignite draft publish acme-corp:greet

After the first publish the app gets a direct FQDN`greet-acme-corp.ignite.dodil.cloud` (port 80). Confirm it landed:

dodil ignite app get acme-corp:greet -o json | jq '{active_version, public_urls}'

5. Invoke

dodil ignite invoke acme-corp:greet -p '{"name": "Ada"}'

You’ll get back the handler’s JSON:

{ "greeting": "Hello, Ada!", "execution_id": "01J...", "received_at": "2026-05-28T12:00:00+00:00" }

You can also hit the direct FQDN with any HTTP client — still Bearer-authed:

curl -sS -X POST "https://greet-acme-corp.ignite.dodil.cloud/" \ -H "Authorization: Bearer $DODIL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Ada" }'

First call may pause. Idle apps scale to zero. The first request to a cold app waits while a pod starts (0→1), then proceeds — it isn’t rejected. Details in API Reference → Cold starts vs warm pods.

6. Check the execution

Every invoke produces an execution record with status and metrics. dodil ignite invoke prints the execution id; fetch its details:

dodil ignite execution get <exec-id>

You’ll see the status (COMPLETED), the result, and metrics (including cold_start_ms and billed_duration_ms).

What you just built

StepCLI commandWhat happened
2app createApp metadata created (version 0, no code)
3draft saveCode uploaded to the draft slot
4draft publishDraft snapshotted into immutable version 1, set active, FQDN assigned
5invoke / FQDN curlPod ran the active version, returned the response
6execution getPer-invoke status + metrics

Next steps