OrkStageOrkStage

Template reference

The platform/v1 EnvironmentTemplate format. Metadata and tags, placement slots, variables, every resource type with defaults and limits, and examples.

A template describes intent, never provider resource blocks. The schema on this page comes from packages/templates/src/schema.ts, the source of truth for the API, the console builder and the CLI.

minimal template
apiVersion: platform/v1
kind: EnvironmentTemplate
metadata:
  name: hello
  version: 1.0.0
  displayName: Hello
  tags: [starter]
spec:
  placements:
    - name: primary
      providers: [aws]
  resources:
    - id: api
      type: compute.container-service
      image: catalog://hello-api
      port: 8080
      public: true

Identifiers

Resource ids, slot names and variable names match ^[a-z][a-zA-Z0-9-]{0,39}$. They start with a lowercase letter, continue with letters, digits and dashes, and have at most 40 characters.

metadata

FieldTypeDefaultNotes
namestringrequired^[a-z][a-z0-9-]{1,62}$, unique per installation.
versionstringrequiredSemantic version MAJOR.MINOR.PATCH.
displayNamestringrequiredShown in the console.
descriptionstring""
nonProductionbooleanfalseShows a warning. The non-production-template policy fails it for production instances.
tagsstring[][]Free form labels for search and the marketplace, at most 20: lowercase letters, digits and spaces, up to 32 characters each (starter, postgres, object storage).
profilestringnoneDeprecated: accepted and ignored with the warning PROFILE_DEPRECATED; rejected from the next release. Move the value to tags.

spec

FieldTypeDefaultNotes
plansstring[]noneDeprecated: accepted and ignored with the warning PLANS_DEPRECATED; rejected from the next release. A tenant's limits decide what fits, not a list in the template.
placementsslot[]required, at least 1See placements.
variablesvariable[][]See variables.
resourcesresource[]required, at least 1See resources.
connectivityrequirement[][]See connectivity.
observabilityobjectall on except tracesSee observability.

Placements

A placement slot is a named group of resources that an instance binds to one cloud target and region.

FieldTypeDefaultNotes
nameidrequiredResources refer to it in their placement field.
descriptionstring
providersenum[][] (any)Allowed providers: aws, azure, gcp, oci, digitalocean, vultr, coreweave, magalu, vercel, render, supabase, mock. An empty list allows any registered provider. See providers.
placements:
  - name: primary
    description: Application runtime, registry, ingress and DNS.
    providers: [aws, mock]
  - name: data
    description: Relational database.
    providers: [aws, azure, mock]

A network binds implicitly only to resources in its own slot. A database placed on another cloud therefore does not depend on the AWS VPC.

Variables

FieldTypeDefaultNotes
nameidrequired
descriptionstring
typeenumrequirednumber, string, boolean.
defaultnumber, string or booleanrequired
min, maxnumberFor number variables.
allowedstring[]For string variables.
targetstringrequiredThe field the variable sets, as <resourceId>.<field>, for example api.replicas.
variables:
  - name: apiReplicas
    type: number
    default: 1
    min: 1
    max: 2
    target: api.replicas
  - name: databaseSize
    type: string
    default: small
    allowed: [micro, small, medium]
    target: database.size

Resources

Every resource has these common fields, plus the fields of its type.

FieldTypeDefaultNotes
ididrequiredUnique in the template. Physical names use it: ork-<tenant>-<instance>-<id>.
typeenumrequiredOne of the nine types below.
placementidprimaryThe slot this resource belongs to.
implementationstringresolver's defaultPreferred capability, for example ecs-fargate, ecs-ec2 or rds-postgres.
enabledbooleantrueA disabled resource stays in the template, so a variable can turn it on, but is never provisioned.
dependsOnid[][]Explicit dependencies. OrkStage adds the implicit ones (network, ingress routes, DNS target).
overridesmap of mapsEscape hatch for settings of one provider, such as { aws: { … } }. Less portable, and for admins only.

network

FieldTypeDefaultNotes
strategyenumisolatedisolated or shared.
availabilityZonesinteger11 to 3.
natGatewaybooleanfalsePrivate egress through NAT. Adds one NAT gateway per availability zone, which adds cost.

compute.container-service

