Until recently, most organizations I work with have been comfortable running their databases and applications across two regions. Sometimes that is an Active/Standby configuration, but more often I see some form of Active/Active. The big change I have seen recently is the addition of a third site, often described as a "cyber vault" or an IRE (Isolated Recovery Environment).
To provide that third site, many customers are looking at hosting a standby database in the cloud, either in OCI or through Oracle Database@ services in a multicloud environment. A practical way to limit traffic from the on-premises environment is to only send redo to the cloud database with Data Guard, then back up that cloud database to Autonomous Recovery Service. The backup workload stays on the cloud side.
Creating a cloud standby from your on-premises database is easier than you might think. In this post, I go through the standby build and the next step: configuring backups to Autonomous Recovery Service.
One thing to keep in mind is that a standby database and backups are only part of the picture. To use this as a cyber vault or IRE, you also need to control who can access it and which systems can connect to it. You need to protect the encryption keys and test that you can restore the database to a point before an attack or data corruption occurred. Plan for all of this as you build the standby and configure the backups..
The third-site pattern: send redo to a cloud standby, then back up the standby to Autonomous Recovery Service. The worked example below uses Oracle Exadata Database Service in OCI.
I recently went through the Oracle documentation for creating a hybrid Data Guard configuration. There is a lot of information to work through, especially when you are trying to figure out what needs to be ready before you start.
I am breaking this into four parts:
- Get the prerequisites in place.
- Run
dbcactlto prepare the primary database. - Run
dbaasclito create the standby database in OCI. - Configure backups from the cloud standby to Autonomous Recovery Service.
Once the preparation is done, the standby build comes down to two commands. I will go through their parameters and what dbcactl and dbaascli are doing, then show where Recovery Service fits into the third-site design.
For this walkthrough, I am showing an on-premises Oracle RAC primary with a standby on Oracle Exadata Database Service in OCI. I have changed the database names and hostnames to use a generic sales example. My example build used a 19c Oracle Home and DBAAS CLI 26.3.1.0.0.
NOTE: The cloud VM cluster and Oracle Home need to exist before you start. configureStandby creates the database within that cluster. Refer to the full Oracle guide for platform requirements and configurations with additional standbys.
1) What needs to be ready before I start
First, let's go through the pieces that need to be in place before running either command.
- Download
dbcactl. My Oracle Support document 3099785.1, linked from the hybrid guide, has the download and installation instructions. I am using/home/oracle/dbcacl/dbcactlin the example. The folder is nameddbcacl, and the executable isdbcactl. - Have the cloud Oracle Home ready. Match the primary release, RU, and one-off patches where possible. If you need a different RU, check the combinations allowed in the guide.
- Check connectivity in both directions. The primary needs to reach the cloud, and the cloud needs to reach the primary. Check DNS, SSH, and Oracle Net for all RAC nodes and SCAN endpoints. The network also needs enough bandwidth for the initial copy and ongoing redo.
- Have a shared ACFS directory on the primary. This is where the network files and wallet configuration can be shared between instances. For this example I am using
/acfs01/saleson an existing mounted ACFS filesystem. - Prepare the primary for Data Guard. This includes standby redo logs, logging, Flashback Database, Oracle Net encryption, and enough recovery-area space. Follow the MAA recommendations in the guide.
Make sure the encryption keys are there
One thing I want to call out is the TDE wallet. Even if the on-premises primary is not encrypted, it still needs a wallet with master encryption keys for this hybrid configuration. The cloud database needs those keys.
For this example I am using a file-based TDE keystore. Before starting, I would check that the wallet is usable and that the keys exist in the CDB root and each PDB other than the seed. The TDE with Data Guard documentation goes through the key handling.
For 19c at RU 19.16 or later, these are the settings I would look at:
| Parameter | Example or policy | Purpose |
|---|---|---|
WALLET_ROOT | /acfs01/sales/wallet | Root directory for wallet storage; the file-based TDE wallet is under tde. Use your existing keystore location. |
TDE_CONFIGURATION | KEYSTORE_CONFIGURATION=FILE | Selects the file-based keystore used in this example. |
TABLESPACE_ENCRYPTION | Choose for each site | AUTO_ENABLE is the cloud policy. DECRYPT_ONLY is an on-premises option when encrypted tablespaces must be avoided. Do not apply it to the cloud standby. |
NOTE: Setting the parameters does not create the wallet or set the master keys. Also, WALLET_ROOT is static, so changing it requires a restart.
If you still need to set up the wallet, follow the TDE configuration procedure. The TABLESPACE_ENCRYPTION reference explains the encryption policies. For earlier RUs, use the release-specific settings in the hybrid guide.
Here is a quick check I can run on the primary, connected through SQL*Plus as oracle:
SELECT name, db_unique_name, database_role, log_mode,
force_logging, flashback_on
FROM v$database;
SHOW PARAMETER wallet_root
SHOW PARAMETER tde_configuration
SHOW PARAMETER tablespace_encryption
SELECT con_id, status, wallet_type, wrl_parameter
FROM v$encryption_wallet;
I want the primary in ARCHIVELOG mode, with force logging enabled and Flashback Database prepared before moving on. If archive logging still needs to be enabled, plan for the maintenance window that change may require.
I would also check V$DATABASE_KEY_INFO and V$ENCRYPTION_KEYS in the root and relevant PDBs. An open wallet is only part of the check; I need the master keys as well. If the wallet shows OPEN_NO_MASTER_KEY, that needs to be addressed before the build.
Use your existing key-management procedure and wallet location. There is no reason to replace an existing wallet just to match the path in my example.
Finally, have the primary SYS password, the TDE wallet password, and the password you will supply for AWR administration ready. These have different purposes and do not need to be the same.
Get Recovery Service ready as well
For the backup step, I also need the Recovery Service IAM policies, network connectivity, and a registered Recovery Service subnet. For 19c, the documented minimum is RU 19.18. Broker is mandatory for this backup destination in a Data Guard configuration with dbaascli 25.3.1.0.0 and later. I would also check regional availability, service limits, and the retention policy I need. The Exadata backup guide covers these prerequisites.
The names I am using in the example
| Item | Generic value |
|---|---|
| Database name on both sites | sales |
| Primary database unique name | sales_primary |
| Standby database unique name | sales_stby |
| Primary SCAN | onprem-scan.example.com |
| Standby SCAN | cloud-scan.oraclevcn.com |
| Primary database service | sales_primary.example.com |
| SCAN listener port on both sites | 1521 |
| Existing cloud Oracle Home | /u02/app/oracle/product/19.0.0.0/dbhome_1 |
You can see that I am using sales as the database name on both sides. The unique names are different: sales_primary and sales_stby.
The other distinction to keep in mind is the SCAN name versus the database service. The SCAN gets me to the cluster, and the service identifies the database connection. Use the actual service registered with your primary listener when replacing sales_primary.example.com.
2) Run dbcactl on the primary

