Workflows

Deployments, tags, and resources

How a deployment binds definitions to a Sanity resource: name versus tag, the storage partition that keeps environments apart, and the aliases that point a definition at real content.

Early access

A deployment is one entry in the deployments array of a sanity.workflow.ts config. It binds a set of workflow definitions to the Sanity resource that stores them, gives their instances an environment partition to live in, and declares the engine data model every runtime reading that resource can interpret. Every CLI command reaches a definition through a deployment.

This page explains the model that config expresses. To install the CLI and write your first config, see Configure and deploy workflow definitions.

A deployment has two identities

A deployment has two identifiers and they answer different questions. name is its unique CLI identity, so it always resolves to exactly one deployment. Use --deployment <name> when a command must target one. tag labels the stored definition and instance partition, and may group deployments across different workflow resources.

Because one tag can cover several deployments and a name never can, the two selectors do not behave the same way on every command. The Workflow CLI command reference has the full matrix, including which commands treat a tag as a group and which require it to resolve to exactly one deployment.

The workflowResource and tag pair is the storage partition

One pair must stay unique: no two deployments may share both a workflowResource and a tag. That pair is the storage partition, so two deployments sharing it would write into the same place and fight over definition versions. The config rejects the collision at load and names both entries.

Environments are kept apart by that pair, not by anything inside the definition. The same definition deployed under two tags produces two independent sets of instances that never see each other. To run one definition in both staging and production, either point the two deployments at different datasets or keep one dataset and give them different tags.

workflowResource decides where engine documents live

The documents a workflow owns, its deployed definitions and the instances it spawns, are written to the workflowResource: one Sanity resource. The CLI derives the project and dataset of its client from it, so every deployment must declare it. A dataset, with id <projectId>.<dataset>, is the common case. Canvas, media-library, and dashboard resources are accepted too. Point it at a dedicated dataset when you would rather keep engine documents out of the dataset your editors work in.

Resource aliases bind a definition to real content

Content a workflow reads and writes is addressed through resourceAliases. A definition points at content by alias name rather than a hardcoded dataset, as in {id: '@content:article-123', type: 'article'}, and resourceAliases binds each alias to a real resource. Using aliases is what lets the same definition ship to production or staging by binding differently.

You only need an alias for content in a different resource from the workflowResource. A definition can reference a document in the same resource by bare id, because bare ids root at the workflowResource. So the smallest single-dataset setup is a workflowResource and definitions, with no resourceAliases at all.

At deploy, each @<handle>: reference expands to the bound resource, and nothing alias-shaped survives into the deployed definition. A deployment that references an alias it does not bind fails rather than deploying against the wrong resource.

Two alias patterns look similar and do different jobs. Two aliases in one deployment mean one workflow touching more than one resource at once, such as a cross-brand publish reading two datasets together; see One workflow across resources. The same alias name bound differently across deployments means one workflow shipped to several equivalent environments. Coordinate content across projects and datasets is the guide that puts both into practice.

Choose where workflows and effects run

A runtime calls the engine to advance workflow instances and run effects, the external work a workflow queues. The runtime block declares which host runs that code. The experimental generator uses it to decide which Sanity Functions to create.

A workflow inherits its deployment's runtime.kind. Each effect inherits its workflow's kind. A block on the workflow or effect overrides that inherited value. When no level declares a block, the kind is function. For example, a deployment with runtime: {kind: 'selfHosted'} can keep one workflow on Sanity Functions by giving that workflow runtime: {kind: 'function'}.

The generator handles the three kinds as follows:

Kind

Generated runtime

function

Functions run effects and reevaluate time-based conditions. Effects without a custom budget share a drain function.

durableFunction

The plan reports the workflow or effect, but emits no durable execution function. A qualifying autonomous workflow can still receive a document watcher that starts its instances.

selfHosted

Your process runs the workflow or effect. The plan reports deadlines to tick, effects to drain, parents to reevaluate after children settle, and autonomous workflows to start.

Generated runtime resources derive their names from the tag. Give deployments that generate functions distinct tags, even when they target different workflow resources. Generation rejects colliding resource names.

Only effect-level runtime blocks with kind: 'function' accept timeout and memory. Timeout is an integer from 1 through 900 seconds; memory is an integer from 1 through 10 GB. Set either to give that effect its own drain function. Effects with the same name in one deployment must resolve to the same kind and budget.

The block is authoring metadata. Deployment removes it before storing the definition, so changing hosting does not create a definition version. Regenerate and redeploy the runtime after changing it. Regeneration preserves your handler implementations; directories no longer referenced by the generated Blueprint are inert and can be removed separately.

Hosting is not an execution restriction. Any engine with a registered handler can drain that effect. The generator emits a heartbeat, a scheduled function, when a function-hosted workflow reads $now or spawns children, or when any workflow has a function-hosted effect. Once emitted, it ticks in-flight instances of all function-hosted workflows in the deployment. Recovery of function-hosted effects has a separate scope and can include completed instances and workflows hosted elsewhere. See heartbeat recovery.

Reference

WorkflowDeploymentInput

Each entry in the deployments array passed to defineWorkflowConfig takes this shape.

  • name

    string, required

    The identity of the deployment, unique across the config. This is what --deployment matches. Lowercase letters, digits, and dashes, with no leading dash and no dots.

  • tag

    string, required

    The environment partition every engine document is scoped to. Tags may repeat across deployments. Same grammar as name.

  • workflowResource

    object, required

    Where the engine keeps its own documents: instances, deployed definitions, and guards. For a dataset, {type: 'dataset', id: '<projectId>.<dataset>'}.

  • definitions

    array, required

    The definitions this deployment ships. At least one. The engine orders the batch itself, deploying children before the parents that spawn them, so the order you list them in does not matter. A spawn reference must resolve either inside the batch or to an already-deployed definition.

  • expectedMinReaderModel

    number, required to deploy

    The reader model you have verified across every runtime sharing the workflow resource. Deploy refuses when a definition needs a higher model. Required subject, doc.ref, and doc.refs fields need model 10; other features can require a lower floor. Follow Upgrade Workflows packages before raising this reviewed literal.

  • resourceAliases

    array, optional

    Binds each @<handle>: reference a definition makes to a physical resource. Only for content that lives in a different resource from workflowResource.

  • runtime

    RuntimeBlock, optional

    Default hosting for workflows in this deployment. Accepts {kind: 'function'}, {kind: 'durableFunction'}, or {kind: 'selfHosted'}. Defaults to function. Deployment-level blocks accept no function budget.

Runtime blocks

A deployment or workflow accepts RuntimeBlock. An effect accepts EffectRuntimeBlock, which adds function budgets:

  • Requiredkind

    'function' | 'durableFunction' | 'selfHosted', required

    Required when a runtime block is present. Omit the whole block to inherit the enclosing host. The deployment default is function.

  • timeout

    integer, 1–900, optional

    Seconds available to the effect’s function, from 1 through 900. Accepted only on an effect with kind: 'function'. Creates a dedicated drain when set. Omitted values use the platform default.

  • memory

    integer, 1–10, optional

    GB allocated to the effect’s function, from 1 through 10. Accepted only on an effect with kind: 'function'. Creates a dedicated drain when set. Omitted values use the platform default.

Was this page helpful?