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 });
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
| OpenTofu | Encore |
|---|---|
| Root module | No direct equivalent; an Encore application contains services and resource declarations |
| Child module | No direct equivalent; services organize application code and its resources |
| Provider configuration | Cloud provider and deployment settings selected for an Encore Cloud environment |
resource block | An Encore primitive when the resource type is supported |
| Resource reference | Import and use the resource object in application code |
data source | No general equivalent; query external systems using their client or keep the lookup in OpenTofu |
| Variables and locals | No single equivalent; infrastructure settings, secrets, and other application configuration are handled separately |
| Outputs and remote state | No general equivalent; retain outputs for infrastructure that remains in OpenTofu |
depends_on | Usually derived from application resource usage and service calls; no direct equivalent |
count and for_each | No equivalent for Encore resources; declarations must be statically discoverable |
| Workspace | An Encore environment is the closest operational concept, but the lifecycle and configuration differ |
| Backend and state | The application model is rebuilt from source; Encore Cloud separately records managed infrastructure |
tofu plan | No direct equivalent; builds validate declarations and Encore Cloud provides infrastructure change workflows |
tofu apply | No 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.
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
- Inventory the resources used by one service, including module and remote-state dependencies.
- Map supported application resources to TypeScript primitives or Go primitives.
- Leave shared, unsupported, and dynamically generated infrastructure in OpenTofu.
- Decide whether each target environment will use Encore Cloud or be self-hosted.
- Add resource declarations and test locally with
encore runandencore test. - For Encore Cloud, provision new resources or follow the relevant import workflow. For self-hosting, retain OpenTofu provisioning and create the infra config mapping.
- Deploy the service and verify resource connectivity and data before changing OpenTofu state.
- 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.