What Changed in Kestra 2.0.0 and How to Migrate

For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append .md to any kestra.io/docs/* URL for plain Markdown.

Kestra 2.0.0 removes several flow constructs and changes how triggers, permissions, and plugin defaults work. This page covers what changed, how to assess your migration effort, and where to find step-by-step guidance.

Migration at a glance

Before scheduling a maintenance window, run kestra-migrate --check ./flows/ against your exported flows to classify the migration effort — automated-only or manual rewrites required. Then follow the step-by-step tutorial for the full walkthrough with real command output from a live 1.3.5 → 2.0.0 run.

Before you start

Back up your database

Take a full database backup before upgrading. Several 2.0 migrations are irreversible: in particular, the BasicAuth password rehash prevents rollback to 1.x.

Run database migrations (EE)

Enterprise Edition users must run database migrations manually before starting Kestra 2.0. By default, Kestra EE refuses to start if pending migrations exist. Stop your 1.3 instance, then run the following using the 2.0 binary:

kestra migrate plan # preview what will run
kestra migrate run # apply migrations

Open-source users do not need to do this manually; migrations run automatically on startup.

See Database Migrations for the full upgrade sequence, Docker Compose and Kubernetes examples, and configuration options.

What changed in 2.0.0

The changes below are grouped by the area they affect. Work through the categories relevant to your setup; not every change applies to every installation.

Flows

Changes that affect how flows are written or behave at runtime. Review all of these before upgrading, regardless of edition.

GuideEditionsWhat changed
ForEach replaced by LoopOSS, EEForEach and ForEachItem are removed. Migrate all uses to the Loop task before upgrading; flows that reference either task fail to parse in 2.0.
Trigger conditions redesignOSS, EEThe conditions list and preconditions block on triggers are removed. All trigger types now use a top-level when Pebble expression.
condition → when (Checks)OSS, EEThe condition property on flow-level checks is renamed to when.
json() → fromJson()OSS, EEThe json() Pebble function and | json filter are removed. Replace json(x) with fromJson(x) and | json with | toJson. kestra-migrate rewrites both automatically.
local.Delete recursive defaultOSS, EEio.kestra.plugin.fs.local.Delete now defaults recursive to false. Flows deleting directories without setting recursive explicitly will stop removing subdirectory contents.

Two additional removals have no dedicated guide. The four tasks io.kestra.plugin.core.execution.Count, Resume, trigger.Toggle, and log.Fetch are removed from core; replace them with the equivalent tasks from plugin-kestra. The CANCELED state name (single-L) was never a valid State.Type value and is not accepted in states: lists on either 1.x or 2.0. kestra-migrate rewrites any occurrences to CANCELLED (double-L) automatically. Update any external API clients or tooling that sends CANCELED.

Governance and plugins

Changes to flow configuration, permissions, and plugin defaults. The SDK auth and pluginDefaults changes apply to all editions; RBAC is EE only.

GuideEditionsWhat changed
SDK authentication required for internal tasksOSS, EETasks that call the Kestra API internally (git sync tasks, and others) now require explicit credentials. Add an auth block to the task, configure a namespace/tenant default service account, or set kestra.tasks.sdk.authentication in your server config.
Git dashboard tasks moved to EEEEio.kestra.plugin.git.SyncDashboards and PushDashboards are removed from the OSS plugin and replaced by io.kestra.plugin.ee.git.SyncDashboards and PushDashboards. OSS flows referencing the old types will fail to load. PushDashboards output field flows is renamed to dashboards.
EE Git Clone removedEEio.kestra.plugin.ee.git.Clone is removed. Flows that reference it return 422 Invalid type on save. Replace with io.kestra.plugin.git.Clone; SSH flows using privateKey also require strictHostKeyChecking: true to preserve the host-key verification behavior the EE task had by default.
pluginDefaults removedOSS, EEThe pluginDefaults keyword is removed at all scopes. EE users migrate to Policies; OSS users inline task values manually.
pluginDefaults.forced removed from flowsOSS, EEThe forced property on flow-level pluginDefaults is removed. Use Add rules with override: true in a Policy (EE) or inline the values (OSS).
RBAC action modelEEThe CRUD-based permission model is replaced by a resource and action model. Existing roles are migrated automatically; CLI role definitions require updates.

Data and storage

Changes to execution data formats, API responses, and storage configuration.

GuideEditionsWhat changed
Execution API responseOSS, EEThe execution endpoint response no longer includes task run outputs. Update any API consumers that read taskRunList[*].outputs.
ION binary formatOSS, EEION task output files are now written in binary format. Expressions that call read() on ION output and then perform string operations will fail; wrap with fromIon().
Execution data in internal storage removedEEThe configuration option that stored task run outputs in internal storage is removed. Remove the affected keys from your configuration.

Infrastructure

Changes to deployment, Helm charts, and server configuration. Relevant primarily for operators and platform teams.

GuideEditionsWhat changed
Database migrationsOSS, EEHow to run the 2.0 schema migrations, including the upgrade sequence, Docker Compose and Kubernetes examples, and key scripts.
Helm gRPC worker-controllerEEPort 50051 is now exposed by default on all pods, and a dedicated controller deployment is added to the Helm chart. The workerGroup.key property is removed; migrate to workerSelector.tags. The fallback default changes from WAIT to FAIL. Review before upgrading.
Management endpoint hardeningOSS, EESeveral management endpoints that were open without authentication in 1.x now require explicit opt-in. Review before upgrading in production.

Terraform provider

Changes to the official Terraform provider. Relevant for teams managing Kestra resources as Infrastructure as Code.

GuideEditionsWhat changed
Terraform providerEE, CloudThe permissions block on kestra_role is renamed to resources with actions instead of CRUD verbs; plugin_defaults and worker_group are removed from kestra_namespace; kestra_template resources must be deleted. Pin to ~> 2.0.
Super Admin renamed to Instance OwnerEE, CloudThe Super Admin privilege is renamed to Instance Owner. Deprecated CLI, config, and request-body aliases are retained. HTTP API responses emit instanceOwner instead of superAdmin; update API consumers that read this field.

CLI

Changes to kestractl behavior. Relevant for teams using the CLI in CI/CD pipelines.

GuideEditionsWhat changed
flows bulk-update —delete defaultOSS, EE--delete now defaults to false. Pipelines relying on the previous default must pass --delete explicitly to delete flows absent from the file.

Completing the migration

Migration is complete when the 1.3 instance has no flows remaining. Migrate them one at a time using this sequence:

  1. Migrate dependencies first. A flow will break at runtime if any of its dependencies are missing on the 2.0 instance. Before migrating a flow, ensure the following are in place:
    • Subflows — migrate and validate any subflows the flow calls before migrating the parent. Removing a subflow from 1.3 while a parent flow still runs there will break in-flight executions.
    • Namespace files — sync any namespace files the flow reads.
    • KV store — migrate KV entries the flow reads at runtime.
    • Secrets — confirm secrets are available in the 2.0 secret backend.
  2. Validate on 2.0. Trigger at least one test execution on the 2.0 instance and confirm it completes successfully.
  3. Drain before removing. Wait for any active executions of the flow on 1.3 to finish before deleting it. Removing a flow with running executions leaves those executions in an unresolvable state.
  4. Activate triggers on 2.0 first. If the flow has a schedule or polling trigger, confirm the trigger is active on 2.0 before removing the flow from 1.3; otherwise scheduled runs are silently dropped during the gap.
  5. Delete from 1.3. Once validated, drained, and triggers are live, delete the flow from the 1.3 instance.

Verifying the migration with kestractl

Once all flows are on the 2.0 instance, use kestractl flows validate-by-query to confirm every stored flow is still valid against the new runtime. The command fetches flows from the live instance, validates them in batches, and exits non-zero if any violations are found, making it suitable as a CI gate.

# Validate all flows on the instance
kestractl flows validate-by-query --all
# Scope to a single namespace
kestractl flows validate-by-query --namespace company.team
# Machine-readable output for CI
kestractl flows validate-by-query --all --output json

This is equivalent to the manual export-unzip-validate round-trip, done in a single command and entirely in memory. A flow with an unsaved draft is validated at its last saved revision.

Was this page helpful?