Migrate from AWS Step Functions to Temporal

Moving from Step Functions to self-hosted Temporal is a rewrite of state machines into workflow code, plus a planned cutover. This page explains what moves cleanly, what needs rework, and how to plan the sequence, cost drivers and risks.

On this page

Migrate from AWS Step Functions to Temporal: what the move involves

Moving from AWS Step Functions to Temporal is a code rewrite plus a staged cutover, not a file import. Amazon States Language definitions describe states in JSON, while Temporal expresses the same logic as workflow and activity code in a supported SDK language, so each state machine has to be re-implemented, tested and then switched over one workflow family at a time. Teams usually arrive here because of a renewal, a data residency rule or a wish to run orchestration inside their own network, and the first decision is whether the work justifies the rewrite at all. Platform engineers normally lead the effort, with application owners confirming the business behavior of each workflow, retry expectations and downstream side effects. The short answer on effort and risk depends on how many state machines exist, how many call AWS services directly through service integrations, and how many run long enough to need careful versioning. Build an inventory first and rank workflows by risk before estimating anything.

Temporal's server is licensed under the MIT license, so the orchestration engine itself carries no license fee, and you can run it in your own cloud accounts or data center. Temporal Cloud is a separate, managed option sold by Temporal Technologies with its own pricing, so the choice between running the server and buying the managed service is an operations and cost decision, not a license decision. Ask for a written scope that names the workflows in each wave, the persistence and visibility stores you will run, who owns the on-call rotation, and what must be retained from Step Functions execution history before it expires. Keep the old state machines running until each new workflow has passed parallel testing with real inputs, and plan the cutover so that in-flight executions finish on the system where they started. Confirm the current server and SDK versions and the upgrade path with Temporal before you commit to a timeline.

Which Step Functions capabilities map to Temporal, and what needs rework

This table maps each Step Functions capability to its closest Temporal equivalent and labels it as a clean translation, work that needs rework, or a gap. Read the rework rows as the places where engineers will rewrite logic, not just move a JSON file. Amazon States Language has no direct import path into Temporal, so every definition becomes code.

Step Functions capabilityTemporal equivalentStatus and what to plan
Task state (Lambda or service call)Activity called from a workflow functionNeeds rework: each AWS service integration must be rebuilt as an activity with its own SDK client, credentials and retry settings.
Choice stateNative if, switch or conditional logic in workflow codeClean: branching logic translates directly, but comparison operators and JSONPath expressions must be rewritten in the host language.
Wait stateDurable timer (sleep or timer call in the workflow)Clean: timers persist across worker restarts, but long waits still count toward history and retention limits.
Parallel and Map statesConcurrent activity futures, child workflows or fan-out with bounded concurrencyNeeds rework: concurrency limits, result ordering and error aggregation must be coded explicitly.
Retry and CatchActivity and workflow retry policies with try and catch blocksNeeds rework: map each ErrorEquals list to a retry policy or an exception type, then test non-retryable errors.
Timeouts (TimeoutSeconds, HeartbeatSeconds)Start-to-close, schedule-to-close and heartbeat timeouts on activitiesNeeds rework: choose which timeout type each activity needs, because Temporal separates them more finely.
Callback task tokens (.waitForTaskToken)Signals and workflow waits on a conditionNeeds rework: external systems must send a signal to the workflow ID instead of returning a token, so the sender needs the workflow ID.
Execution history and visibilityWorkflow event history and visibility storeGap in portability: Step Functions history cannot be imported. Plan to archive exports and confirm the retention you need in your Temporal persistence and visibility setup.
Versioning of state machine definitionsWorkflow versioning with patching or worker build IDsNeeds rework: in-flight executions must keep running on the code that started them, so plan version markers before changing workflow code.

Which definitions, histories and integrations to export and rebuild

A migration from Step Functions to Temporal succeeds or fails on what you capture before the first line of workflow code is written. The items below form one inventory: the definitions, the execution history, the IAM roles and the service integrations that each state machine depends on. Every card feeds the rebuild plan, so treat the inventory as the source of truth rather than the console.

Export state machine definitions

