Territorial product

Ordo

A contract-driven orchestration control plane for long-running processing jobs, built to sit above n8n.

Architecture

  1. Client
    POST /jobs with recipe + artifacts
  2. Ordo
    validate · store · track state
  3. n8n workers
    claim step · run tool · register artifact
  4. Object storage
    MinIO / S3 artifacts
  5. Finalizer
    deliver outputs · on_exit hook

Workflow engines like n8n execute steps well but do not give you a durable, validated model of a multi-step job. Ordo is that missing layer: it validates recipes, enforces input/output contracts between steps, and tracks every job, step and artifact as queryable state. Open source, and the backend of every heavy platform I build.

At a glance

  • Recipes are deterministic, artifact-based DAGs validated against executor contracts before anything runs
  • Jobs, steps and artifacts are first-class PostgreSQL state with progress, per-step logs and lifecycle hooks
  • Deliberately does not execute steps, manage workers or ship a UI: execution belongs to the engine underneath
  • Runs in production for Skyport and MapPrism; released with semantic versioning, migrations and a Vitest suite

Why it exists

I built Ordo while building Skyport. n8n was excellent at executing steps and integrating systems, but the pipeline kept needing guarantees n8n could not give: that a job's inputs were valid before the first step ran, that step outputs actually matched what the next step expected, that a failed job left a clear trail of what had and had not been produced. I wanted something that could sit above execution, stay simple, and still be strict.

The model

A recipe is a list of steps. Each step names an executor type, maps the executor's input slots to namespaced artifact references (job:<name> for job inputs, step:<id>.<slot> for step outputs) and maps its output slots to artifact names. Executors are rows in a step_executor table declaring what they accept and produce; recipe validation checks that every step type exists, every slot is bound exactly once, every referenced artifact is producible, and no artifact name is reused. Parameters are declared on recipes by key only and supplied per job, so parameter values never affect recipe identity.

Jobs are created from a recipe plus concrete input artifacts, parameters and optional output declarations. Ordo inserts the step queue, exposes progress as a fraction across steps, surfaces the latest per-step log line, and runs an on_exit step after the main graph completes regardless of outcome. Per-step max_concurrency limits how many instances of an executor run at once across all jobs.

Boundaries and next steps

Ordo does not execute steps, manage infrastructure, provide an editor or move files. n8n workers claim steps straight from the database, run the tool, register artifacts and report status; a separate finalizer workflow delivers declared outputs to their final storage path. That direct database contract is pragmatic rather than fundamental, and the roadmap is to decouple it behind queues or APIs so that multiple execution backends can run side by side.

The API is a small TypeScript/Express service on PostgreSQL with migrations applied at startup, released through semantic-release and shipped as a Docker image.

More projects

All projects