How It Works
This page is the big-picture view of how Zenvara behaves. You don’t need it to author flows, but it explains why the platform works the way it does — compiled-not-interpreted, single-binary, self-rolling-back.
Compiled, not interpreted
Section titled “Compiled, not interpreted”A flow’s YAML is not executed line by line. It is parsed into a typed model and validated before a single byte moves:
- Parse — the YAML is read into a typed structure by the compiler.
- Validate — references between steps (
${orders.rows}), expressions, operator input types, and theoutput:contract are all type-checked. Mistakes surface here, not at 3 a.m. - Plan — the step graph is planned; transformer chains (e.g.
load:thenjoin:) are fused at zero runtime cost. - Invoke — the planned flow runs.
This is the central design choice: the YAML is a real language with a compiler, so the class of errors that plague interpreted glue scripts is caught at validation time.
Saga compensation — flows that roll themselves back
Section titled “Saga compensation — flows that roll themselves back”Every write operator carries a compensating action — the inverse of what it did. If a flow writes to three systems and the fourth step fails, the engine runs the compensations for the three successful writes in reverse order. This is the saga pattern, built into the platform rather than hand-coded per flow. A failed run leaves no half-finished state.
Operations never throw — each returns a typed result (success with a payload, or a typed error). That uniform contract is what lets the engine apply consistent retry, rollback, and logging across every operator, from a SQL query to an LLM call. See the Error Catalog for how errors are categorised and which are retried.
Layered storage
Section titled “Layered storage”Everything the platform runs — flows, connections, environments, secrets, invocation logs — lives in storage, organised as a layered chain. Each layer wraps the one beneath:
graph TD
subgraph L4["optional local overlay · /api/v1/local/… · no-git scratchpad"]
subgraph L3["branch overlay · the /{branch}/ URL segment"]
subgraph L2["optional Git versioning · commit-on-write, branch staging"]
L1["underlying provider<br/>File · S3 · Minio"]
end
end
end
This is why versioning, branch staging, and the developer overlay compose cleanly rather than fighting each other — they are layers over one storage model, not bolted-on features. Entity names may contain / as a path separator, so akeneo/product/sync is a valid flow name. See Storage Backends for the operational view.
Single binary, single replica
Section titled “Single binary, single replica”Zenvara runs as one self-contained binary — no JVM, no separate scheduler, no message broker, no external database. It is single-replica by design today; the operating model is “scale up, not out.” The full deployment picture is in Deployment Model.
The three external-facing surfaces
Section titled “The three external-facing surfaces”A flow and the entities around it are reachable through three equivalent surfaces, each with the same guarantees:
- REST — two URL families: branch-scoped (
/api/v1/{branch}/...) and platform-scoped (/api/v1/platform/...). - MCP — the Model Context Protocol server, for AI assistants.
- GraphQL — a resolver surface for typed queries.
Plus the zen CLI, which forwards to REST. The equivalence of these surfaces is deliberate: the same typed contract drives all of them, so a flow behaves identically whether a human, a script, or an AI agent invokes it. See API Surfaces.