Coming from OpenTofu

Map OpenTofu configuration to Encore resources and environments

OpenTofu configuration describes desired infrastructure through provider resources. Encore's TypeScript or Go SDK declarations instead describe the APIs, services, and infrastructure used by the backend. They form an application model that Encore uses for local development and deployment. OpenTofu can continue to manage infrastructure outside that model or provision all physical resources for a self-hosted environment.

OpenTofu aims to maintain compatibility with Terraform configurations, so many of the mappings in Coming from Terraform also apply. See Coming from an IaC tool for the deployment models shared by these tools. This guide focuses on OpenTofu state, ownership, and running both systems together.

How it works

The following examples define an AWS S3 bucket in OpenTofu and an object storage bucket in Encore:

resource "aws_s3_bucket" "uploads" { bucket = "uploads" }
import { Bucket } from "encore.dev/storage/objects"; export const uploads = new Bucket("uploads", { versioned: false });
import "encore.dev/storage/objects" var Uploads = objects.NewBucket("uploads", objects.BucketConfig{Versioned: false})

The OpenTofu resource selects an AWS implementation. The Encore declaration identifies the logical bucket used by the application. For each environment, Encore can provide local development infrastructure, provision the bucket, or connect the declaration to a supported existing bucket.

This is not a source-to-source conversion. OpenTofu can describe resources from a broad provider ecosystem. Encore primitives cover application resources such as databases, Pub/Sub, object storage, caches, cron jobs, and secrets.

How the concepts map

OpenTofuEncore
Root moduleNo direct equivalent; an Encore application contains services and resource declarations
Child moduleNo direct equivalent; services organize application code and its resources
Provider configurationCloud provider and deployment settings selected for an Encore Cloud environment
resource blockAn Encore primitive when the resource type is supported
Resource referenceImport and use the resource object in application code
data sourceNo general equivalent; query external systems using their client or keep the lookup in OpenTofu
Variables and localsNo single equivalent; infrastructure settings, secrets, and other application configuration are handled separately
Outputs and remote stateNo general equivalent; retain outputs for infrastructure that remains in OpenTofu
depends_onUsually derived from application resource usage and service calls; no direct equivalent
count and for_eachNo equivalent for Encore resources; declarations must be statically discoverable
WorkspaceAn Encore environment is the closest operational concept, but the lifecycle and configuration differ
Backend and stateThe application model is rebuilt from source; Encore Cloud separately records managed infrastructure
tofu planNo direct equivalent; builds validate declarations and Encore Cloud provides infrastructure change workflows
tofu applyNo direct equivalent; an Encore Cloud deployment provisions supported changes, while self-hosted infrastructure remains in the OpenTofu workflow

For Encore Cloud, configure capacity, networking, backups, and related deployment properties per environment. For self-hosting, OpenTofu provisions the physical resources and an infra config file maps each Encore declaration to its runtime connection details.

Run Encore with OpenTofu

You can keep OpenTofu for infrastructure outside Encore's application model. This commonly includes:

  • organization and account configuration
  • shared networking and DNS
  • third-party providers
  • infrastructure without an Encore primitive
  • resources shared with non-Encore systems
  • resources created with count, for_each, or other dynamic configuration

Application code can connect to those resources through their normal SDKs. Store credentials and other sensitive values in Encore TypeScript secrets or Go secrets.

Application code can connect to those resources through their normal SDKs. Store credentials and other sensitive values in Encore TypeScript secrets or Go secrets.

Encore Cloud environments can combine resources provisioned by Encore with supported existing resources. At the environment level, Encore can also deploy into an existing GKE cluster or Google Cloud project.

For self-hosted environments, keep all physical resource ownership in OpenTofu. See Configure infrastructure.

State and existing resources

OpenTofu state maps resource addresses in configuration to physical objects. Encore does not consume an OpenTofu state file. Its application model is derived from source, and Encore Cloud maintains separate records for infrastructure managed through the platform.

Choose one provisioning owner for each physical resource. Continuing to apply an OpenTofu resource after Encore has taken ownership can produce conflicting changes.

Encore Cloud has resource-specific workflows for connecting existing infrastructure:

OpenTofu import and Encore import serve different purposes. An OpenTofu import block or tofu import operation brings an existing object into OpenTofu state. An Encore import connects a logical application declaration to an existing physical resource. Review the Encore resource guide before changing OpenTofu state or configuration.

If OpenTofu retains ownership, leave the resource in state and treat it as an external dependency. If ownership moves to Encore, verify the new connection and then replace the resource with a removed block, with destroy = false inside a nested lifecycle block:

removed { from = aws_s3_bucket.uploads lifecycle { destroy = false } }

Review the plan before applying it so OpenTofu forgets the resource without destroying the physical object.

Migrate incrementally

  1. Inventory the resources used by one service, including module and remote-state dependencies.
  2. Map supported application resources to TypeScript primitives or Go primitives.
  3. Leave shared, unsupported, and dynamically generated infrastructure in OpenTofu.
  4. Decide whether each target environment will use Encore Cloud or be self-hosted.
  5. Add resource declarations and test locally with encore run and encore test.
  6. For Encore Cloud, provision new resources or follow the relevant import workflow. For self-hosting, retain OpenTofu provisioning and create the infra config mapping.
  7. Deploy the service and verify resource connectivity and data before changing OpenTofu state.
  8. Repeat for the next service.

Keep existing OpenTofu outputs available until every consumer has moved. If separate root modules read each other's state, record that dependency before changing any resource owner.

Workflow differences

Encore validates statically discoverable resource declarations during the build and configures their deployment per environment. It does not replace OpenTofu plans, modules, or state. Keep unsupported, shared, and dynamically generated infrastructure in OpenTofu, and migrate one ownership boundary at a time.

See Development workflow for the path from local development to preview and production environments. For service-by-service migration patterns, see Migrating an existing system to Encore.