Back
OCI block volume replication with Terraform

How to Achieve High Availability with OCI Block Volume Replication and Terraform

High availability and disaster recovery are essential for modern cloud applications. If your workloads depend on OCI block volumes attached to compute instances, you need protection against region outages. This is exactly where OCI block volume replication with Terraform helps — giving you an automated way to achieve cross-region redundancy.

With replication enabled, your block volumes are copied across OCI regions in near real time. This improves application resilience, reduces downtime during outages, keeps business services running, and meets compliance requirements for disaster recovery.

In industries like finance or healthcare, having data available in multiple regions is not optional — it’s a must. OCI provides a built-in replication mechanism that makes this simple to deploy, while ensuring consistency and performance.

It’s worth noting the difference between OCI Block Volume Backups and Cross-Region Block Volume Replication. Backups are good for long-term retention or point-in-time recovery, but if you need fast failover and minimal data loss, replication is the right choice. For less critical systems, backups alone may still be enough.

👉 In this hands-on guide, you’ll learn how to:

  • Use Terraform to create and manage a block volume replica across OCI regions.

  • Build a fault-tolerant setup with two web servers in different regions, connected by VCNs, DRGs, and cross-region peering.

  • Automate attaching the replicated volume to a standby server and serve static content over HTTP(S).

The demo topology uses two servers in different OCI regions but with one shared Terraform configuration. Region 1 hosts the primary web server and block volume, while Region 2 keeps the replica server ready to take over when needed.

 

🏗️ Architecture Overview

Below is the high-level architecture we’ll deploy:

  • Region 1 – Primary workload:

    • Compute instance (FoggyKitchenWebServer1)

    • 100 GB block volume attached via iSCSI

    • Block volume replica continuously replicated to Region 2

  • Region 2 – Disaster Recovery region:

    • Replica block volume

    • On failover: activation of the replica → new block volume

    • Secondary compute instance (FoggyKitchenWebServer2) attached to the DR volume

👉 With Terraform, we can codify this entire setup so that failover is just a variable flip + terraform apply.

Figure 1. Cross-region replication of OCI Block Volume.

⚙️ Terraform Setup

Providers

We start by defining two OCI providers with aliases: primary (main region) and secondary (disaster recovery region). This allows us to create and manage resources across both regions in a single Terraform configuration. Having aliases makes it clear which resources belong to which region.


# Primary region
provider "oci" {
  alias  = "primary"
  region = var.primary_region
}

# DR region (replica target)
provider "oci" {
  alias  = "secondary"
  region = var.dr_region
}

Primary Block Volume

In the primary region, we create a 100 GB block volume and immediately enable replication for it. The block_volume_replicas block specifies that the data should be continuously copied to an availability domain in the DR region. This is the key configuration step that enables cross-region redundancy.

💡 Before creating the primary block volume, we fetch the list of availability domains in both regions. This ensures Terraform knows exactly where to place the resources — the P-ADs datasource is for the primary region, and the S-ADs datasource is for the secondary DR region.



# Gets a list of Availability Domains in Acceptor region
data "oci_identity_availability_domains" "P-ADs" {
  provider       = oci.primary
  compartment_id = var.tenancy_ocid
}

# Gets a list of Availability Domains in Requestor region
data "oci_identity_availability_domains" "S-ADs" {
  provider       = oci.secondary
  compartment_id = var.tenancy_ocid
}    
(...)

# 100 GB Block Volume
resource "oci_core_volume" "FoggyKitchenWebServer1BlockVolume100G" {
  provider            = oci.primary
  availability_domain = var.availability_domain_name == "" ? lookup(data.oci_identity_availability_domains.P-ADs.availability_domains[0], "name") : var.availability_domain_name
  compartment_id      = oci_identity_compartment.FoggyKitchenCompartment.id
  display_name        = "FoggyKitchenWebServer1 BlockVolume 100G"
  size_in_gbs         = "100"
  
  block_volume_replicas { 
    availability_domain = var.availability_domain_name2 == "" ? lookup(data.oci_identity_availability_domains.S-ADs.availability_domains[0], "name") : var.availability_domain_name2
    display_name = "FoggyKitchenWebServer1 BlockVolume 100G replica"
  }  
  block_volume_replicas_deletion = true
}