Figure 1. Run the preparation command on the first primary node. The standby SCAN already belongs to the provisioned cloud cluster.
Now I can prepare the primary. The diagram above shows the database and its SCAN listener, along with the cloud SCAN I will pass to the command.
I run this as oracle on the first primary node, with ORACLE_HOME and the local ORACLE_SID set for the source database. The shared directory /acfs01/sales also needs to be writable by oracle.
Here is the command with the example names:
/home/oracle/dbcacl/dbcactl \
-silent \
-oui_internal \
-configureDatabase \
-prepareForStandby \
-dgTNSNamesoraFilePath /acfs01/sales \
-sourceDB sales_primary \
-gdbName sales.example.com \
-standbyDBUniqueName sales_stby \
-standbyScanName cloud-scan.oraclevcn.com \
-standbyScanPort 1521 \
-primaryScanPort 1521 \
-standbyDBDomain oraclevcn.com \
-blobFileLocation /tmp
The command prompts for the primary SYS password. In my run, I could see it creating the Data Guard services, updating tnsnames.ora and the include-file entry, and then preparing the standby bundle.
What the dbcactl parameters mean
| Parameter | Value in this example | Meaning |
|---|---|---|
-silent | Flag | Runs without the graphical assistant; password prompts still appear. |
-oui_internal | Flag | Workflow flag that allows for the use of prepareForStandby (which is a hidden parameter) |
-configureDatabase | Flag | Selects database configuration. |
-prepareForStandby | Flag | Selects primary preparation for a standby. |
-dgTNSNamesoraFilePath | /acfs01/sales | Directory for the Data Guard network configuration. An "ifile" entry is created in the tnsnames.ora file that points to a tnsnames.ora that is created in this directory which contains entries for both the primary database and the new standby database. |
-sourceDB | sales_primary | Identifies the primary by its unique name. |
-gdbName | sales.example.com | Global database name passed to the workflow. |
-standbyDBUniqueName | sales_stby | Unique name planned for the standby. |
-standbyScanName | cloud-scan.oraclevcn.com | SCAN hostname for the existing standby cluster. |
-standbyScanPort | 1521 | Standby SCAN listener port. |
-primaryScanPort | 1521 | Primary SCAN listener port. |
-standbyDBDomain | oraclevcn.com | Standby database in OCI domain passed to the workflow. |
-blobFileLocation | /tmp | Output directory for the generated bundle. |
These are the options from my successful command, with the environment names changed. If you are using a different utility version, check its supported options, especially -gdbName and -pdbServiceDomain.
NOTE: My original run included -skipFlashbackValidation and -skipForceLoggingValidation. I have left those out here so the checks run. Skipping a check does not remove the need to prepare the database.
At the end, the command tells me where it wrote the .tar file. The filename will look like this, with a generated timestamp and ID:
Successfully created blob file:
/tmp/sales_<generated_timestamp>_<generated_id>.tar
This file contains the preparation material, including network files and the TDE wallet. I need to copy it securely to the first cloud node before running the second command.
For example, I can use scp:
scp /tmp/sales_<generated_timestamp>_<generated_id>.tar opc@cloud-node1.example.com:/tmp/
Replace the timestamp and ID with the actual filename from your output. For the next command, I am using /tmp/sales_standby.tar as a simpler name for the transferred file. You can keep the generated name instead; just use the same path in --standbyBlobFromPrimary.
NOTE: The bundle contains wallet material. Keep access to it restricted during the transfer and on the destination.