Retrieve each Amazon States Language definition with the DescribeStateMachine API call, for every state machine in every account and Region in scope. Store the JSON in version control with the account ID, Region and ARN recorded alongside it. Each definition is the blueprint for the Temporal workflow, so each Task, Choice, Wait, Parallel and Map state must be mapped to code. Confirm in the AWS Step Functions documentation which fields the export returns for your state machine type.

Save execution history early

Execution history is not a migration artifact you can rebuild later. Export the history of executions you still need for audit or support before it ages out of the console. Record which executions were running at cutover, since those are the ones that need a drain plan or a manual decision. Confirm the retention window that applies to your account and whether your compliance team requires a longer archive.

Decrypt KMS-encrypted definitions

When a state machine definition or its logging configuration uses a customer managed KMS key, the reader's role needs permission to call decrypt on that key before the definition can be read in plain form. Missing key permissions often surface only during a migration, not during normal operation. Document which keys protect which artifacts, who can use them, and where the decrypted copies are stored. Keep decrypted definitions in the same controlled repository as the rest of the inventory.

Capture IAM roles and permissions

Each state machine runs under an execution role that grants access to downstream services such as Lambda, DynamoDB, SQS or ECS. In Temporal, those permissions move to the worker processes and their service accounts, so the mapping must be explicit. List every role, its attached policies and the resources it reaches. Then decide which credentials each activity worker will hold, and whether they should be short-lived or scoped per workflow type.

Map service integrations to activities

Optimized and SDK service integrations in Step Functions call AWS APIs directly from the state. In Temporal, each of those calls becomes an activity that a worker executes, with its own retry policy and timeout. Record each integration pattern used, including any wait-for-callback calls, and the AWS SDK operation behind it. Activities that call AWS directly will still need network paths and credentials that the self-hosted cluster can reach.

Keep the inventory as the rebuild source

Use the inventory as the single input for sequencing, testing and sign-off. Each row should link a definition, its history sample, its roles, its integrations and an owner. Mark any state machine that depends on a callback token or an external system that cannot move, because those need a signal design. Keep the inventory under change control until cutover, and confirm each AWS-specific detail against current AWS documentation for your own account.

Migration sequence from inventory to decommission

This sequence moves Step Functions workloads to Temporal in controlled stages, so each workflow is proven on Temporal before its traffic moves and Step Functions is retired only after nothing depends on it. Each step ends with a named artifact that the next step relies on.

  1. Build the inventory of definitions and integrations

    Export every state machine's Amazon States Language definition, the IAM role attached to it, and the list of service integrations it calls, such as Lambda, DynamoDB, SQS or other AWS APIs. Record which workflows are started by EventBridge, API Gateway, schedules or other state machines, and note the execution history retention you need to keep. The output is a migration inventory with one row per state machine, its owners, its callers, its external dependencies and a risk rating. The step is done when the platform team and the workflow owners have signed off on that inventory.

  2. Choose and stand up the Temporal environment

    Decide the deployment method (Docker Compose, Go binaries, or Helm charts on Kubernetes) and the persistence database that your standards support, from the versions Temporal has tested. Confirm the visibility store you will use, and place the services on hosts that are not reachable from the public internet. Configure an Authorizer and a ClaimMapper before any workflow runs, because a self-hosted install without an Authorizer accepts every API request. The output is a hardened non-production cluster and a short architecture note. The step is done when a test worker can start and complete a sample workflow through the frontend.

  3. Pilot one low-risk state machine

    Select one workflow from the inventory that has few integrations, no long-running waits and a clear business owner. Rewrite its Task, Choice, Wait and error-handling states as a Temporal workflow with activities, then run it in a staging namespace against the same downstream systems. Compare inputs, outputs and failure behavior with the Step Functions execution history for the same test cases. The output is a pilot test report listing matched behaviors, known differences and the decisions made about retries and timeouts. The step is done when the owner accepts the report.

  4. Translate and test the remaining workflows

    Translate the rest of the inventory in batches, grouped by shared integrations and risk. Map Parallel and Map states to fan-out logic with bounded concurrency, replace task token callbacks with Temporal signals, and move any Wait states longer than a few seconds to durable timers. Put each workflow under version control and add a test suite that replays representative histories and covers failure paths. The output is a tested code repository and a translation log that links each Amazon States Language state to its Temporal construct. The step is done when every workflow in the batch passes its tests and has an owner.

  5. Run both systems in parallel

    Route new executions to Temporal for each workflow while the Step Functions version remains deployed and able to receive work. Compare outcomes, latency, error rates and downstream side effects for the same business events, and watch for duplicate actions caused by two systems handling one event. Use idempotency keys on every side-effecting activity during this period. The output is a parallel-run dashboard and a log of discrepancies with a disposition for each. The step is done when discrepancies are resolved and the owners agree that Temporal behaves as expected.

  6. Cut over each workflow with a runbook

    For each workflow, write a cutover runbook that names the trigger source to repoint, the point after which new events go only to Temporal, the procedure for draining or stopping in-flight Step Functions executions, and the rollback path. Let Step Functions finish executions already in progress before retiring its trigger, and confirm Temporal's visibility shows the expected counts. The output is a signed cutover runbook and a cutover record for each workflow. The step is done when the workflow has run on Temporal for its agreed observation period with no open incidents.

  7. Decommission Step Functions and archive evidence

    After all workflows have cut over, disable the remaining triggers, delete the state machines and their IAM roles, and retain the exported definitions, execution history and runbooks as records in storage you control. Remove any KMS grants and CloudWatch log subscriptions that no longer serve a purpose, and confirm no other service still calls the state machines. The output is a decommission record that lists each deleted resource and where its archive is kept. The step is done when a second review of the inventory finds no active dependency on Step Functions.