Cross-Region Replica

On the DR side, we use the data "oci_core_block_volume_replicas" data source to check the replication status. The filter ensures the replica is in the AVAILABLE state. Only then—if the variable activate_block_volume_replica = true is set—Terraform provisions a new block volume from that replica in the DR region. This volume can later be attached to a standby compute instance.


data "oci_core_block_volume_replicas" "FoggyKitchenWebServer1BlockVolume100G_xregion_replica" {
  depends_on          = [oci_core_volume.FoggyKitchenWebServer1BlockVolume100G, 
                         null_resource.FoggyKitchenWebServer1_oci_httpd_data_fstab,
                         null_resource.FoggyKitchenWebServer1HTTPD]
  provider            = oci.secondary
  availability_domain = var.availability_domain_name2 == "" ? lookup(data.oci_identity_availability_domains.S-ADs.availability_domains[0], "name") : var.availability_domain_name2
  compartment_id      = oci_identity_compartment.FoggyKitchenCompartment.id
  
  filter {
    name   = "state"
    values = ["AVAILABLE"]
  }
}

(...)

resource "oci_core_volume" "FoggyKitchenWebServer2BlockVolume100G" {
  count               = var.activate_block_volume_replica ? 1 : 0
  depends_on          = [oci_core_volume.FoggyKitchenWebServer1BlockVolume100G, 
                         null_resource.FoggyKitchenWebServer1HTTPD,
                         null_resource.FoggyKitchenWebServer1_oci_httpd_data_fstab]
  provider            = oci.secondary
  availability_domain = var.availability_domain_name2 == "" ? lookup(data.oci_identity_availability_domains.S-ADs.availability_domains[0], "name") : var.availability_domain_name2
  compartment_id      = oci_identity_compartment.FoggyKitchenCompartment.id
  display_name        = "FoggyKitchenWebServer2 BlockVolume 100G"
  size_in_gbs         = "100"
  source_details {
    id   = lookup(data.oci_core_block_volume_replicas.FoggyKitchenWebServer1BlockVolume100G_xregion_replica.block_volume_replicas[0], "id")
    type = "blockVolumeReplica"
  }
}

Read more on OCI + Terraform

Extend this topic with more cross-region, multi-region, and production-grade patterns across storage, networking, and databases in OCI:

🔹 OCI Providers in Terraform (Multi-Region Setup)
How to define multiple providers and aliases — essential for cross-region operations.
https://foggykitchen.com/2025/11/05/oci-provider-terraform/

🔹 OCI Block Volume with Terraform
Baseline guide for provisioning and automating block volumes.
https://foggykitchen.com/2025/06/06/oci-block-volume-terraform/

🔹 OCI Data Guard with Terraform (Database Cross-Region DR)
Database-level HA/DR pattern based on synchronous or asynchronous replication.
https://foggykitchen.com/2025/09/20/oci-data-guard-terraform/

🔹 OCI MySQL HeatWave Cross-Region Replica with Terraform
Multi-region MySQL replication and failover workflows — perfect complement to block volume DR.
https://foggykitchen.com/2025/01/28/oci-mysql-terraform-x-region-replicat/

🔹 OCI VCN with Terraform
Fundamental networking layer for all region-to-region architectures.
https://foggykitchen.com/2020/01/05/oci-vcn-terraform/

Why This Approach?

Breaking it down into three clear steps (primary volume → replica creation → activation) makes it easy to test disaster recovery scenarios. Replication runs automatically in the background, but the actual failover only happens when you explicitly activate the replica and attach it to a secondary server. This setup gives you both continuous protection and full control over when to trigger the failover.

You can find the full Terraform configuration, including variables, modules, and sample scripts, in 👉 this GitHub repository

Want to go further with Terraform automation on OCI? 👉 Explore my flagship course for 10+ real-world labs 

Want to go hands-on with OCI automation?

🚀 Try my flagship course How to Automate Oracle Cloud Infrastructure with Terraform/OpenTofu (2025 Edition).

🔒 Lifetime • ⏱️ Self-paced • 🧪 Real labs

Check also other courses:

Leave A Reply