How to Migrate to fivetran_connection_v2 Terraform Resource
The fivetran_connection_v2 resource replaces fivetran_connection and fivetran_connector_schedule with a unified resource that uses native HCL for connector config instead of JSON strings. Connections managed by fivetran_connection_v2 support new connector types as soon as they're released, and changes made outside Terraform are detected and reconciled on every plan/apply.
The fivetran_connection and fivetran_connector_schedule resources remain fully supported and migration is not required. Use this guide when you're ready to adopt the new resource.
What changed
| Area | v1 | v2 |
|---|---|---|
| Config format | config = jsonencode({...}) | config = {...} (native HCL) |
| Scheduling | Separate fivetran_connector_schedule resource | Scheduling fields on fivetran_connection_v2 directly |
| Pause state | paused field on fivetran_connector_schedule | Separate fivetran_connection_v2_pause_state resource |
| Destination schema | destination_schema { prefix = "..." } block | destination_schema_names enum + schema fields inside config |
sync_frequency type | String ("1440") | Number (1440) |
paused type | String ("false") | Boolean (false) |
pause_after_trial type | String ("true") | Boolean (true) |
| Initial pause state | Configurable at creation | Always created paused; use fivetran_connection_v2_pause_state to unpause |
Before you begin
- Terraform 1.7 or later is required for the
importandremovedblock syntax used in this guide. - The migration keeps the same underlying connection ID in Fivetran. No data is lost and no re-sync is triggered.
- Run
terraform state show fivetran_connection.NAMEand note theidvalue for each connection you plan to migrate.
Migrate individual connections
This example migrates a PostgreSQL connection. Replace the resource names and config fields with your own.
Find connection ID
terraform state show fivetran_connection.pg | grep ' id '
pg is the Terraform resource name from your configuration.
Define v2 resources
Add the new fivetran_connection_v2 and fivetran_connection_v2_pause_state resources to your configuration along with import and removed blocks for the v1 resources. Remove or comment out the original v1 resource blocks at the same time.
Before:
resource "fivetran_connection" "pg" {
group_id = fivetran_group.my_group.id
service = "postgres"
destination_schema {
prefix = "my_prefix"
}
config = jsonencode({
update_method = "WAL_PGOUTPUT"
replication_slot = local.config.sources.postgres.replication_slot
publication_name = local.config.sources.postgres.publication
host = local.config.sources.postgres.host
port = local.config.sources.postgres.port
database = local.config.sources.postgres.database
user = local.config.sources.postgres.user
password = local.config.sources.postgres.password
})
run_setup_tests = true
trust_certificates = false
trust_fingerprints = false
}
resource "fivetran_connector_schedule" "pg" {
connector_id = fivetran_connection.pg.id
sync_frequency = "1440"
daily_sync_time = "03:00"
paused = "false"
pause_after_trial = "true"
schedule_type = "auto"
}
After:
resource "fivetran_connection_v2" "pg" {
service = "postgres"
group_id = fivetran_group.my_group.id
destination_schema_names = "FIVETRAN_NAMING"
sync_frequency = 1440 # number, not string
daily_sync_time = "03:00"
pause_after_trial = true # boolean, not string
schedule_type = "auto"
run_setup_tests = true
trust_certificates = false
trust_fingerprints = false
config = {
schema_prefix = "my_prefix" # was: destination_schema { prefix = "my_prefix" }
update_method = "WAL_PGOUTPUT"
replication_slot = local.config.sources.postgres.replication_slot
publication_name = local.config.sources.postgres.publication
host = local.config.sources.postgres.host
port = local.config.sources.postgres.port
database = local.config.sources.postgres.database
user = local.config.sources.postgres.user
password = local.config.sources.postgres.password
}
}
resource "fivetran_connection_v2_pause_state" "pg" {
connection_id = fivetran_connection_v2.pg.id
paused = false # boolean, not string
}
import {
to = fivetran_connection_v2.pg
id = "<your-connection-id>"
}
import {
to = fivetran_connection_v2_pause_state.pg
id = "<your-connection-id>"
}
removed {
from = fivetran_connection.pg
lifecycle { destroy = false }
}
removed {
from = fivetran_connector_schedule.pg
lifecycle { destroy = false }
}
If you used a separate fivetran_connection_config resource for this connection, add a removed block for it as well:
removed {
from = fivetran_connection_config.pg
lifecycle { destroy = false }
}
If a removed block is missing or does not include lifecycle { destroy = false }, Terraform will delete the connection from Fivetran.
The destination_schema block does not exist in fivetran_connection_v2. Map its fields into config:
v1 destination_schema field | v2 config field |
|---|---|
name | schema |
prefix | schema_prefix |
table | table |
Plan and apply
terraform plan terraform apply
The plan must show 2 to import and 0 to destroy. It will also show 1 to change on fivetran_connection_v2. This is expected: credential fields show a diff because the API does not return secrets, and fivetran_connection_v2 surfaces config fields that fivetran_connection did not expose, some of which Fivetran sets automatically. Neither changes your connection. If the plan shows resources to destroy or replace, stop and review your attribute mapping before continuing.
Remove migration blocks
Delete the import and removed blocks from your configuration. Run terraform plan again. The plan should show no changes.
Migrate multiple connections
Using for_each
If your connections use for_each, the import and removed blocks support it directly:
import {
for_each = local.connections
to = fivetran_connection_v2.this[each.key]
id = each.value.connection_id
}
import {
for_each = local.connections
to = fivetran_connection_v2_pause_state.this[each.key]
id = each.value.connection_id
}
removed {
for_each = local.connections
from = fivetran_connection.this[each.key]
lifecycle { destroy = false }
}
removed {
for_each = local.connections
from = fivetran_connector_schedule.this[each.key]
lifecycle { destroy = false }
}
Generating migration blocks from state
For individually declared connections, generate migration blocks from your state automatically:
terraform show -json | jq -r '
.values.root_module.resources[]
| select(.type == "fivetran_connection")
| "import { to = fivetran_connection_v2.\(.name)\n id = \"\(.values.id)\" }\n" +
"import { to = fivetran_connection_v2_pause_state.\(.name)\n id = \"\(.values.id)\" }\n" +
"removed { from = fivetran_connection.\(.name)\n lifecycle { destroy = false } }\n" +
"removed { from = fivetran_connector_schedule.\(.name)\n lifecycle { destroy = false } }\n" +
"removed { from = fivetran_connection_config.\(.name)\n lifecycle { destroy = false } }\n"
' > migration.tf
This generates import and removed blocks for every fivetran_connection resource in your root module. Review migration.tf before applying.
Update dependent resources
The underlying connection ID does not change during migration. However, any Terraform resource that references fivetran_connection.NAME.id as an expression must be updated to fivetran_connection_v2.NAME.id. The ID value is identical; only the resource address changes.
No additional import or removed blocks are needed for these resources.
| Resource | Field to update |
|---|---|
fivetran_connector_schema_config | connector_id |
fivetran_connector_certificates | connector_id |
fivetran_connector_fingerprints | connector_id |
fivetran_user_connector_membership | connector_id |
fivetran_team_connector_membership | connector_id |
fivetran_transformation (INTEGRATED schedule) | schedule.connection_ids |
fivetran_transformation (QUICKSTART) | transformation_config.connection_ids |
Example:
# Before
resource "fivetran_transformation" "nightly" {
schedule {
schedule_type = "INTEGRATED"
connection_ids = [fivetran_connection.pg.id]
}
}
# After
resource "fivetran_transformation" "nightly" {
schedule {
schedule_type = "INTEGRATED"
connection_ids = [fivetran_connection_v2.pg.id]
}
}
Notes
fivetran_connection_v2always creates connections paused. To enable syncing immediately after creation, include a companionfivetran_connection_v2_pause_stateresource withpaused = falsein the same configuration. Without it, the connection stays paused until that resource is added and applied.- Deleting
fivetran_connection_v2_pause_statedoes not change the pause state in Fivetran. Removing this resource from your configuration removes it from Terraform state only - the connection keeps whatever pause state it had. To pause a connection intentionally, setpaused = trueand apply before removing the resource. destination_schema_namescannot be changed after creation. Changing this field forces replacement of the connection. When migrating an existing connection, check its current naming mode and setdestination_schema_namesto that value before planning.fivetran_connectionandfivetran_connector_scheduleremain fully supported.