Skip to Content
We are live but in Staging 🎉
ComputeCore Concepts

Core Concepts — Compute

Every type below is from proto/proto-ignite/ignite_compute.proto and ignite_common.proto. Package: dodil.ignite.v1. Wire encodings: gRPC follows proto types directly; HTTP uses pbjson (camelCase, int64 as JSON strings, enums as wire-name strings).

An app is long-lived code that runs as an HTTP server in an auto-scaled pod (KEDA scales it 0→N on demand). You don’t deploy code directly — you move it through a lifecycle:

CreateApp ──▶ SaveDraft ──▶ [CompileDraft] ──▶ PublishDraft ──▶ Invoke (metadata) (code → (managed-runtime (draft → new (server-stream draft slot, compile, or image immutable response; yields version 0) build) version 1..N) an Execution) RollbackApp ──▶ re-point active_version

The draft slot is version 0 (mutable); publishing snapshots it into an immutable numbered version. The app’s active_version is what serves traffic.

App (AppMeta)

The central record. Curated to the fields you’ll actually set or read — the full message has more (catalog/discovery metadata, build provenance).

message AppMeta { string id = 1; // "org/name" string name = 2; string organization_name = 27; Runtime runtime = 3; // compile-path runtime (see below) ResourceTier resource_tier = 9; // SMALL | MEDIUM | LARGE | XLARGE ResourceLimits limits = 4; // explicit memory/cpu/timeout — overrides tier ScalingConfig scaling = 10; map<string, string> env = 5; StorageMode storage_mode = 11; // PERSISTENT | EPHEMERAL | TTL DeploymentState deployment_state = 15; uint32 version = 26; // 0 = unversioned draft, 1+ = versioned uint32 active_version = 28; // version currently serving (0 = none yet) string description = 29; // also the MCP tool description string input_schema = 30; // JSON Schema string string output_schema = 31; // JSON Schema string bool mcp_enabled = 32; // export as an MCP tool after publish uint32 max_concurrency = 38; // per-pod concurrent executions (0 = default) DeploymentMode deployment_mode = 39; // COMPILATION | IMAGE (derived from code_kind) CodeKind code_kind = 45; // SDK | UPLOAD_IMAGE | GIT_IMAGE | PREBUILT string image_ref = 40; // image-mode only repeated string public_urls = 43; // FQDNs, populated after first publish int64 created_at_ms = 7; int64 updated_at_ms = 8; }
  • id is always "org/name". Most RPCs take organization_name + app_name separately.
  • mcp_enabled turns a published app into an MCP tool named ignite_{org}_{name} (needs description + input_schema).
  • public_urls is empty until active_version > 0 — one URL per listening port.

Code source — how the pod is built

Code is attached via SaveDraft (or inline on CreateApp) as a CodeSource, which is a oneof over two branches:

message CodeSource { oneof source { CompileSource compile = 1; // managed runtime — platform compiles your source ImageSource image = 2; // container image — BYOI or platform-built } } message CompileSource { Runtime runtime = 1; // picks the compile pipeline oneof body { bytes source_code = 2; // single file (handler.py, main.rs, …) bytes archive = 3; // ZIP / tar.gz project (magic-sniffed) } map<string, string> build_args = 4; } message ImageSource { oneof variant { PrebuiltImage prebuilt = 1; // BYOI — image_ref (+ registry_secret_ref for private) ImageFromCode from_code = 2; // build from an uploaded archive (Kaniko / Buildpacks) ImageFromGit from_git = 3; // build from a git repo at build time } }

The branch you pick determines the CodeKind stamped on the version:

enum CodeKind { CODE_KIND_UNSPECIFIED = 0; CODE_KIND_SDK = 1; // managed-runtime compile (CompileSource) → DeploymentMode.COMPILATION CODE_KIND_UPLOAD_IMAGE = 2; // build from uploaded context (ImageFromCode) CODE_KIND_GIT_IMAGE = 3; // build from git (ImageFromGit) CODE_KIND_PREBUILT = 4; // BYOI pull (PrebuiltImage) → DeploymentMode.IMAGE }

The from_code / from_git branches hand off to Builds (Kaniko/Buildpacks) to produce an image. Private registry/image pulls reference a Secret by name.

For the full supported-runtime matrix (Python/Rust/Go/Deno versions + targets) and the image-build options in depth, see Code & Runtimes.

Runtimes (compile path)

message Runtime { oneof runtime { PythonRuntime python = 1; // version e.g. "3.11" RustRuntime rust = 2; // target: NATIVE | WASM, toolchain e.g. "1.82" GoRuntime go = 3; // target, toolchain e.g. "1.24" DenoRuntime deno = 4; // version e.g. "2.0" } }

Only the compile path uses Runtime; image-mode apps run their container directly.

Resources & scaling

enum ResourceTier { // shorthand for cpu/memory RESOURCE_TIER_SMALL = 1; // 256MB, 250m CPU RESOURCE_TIER_MEDIUM = 2; // 512MB, 500m CPU RESOURCE_TIER_LARGE = 3; // 1GB, 1000m CPU RESOURCE_TIER_XLARGE = 4; // 2GB, 2000m CPU } message ResourceLimits { // explicit override (any subset) optional uint32 memory_mb = 1; optional uint32 cpu_millicores = 2; // 1000 = 1 core optional uint32 timeout_secs = 3; } message ScalingConfig { uint32 max_replicas = 1; // default 10 uint32 reserved_capacity = 2; // warm pods to keep (default 0) uint32 scale_threshold = 3; // target per pod; meaning set by scale_metric ScaleMetric scale_metric = 4; // REQUEST_RATE (req/s) | CONCURRENCY (in-flight) uint32 scaledown_period_secs = 5; // stay warm after signal drops (default 300) }

ScaleMetric.CONCURRENCY suits variable-duration work (LLM inference, image processing); REQUEST_RATE suits short uniform requests. Activation from zero is automatic on any inbound request.

Lifecycle states

enum DeploymentState { // K8s resource lifecycle (on AppMeta) DEPLOYMENT_STATE_CREATED = 8; // app exists, no version promoted yet DEPLOYMENT_STATE_PROVISIONING = 1; DEPLOYMENT_STATE_DEPLOYED = 2; // pods may be running DEPLOYMENT_STATE_COLD = 3; // scaled to zero, K8s resources exist DEPLOYMENT_STATE_ARCHIVED = 4; // long idle, resources torn down DEPLOYMENT_STATE_ACTIVATING = 5; DEPLOYMENT_STATE_COMPILING = 7; DEPLOYMENT_STATE_FAILED = 6; } enum VersionStatus { // per-version (AppVersionInfo) VERSION_STATUS_COMPILING = 1; VERSION_STATUS_DRAFT = 2; // ready to test, not active VERSION_STATUS_ACTIVE = 3; // serving VERSION_STATUS_SUPERSEDED = 4; VERSION_STATUS_FAILED = 5; } enum StorageMode { // app retention STORAGE_MODE_PERSISTENT = 1; // default — keep until deleted STORAGE_MODE_EPHEMERAL = 2; // auto-delete after execution STORAGE_MODE_TTL = 3; // auto-delete after ttl_seconds }

Execution

Each invocation produces an Execution record:

message Execution { string id = 1; string app_id = 2; ExecutionStatus status = 3; // PENDING | RUNNING | COMPLETED | FAILED | TIMEOUT bytes result = 4; // JSON-encoded string error = 5; ExecutionMetrics metrics = 6; // cold_start_ms, execution_ms, billed_duration_ms, // cpu_used_ms, memory_used_mb, result_size_bytes, … uint32 function_version = 9; // version that ran string error_class = 13; // "client" | "user_code" | "model_config" | "model_upstream" | "platform" int64 started_at_ms = 7; int64 completed_at_ms = 8; }

metrics.billed_duration_ms is what you’re billed on (execution + init if cold). error_class tells you whose fault a failure is.

Invocation envelope

Invoke streams its response, and carries an HTTP envelope so the same shape works whether the call arrives over gRPC or the plain-HTTP edge:

message HttpContext { HttpMethod method = 1; // UNSPECIFIED → POST string path = 2; // empty → "/" string query = 3; // raw query string, no leading "?" map<string,string> headers = 4; }

Invoke frames the response as: one head (status code, headers, execution_id) → 0..N chunk (body) → one trailer (total bytes, duration). See API Reference → Invocation.

See also