How callback patterns become Temporal signals

In Step Functions, a task that waits for an outside system usually uses the callback pattern: the state passes a task token to a downstream service, which later calls SendTaskSuccess or SendTaskFailure with that token. In Temporal, the equivalent is a workflow that blocks on a signal while an activity or an external caller does the outside work. The migration decision is where the token's job goes. Map each token-based state in your inventory to one of two shapes: a signal the workflow waits for, identified by a workflow ID that your system of record already stores, or an activity that calls the external system and returns only when it finishes. Record which external system sends the completion, how it identifies the waiting run, and what happens if it never answers. Illustrative example (hypothetical): an approval state that waits for a human decision in an internal ticketing tool would become a workflow that waits on an approval signal, with the ticketing webhook sending that signal using the workflow ID stored with the ticket.

Wait states translate to durable timers in workflow code, so a 24-hour wait survives worker restarts and deployments without a separate scheduler. Confirm with your own tests that timer behavior matches the Step Functions timeout settings you rely on, especially where a Step Functions state has a TimeoutSeconds or HeartbeatSeconds value. Parallel and Map states become concurrent activity calls issued from workflow code. The risk here is unbounded fan-out: a Map over a large array can flood downstream services and the Temporal history. Set an explicit concurrency limit in the workflow, cap the size of each batch, and check that the Temporal server and persistence database can absorb the event volume at your peak. Test these limits against your own load profile before cutover, since the right bound depends on your activities and downstream capacity, not on a general rule.

Signals also need a versioning plan. A signal sent to a workflow run that has since changed shape can fail or be ignored, so define signal names and payload schemas as a contract, and keep older workers able to handle signals for runs already in flight. Plan to drain or migrate those in-flight executions during the side-by-side period rather than assuming they finish under the new code. Review the Temporal documentation on workflow and signal behavior for your server version before you finalize the design.

Choosing a Temporal deployment and persistence path for the migration

Self-hosted Temporal can be deployed in four ways, and the right one depends on how much platform tooling your team already runs. Docker Compose suits proofs of concept and small test environments. Go binaries give you direct control over each service on hosts you manage. Helm charts run the Temporal Server services in individual Kubernetes pods and fit teams that already operate clusters. A custom Go build imports the server package into your own binary, which suits teams that need to change server internals, at the cost of owning that build pipeline.

  • Docker Compose: Useful for evaluating the migration on a single host, not for a production cutover.
  • Go binaries: Each Temporal service runs as a process you supervise, so your team owns service management and restarts.
  • Helm charts on Kubernetes: Chart versions below 0.73.1 do not work with server images 1.30 and later, so pin the chart version to match the server image.
  • Custom Go build: Importing the server package adds a build and patching responsibility that continues after go-live.
  • Network placement: Temporal services should run on hosts that are not reachable from the public internet.