FieldTypeDefaultNotes
imagestringrequiredCatalog reference such as catalog://orders-api. It resolves to an immutable digest at deploy time.
replicasinteger10 to 100.
cpunumber0.25vCPU, more than 0 and at most 16.
memoryMiBinteger512128 to 122880.
portinteger1 to 65535.
publicbooleanfalseReachable through an ingress.
healthCheckPathstringMust start with /.
autoscalingobject{ minReplicas, maxReplicas, targetCpuPercent }, with targetCpuPercent from 10 to 95.
criticalbooleantrueWhen a critical component is unhealthy, the instance is unhealthy.

AWS implementations: ecs-fargate (the default) and ecs-ec2.

On AWS, autoscaling becomes an Application Auto Scaling target with a target tracking policy on CPU for the ECS service. MiniStack does not emulate autoscaling. There the service runs a fixed number of tasks (replicas) and the deployment logs a warning.

container-registry

FieldTypeDefault
scanOnPushbooleantrue
immutableTagsbooleantrue

database.postgresql

FieldTypeDefaultNotes
versionstring"17"Major version.
sizeenumsmallmicro, small, medium, large, xlarge.
storageGiBinteger201 to 16384.
highAvailabilityenumnonenone, same-zone, zone-redundant. On AWS, RDS supports only zone-redundant, which turns on the RDS multi_az setting.
publicAccessbooleanfalseThe no-public-database policy fails a database with true.
backupobject{ enabled: true, retentionDays: 7 }retentionDays is 0 to 35. recoveryPointObjectiveMinutes is optional.
criticalbooleantrue

cache.redis

FieldTypeDefaultNotes
sizeenummicromicro, small, medium, large.
replicasinteger00 to 5.
criticalbooleanfalse

AWS implementation: ElastiCache with the Valkey engine, which is compatible with Redis OSS.

queue

FieldTypeDefault
fifobooleanfalse
deadLetterbooleantrue
criticalbooleanfalse

object-storage

FieldTypeDefaultNotes
tierenumstandardstandard, infrequent, archive.
versioningbooleanfalse
publicAccessbooleanfalseThe no-public-storage policy fails a bucket with true.
retentionDaysintegerLifecycle expiration, in days.
accessKeysbooleanfalseCreate an access key limited to this bucket and keep it in the provider's secret store, for consumers on other providers (a Vercel or Render app). Services on the same provider use their own identity instead.
criticalbooleanfalse

ingress

FieldTypeDefaultNotes
routesroute[]required, at least 1{ service, pathPrefix }. service is the id of a container service. pathPrefix defaults to /.
tlsbooleantrue

dns

FieldTypeDefaultNotes
targetidrequiredThe ingress this name points to.
subdomainbooleantrueA name under the platform zone, for example production-acme.apps.example.com.
customDomainenumdisableddisabled, optional, required.

web.frontend

A website, landing page or web app built from a Git repository by a frontend platform (Vercel projects, Render static sites).

FieldTypeDefaultNotes
source.repositorystringrequiredowner/name on the platform's connected Git provider.
source.branchstringmain
source.rootDirectorystringFolder of the app inside a monorepo.
source.gitProviderenumgithubgithub, gitlab, bitbucket.
frameworkstringPreset such as nextjs, vite or astro; detected when omitted.
buildCommand, installCommand, outputDirectorystringOverride the preset.
nodeVersionstring22 or 22.x.
environmentmap{}Plain settings, keys in UPPER_SNAKE_CASE. Never put credentials here.
domainsstring[][]Custom domains, up to 20.
previewDeploymentsbooleantrueA preview build for each pull request, where supported.
healthCheckPathstring/Path the health check requests.
criticalbooleantrue

Resources listed in dependsOn reach the frontend as environment variables. Connection settings arrive in plain text (<ID>_HOST, <ID>_PORT, <ID>_URL, <ID>_BUCKET, <ID>_ENDPOINT, <ID>_REGION); credentials a dependency publishes arrive as encrypted values, one per field (<ID>_URL, <ID>_USERNAME, <ID>_PASSWORD, <ID>_ACCESS_KEY_ID, <ID>_SECRET_ACCESS_KEY, and so on), read from the provider that owns the dependency at deploy time. <ID> is the resource id in upper case with dashes turned into underscores.

- id: web
  type: web.frontend
  placement: web
  source: { repository: acme/website, branch: main }
  framework: nextjs
  environment: { NEXT_PUBLIC_APP_NAME: Acme }
  dependsOn: [database, files]

Connectivity