Confirm the chosen deployment method against the current Temporal deployment documentation before you pin versions in your infrastructure code.

What drives migration cost and duration

This table lists the factors that most change the effort of moving Step Functions state machines to Temporal, with why each matters and how to keep it under control. Read it as a scoping checklist: the more a driver applies to your estate, the more discovery, code translation and parallel running your written scope should cover.

DriverWhy it changes cost or effortHow to keep it down
Number of state machinesEach state machine becomes a Temporal workflow definition with its own tests, versioning and cutover step, so effort scales with the inventory count.Export every definition first, group near-identical machines into shared workflow libraries, and retire unused machines before translating.
Depth of AWS service integrationsTask states that call Lambda, SQS, DynamoDB or other services become activities that need their own SDK clients, IAM-equivalent credentials and error handling.Map each integration to a single activity pattern, reuse clients across workflows, and confirm which AWS calls can move to your own services.
Callback and task token patternsWaiting for an external callback must be rebuilt as Temporal signals, which changes how external systems send events and how timeouts are handled.Inventory every callback and token consumer early, agree the signal contract with the owning teams, and test timeouts explicitly.
Length of long-running executionsExecutions that wait days or months need careful handling of history size, timers and the retention period set for your Temporal namespaces.Measure the longest current executions, plan for continue-as-new where appropriate, and confirm retention settings with your Temporal design.
Need for in-flight execution continuityRunning executions cannot simply switch engines, so you must decide whether to drain, restart or finish them on Step Functions during cutover.Set a cutover rule per workflow type, drain short executions, and keep Step Functions running until long executions complete.
Number of environmentsEach environment needs its own Temporal deployment, persistence database, visibility store and configuration, which multiplies infrastructure and testing work.Standardize Helm or Compose configuration across environments and automate namespace creation so each environment follows the same pattern.
Team Temporal experienceTemporal workflows are code with determinism rules, so teams new to it need training and review time before production work starts.Pilot one representative workflow, pair engineers with experienced reviewers, and budget training time in the written scope.
Visibility and security setupAdvanced visibility requires a supported Elasticsearch, OpenSearch or SQL store, and an open server needs an Authorizer, mTLS and SSO configured before use.Pick the visibility store from the supported list, restrict network access to internal networks, and configure the ClaimMapper and Authorizer before any production namespace is opened.
Temporal Cloud as a comparison pointTemporal Cloud pay-as-you-go pricing starts at 50 US dollars per million actions, with a 99.9% SLA or 99.99% with high availability, per Temporal's pricing page. Self-hosting removes that per-action fee but adds the operations work listed above.Ask for a total cost comparison that includes servers, persistence, visibility, engineering time and on-call, and confirm current figures on Temporal's pricing page.

What usually goes wrong and how to prevent it

Most failed Temporal migrations trace back to a handful of decisions made early: how the cluster is exposed, how it is secured, how it is upgraded and how workflow code evolves. The cards below pair each risk with a prevention step you can check before cutover, and they cover the data and integration work that Step Functions hid from your team.

Services exposed to the internet

Temporal's self-hosted deployment guidance says the services should run on hosts that are not reachable from the public internet, with network access limited to trusted internal networks. Teams moving from a managed AWS service often assume the endpoint is protected by default and expose the frontend for convenience. Prevention: place the frontend, history and matching services on private subnets, restrict ingress to known worker and client networks, and verify from outside the network that no Temporal port answers.

Running without an Authorizer

If no Authorizer is configured, self-hosted Temporal falls back to the default noopAuthorizer, which allows every API request with no authentication or access control. Anyone who can reach the frontend can start, signal or terminate workflows. Prevention: configure a ClaimMapper and an Authorizer before any production namespace receives traffic, enable mTLS between services and clients, and test that an unauthenticated call is rejected.

Mismatched Helm chart and server versions

Helm chart versions below 0.73.1 do not work with server images 1.30 and later. Pinning a chart from an old example and pulling the latest server image can produce a deployment that fails at startup or behaves unpredictably. Prevention: pin the chart and server image versions together in source control, record both in the change record, and run a staging deployment with the exact pair before production.

Skipping the minor-by-minor upgrade path

Backward compatibility is guaranteed only between two successive minor versions, so jumping several minor releases at once is unsupported. Schema upgrades must also run before server upgrades when the release notes call for them. Prevention: move to the latest patch of your current minor first, then step one minor version at a time, reading the release notes at each step and applying schema changes in the order the upgrade guide specifies.

Non-deterministic changes to workflow code

Temporal replays workflow history to recover state, so changing the order of activity calls, timers or random decisions in workflow code can break in-flight executions that were started on the old logic. Step Functions definitions were versioned as whole state machines, which hides this risk. Prevention: use Temporal's workflow versioning or patching for logic changes, keep workflow code free of direct clock, random and I/O calls, and replay representative histories in tests before each deployment.

Losing execution history before export

Step Functions retains execution history for a limited window, and a migration inventory that only copies definitions loses the record of runs that are still in progress or need audit evidence. Prevention: export state machine definitions, IAM roles and service integrations, and capture execution history for any run that matters before the window closes. Store the export in a location with the same access controls as the original data.

Underestimating AWS integration rebuilds

Step Functions calls Lambda, SQS, DynamoDB and other services directly through service integrations and optimized callbacks. In Temporal, each of these becomes an activity with its own retry policy, credentials, timeouts and error handling, and task-token callbacks become signals. Prevention: list every service integration in the inventory, assign each an owner, write activities with explicit timeouts, and run both systems side by side with duplicate-action checks until cutover is verified.

How the migration differs by starting point

A small set of state machines owned by one team is the simplest starting point. The main work is translating definitions into code and making sure one team can operate the cluster and its on-call rotation. Because the blast radius is limited, the team can often run a single Temporal environment for development and staging before promoting the first production workflow.

  • Inventory first: List every state machine, its triggers, and its service integrations, then decide which ones are worth moving at all.
  • Pick one pilot: Choose a workflow with clear inputs and outputs and a modest number of Task states to prove the translation pattern.
  • Keep the cluster small at first: A single-team estate usually needs one namespace and one persistence backend, so the operational surface stays manageable.
  • Run the pilot beside the original: Route a fraction of new executions to Temporal while Step Functions keeps the rest, then retire the old state machine once results match.
  • Document the runbook early: With one team, knowledge sits in few heads, so write down deployment, upgrade and incident steps before the second workflow moves.

Before starting, confirm with the team who will carry the pager for the Temporal cluster and whether that matches the time they can spare.

Questions buyers ask before migrating from Step Functions to Temporal

How much does moving from Step Functions to Temporal cost?

The cost is driven by inventory size and by who runs the platform, not by a single license fee. Temporal's server is MIT licensed, so self-hosting carries no license charge, but you pay for the persistence database, the advanced visibility store (Elasticsearch or OpenSearch is recommended beyond a few workflow executions), compute, engineering time to rewrite definitions as code, and on-call coverage. One-time costs include translating state machines, building activities and testing. Recurring costs include infrastructure, upgrades and monitoring. Ask any services partner for a written quote that lists each component, the number of state machines in scope, and which environments are included. DeployOpen issues quotes only from a written scope.

How long does a Step Functions to Temporal migration take?

The timeline depends on how many state machines you have, how many use service integrations, callbacks and long waits, and how many workflows must run side by side during cutover. Teams with a small set of linear workflows move faster than teams with nested Parallel and Map states and external callback tokens, which need signal-based redesign. Temporal's upgrade guidance also shapes planning: self-hosted servers should move one minor version at a time, and some releases require schema upgrades before server upgrades. Ask for a timeline tied to a fixed scope and a dated list of deliverables, and confirm which environments and cutover windows are assumed.