FieldTypeDefaultNotes
from, toidrequiredResource ids.
protocolenumrequiredtcp, http, https, postgres, redis, amqp.
portinteger1 to 65535.
modeenumprivate-preferredprivate-required, private-preferred, secure.

When the two resources are on different clouds, private-preferred falls back to TLS over a public endpoint with an allowlist. The plan rejects private-required across clouds. See connectivity in the plan review.

connectivity:
  - { from: api, to: database, protocol: postgres, port: 5432, mode: private-preferred }
  - { from: api, to: storage, protocol: https, mode: secure }

Triggers

A trigger is a named action on one deployed resource, with default parameters: redeploy a frontend, restart a service, take a database restore point. The provider decides which actions exist; the console and GET /instances/{id}/triggers list them with their parameters.

FieldTypeDefaultNotes
nameidrequiredUnique in the template.
descriptionstring
resourceidrequiredThe resource the action runs on.
actionstringrequiredFor example redeploy, restart, rollback, purge-cache, backup.
paramsmap{}Default parameters, checked against the action when it runs.
overridablestring[][]Parameters a caller may change at run time. Anything else is rejected.
on.manualbooleantrueRun from the console or the CLI.
on.webhookbooleanfalseRun with an API key holding instances:deploy, for example from CI or a CMS.
on.schedulecronFive field cron expression in UTC, for example 0 3 * * *.
triggers:
  - name: redeploy-site
    resource: web
    action: redeploy
    params: { target: production }
    overridable: [ref]
    on: { manual: true, webhook: true }
  - name: nightly-backup
    resource: database
    action: backup
    on: { manual: false, schedule: '0 3 * * *' }

See triggers for running them and following their runs.

Observability

FieldDefault
logstrue
metricstrue
tracesfalse
uptimetrue
alertstrue

Example: the multicloud reference

This example places the API on AWS, the database on Azure and object storage on OCI. Bind each slot to a real target of that provider, to a simulation target that imitates it, or bind every slot to the same AWS target for the AWS only variant. The Azure and OCI adapters are in preview (see providers).

06-multicloud-reference.yaml
apiVersion: platform/v1
kind: EnvironmentTemplate
metadata:
  name: multicloud-reference
  version: 1.0.0
  displayName: Multi-cloud reference
  description: >
    API on AWS ECS Fargate behind an ALB with ECR and Route 53, Postgres on Azure Flexible Server,
    object storage on OCI. Bind every slot to the same AWS target for the AWS-only variant.
  tags: [growth, multicloud]
spec:
  placements:
    - name: primary
      description: Application runtime, registry, ingress and DNS.
      providers: [aws, mock]
    - name: data
      description: Relational database.
      providers: [aws, azure, mock]
    - name: storage
      description: Object storage.
      providers: [aws, oci, mock]
  resources:
    - id: network
      type: network
      availabilityZones: 2
    - id: registry
      type: container-registry
      implementation: ecr
    - id: api
      type: compute.container-service
      implementation: ecs-fargate
      image: catalog://sample-api
      replicas: 2
      cpu: 0.5
      memoryMiB: 1024
      port: 8080
      public: true
      healthCheckPath: /health
    - id: worker
      type: compute.container-service
      implementation: ecs-ec2
      image: catalog://sample-worker
      replicas: 1
      cpu: 0.5
      memoryMiB: 1024
      critical: false
    - id: database
      type: database.postgresql
      placement: data
      size: small
      storageGiB: 50
      highAvailability: zone-redundant
      backup: { enabled: true, retentionDays: 7 }
    - id: storage
      type: object-storage
      placement: storage
      tier: standard
      versioning: true
    - id: ingress
      type: ingress
      routes:
        - service: api
    - id: dns
      type: dns
      target: ingress
  connectivity:
    - { from: api, to: database, protocol: postgres, port: 5432, mode: private-preferred }
    - { from: worker, to: database, protocol: postgres, port: 5432, mode: private-preferred }
    - { from: api, to: storage, protocol: https, mode: secure }
  observability: { logs: true, metrics: true, traces: true, uptime: true, alerts: true }

Validating from your machine

curl -X POST "$ORK_API_URL/api/v1/templates/validate" \
  -H "Authorization: Bearer $ORK_TOKEN" -H "Content-Type: application/json" \
  --data "$(jq -Rs '{source: .}' < template.yaml)"

On this page