What does the migration need from our engineering team?

Expect to involve application engineers who own the business logic, platform engineers who run the cluster, and security staff who approve the access model. Application engineers translate Task, Choice, Wait, Parallel and Map states into workflow and activity code and decide how callbacks become signals. Platform engineers manage the persistence database, visibility store, networking and upgrades. Security reviews the authorizer, mTLS and OIDC settings. Your team also needs to confirm which AWS services each state calls, since those integrations must be rebuilt as activities with their own IAM or credential handling.

Can our own team run the migration and operate Temporal without a partner?

Yes, if you have engineers who can write Go, Java, Python or TypeScript workflow code and who can operate a stateful distributed service. Self-hosted Temporal can be deployed with Docker Compose, Go binaries, Helm charts for Kubernetes, or a custom Go build. The deployment guidance says the services should run on hosts that are not reachable from the public internet, so network design matters. Many teams use a partner for the first migration wave and then take over operations. Decide early which parts you will keep in house, such as day-to-day operations, and which you will contract, such as upgrades or continuous support, and write that split into the scope.

Can Temporal take over workflows that are already running in Step Functions?

Not automatically. Step Functions execution state lives in AWS and cannot be transferred into a Temporal workflow history. The common approach is to let in-flight Step Functions executions finish, start new executions in Temporal, and cut over new work when the old queue drains. Long-running executions, such as those with multi-day Wait states, extend the overlap period, so the inventory should record the longest running execution for each state machine. Confirm this approach against your own execution history and retention needs before committing to a cutover date.

Can Amazon States Language definitions be converted to Temporal code automatically?

Definitions cannot be converted fully automatically in a way you should rely on for production. Amazon States Language describes states and transitions in JSON, while Temporal expresses control flow in ordinary code and models retries, timers and fan-out in the workflow itself. An export tool can produce an inventory of states, service integrations and IAM roles, which is useful for scoping. The translation of each state, especially Parallel, Map and callback patterns, is design work that needs review and testing. Ask for the export inventory as a deliverable, then have every converted workflow reviewed against its original behavior.

Should we choose self-hosted Temporal or Temporal Cloud?

Choose self-hosted Temporal when data residency, network isolation or ownership of the runtime is a requirement, and choose Temporal Cloud when you want Temporal Technologies to operate the service. Temporal Cloud pay-as-you-go pricing starts at 50 US dollars per million actions, with storage charges per GB-hour, a 99.9% SLA or 99.99% with high availability, and SAML SSO, according to Temporal's pricing page. Self-hosting removes per-action charges but adds database, search, staffing and on-call costs. Compare both options on your expected action volume, data location rules and staffing, and confirm current terms directly with Temporal before deciding.

How DeployOpen plans and runs the migration

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside the client's own infrastructure, and that includes self-hosted Temporal. For a move from AWS Step Functions, we start from a written scope that inventories the state machines and cuts them over in stages while both systems run.

How we scope

  • Inventory every state machine, its Task, Choice, Wait, Parallel and Map states, and its service integrations
  • Agree in writing which workflows move, which stay on Step Functions, and the cutover order
  • Engagements are fixed-scope, with scope, deliverables and timelines agreed before work starts

How we build

  • Translate state definitions into Temporal workflow code and activities, with signals replacing callback patterns
  • Deploy Temporal in your environment with persistence and visibility sized to your execution volume
  • Configure mTLS, namespace authorization, OIDC single sign-on for the Web UI and payload encryption before go-live

How we hand over

  • Document workflow code, deployment topology, upgrade runbooks and the side-by-side cutover plan
  • Run parallel execution tests and compare outcomes from both systems before retiring any state machine
  • Transfer operational runbooks to your platform and on-call teams with recorded walkthroughs of the Web UI

How we support

  • Ongoing support, server upgrades one minor version at a time, and continuous testing are available as a retainer
  • Security testing of workflow APIs and the Temporal frontend can be scoped as a separate engagement
  • Confirm with your team which upgrade path, persistence backend and retainer level fit your operating model

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.