This article presents a complete, real-world migration playbook for moving an Oracle Database from an on-premises Exadata X8 to Oracle Database@Azure Autonomous Database Serverless (ADB-S). The two data centres are 70 km apart, connected via a dedicated Azure ExpressRoute circuit. We use Oracle Zero Downtime Migration (ZDM) with GoldenGate replication to achieve a sub-minute application downtime.


Environment Diagram

┌─────────────────────────────────────────────────────────────────┐
│              ON-PREMISES DATA CENTRE (Frankfurt)                  │
│                                                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                EXADATA X8 FULL RACK                       │   │
│  │                                                            │   │
│  │  ┌──────────────┐      ┌──────────────┐                  │   │
│  │  │  x8db01      │      │  x8db02      │   Compute nodes  │   │
│  │  │  (RAC inst1) │      │  (RAC inst2) │                  │   │
│  │  └──────┬───────┘      └──────┬───────┘                  │   │
│  │         └──────── IB ─────────┘                           │   │
│  │              ┌──────────────────┐                         │   │
│  │              │  Storage Cells   │  (8 cells)              │   │
│  │              │ x8cel01–x8cel08  │                         │   │
│  │              └──────────────────┘                         │   │
│  │                                                            │   │
│  │  Database: ORCL (CDB), PDB: PDB_ERPSYS                   │   │
│  │  Size: 3.2 TB (data) + 400 GB indexes                     │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  ZDM Service Host:  zdmhost01.prod.example.com           │   │
│  │  GoldenGate Extract: running on x8db01 (Integrated)      │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                   │
│                     │ Azure ExpressRoute                          │
│                     │ Dedicated, 10 Gbps, 70 km                  │
│                     │ RTT: ~0.7 ms (measured)                    │
│                     │                                            │
└─────────────────────┼──────────────────────────────────────────-─┘
                       │
┌──────────────────────┼──────────────────────────────────────────┐
│    ORACLE DB@AZURE  (West Europe — Amsterdam)                    │
│                       │                                          │
│  ┌────────────────────▼──────────────────────────────────────┐  │
│  │        Oracle Database@Azure — ADB-S                       │  │
│  │        Display Name: adb-erpsys-prod                       │  │
│  │        DB Name:      ADBERPSY                              │  │
│  │        Shape:        16 OCPUs, auto-scale                  │  │
│  │        Storage:      10 TB (elastic)                       │  │
│  │        TLS:          mTLS (wallet-based)                   │  │
│  │                                                            │  │
│  │    OCI GoldenGate (Managed Microservices deployment)       │  │
│  │        GG Service:   gg-erpsys-deployment                  │  │
│  │        Replicat:     REP_ERPSYS (Integrated)               │  │
│  └────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘

Network Architecture

On-Premises Exadata          Azure ExpressRoute          Oracle DB@Azure
  (Frankfurt DC)            (Dedicated, 10 Gbps)         (Amsterdam)
  10.10.0.0/16  ───────────────────────────────────────► 172.16.0.0/16

Key Network Points:
  x8db01 public IP:    10.10.1.101
  x8db01 SCAN IP:      10.10.1.200 (for GoldenGate source connection)
  zdmhost01:           10.10.5.50
  OCI GoldenGate GW:   172.16.10.10 (private endpoint)
  ADB-S private EP:    172.16.20.5  (private endpoint in Oracle DB@Azure VNet)

ExpressRoute Circuit:
  Provider: equinix-frankfurt
  Bandwidth: 10 Gbps dedicated
  Measured RTT (Frankfurt → Amsterdam): 0.7 ms
  Throughput achieved (iperf3): 9.2 Gbps (92% of capacity)

Reference Environment

SOURCE (On-Premises Exadata X8):
  RAC node 1:       x8db01.prod.example.com    (oracle user)
  RAC node 2:       x8db02.prod.example.com
  Storage cells:    x8cel01–x8cel08.prod.example.com
  ZDM host:         zdmhost01.prod.example.com  (oracle user, ZDM installed here)
  DB unique name:   ORCL
  PDB:              PDB_ERPSYS
  Data size:        3.2 TB
  DB version:       19.18.0.0

TARGET (Oracle DB@Azure):
  Region:           Azure West Europe (Amsterdam)
  Resource Group:   rg-oracle-prod
  ADB name:         adb-erpsys-prod
  ADB DB Name:      ADBERPSY
  Service name:     adberpsy_high (high priority service)
  mTLS wallet dir:  /etc/oracle/adb_wallet/ (on zdmhost01)
  OCI GG deploy:    gg-erpsys-deployment (Microservices, managed by Oracle)
  OCI GG version:   21c

ADMIN JUMP HOST:
  admin01.prod.example.com  (used for OCI CLI, ZDM monitoring)

Phase 1: Pre-Migration Assessment

1.1 Network Latency and Throughput Validation

Before any migration work, validate the ExpressRoute circuit performance from the ZDM host:

# [[email protected] ~]
# Test RTT to OCI GoldenGate endpoint via ExpressRoute
ping -c 100 172.16.10.10

# Result:
# rtt min/avg/max/mdev = 0.612/0.718/1.204/0.089 ms  ← Excellent for 70km

# Test throughput
iperf3 -c 172.16.10.10 -t 30 -P 4 -B 10.10.5.50
# [  4]   0.00-30.00  sec  33.5 GBytes  9.35 Gbits/sec  ← 93% of 10Gbps circuit

Impact on SYNC vs ASYNC redo transport: At 0.7 ms RTT, synchronous redo transport (SYNC) would add 0.7ms to every commit — acceptable for most OLTP workloads. However, since the target is ADB-S (which uses async GoldenGate replication, not Data Guard SYNC), this is not a concern here.

1.2 ADB-S Compatibility Assessment

ADB-S has feature restrictions vs on-premises. Run the ZDM evaluation to identify incompatibilities:

# [[email protected] ~]
zdmcli migrate database \
  --sourcesid ORCL \
  --sourcenode x8db01.prod.example.com \
  --srcauth zdmauth \
  --srcarg1 user:oracle \
  --srcarg2 identity_file:/home/oracle/.ssh/id_rsa \
  --targetdatabaseid <adb_ocid> \
  --rsp /u01/zdm/zdm_erpsys.rsp \
  --eval   # evaluation mode — identifies issues, does not migrate

Common ADB-S incompatibilities to resolve before migration:

  • Database links: ADB-S does not support outgoing DB links by default. Replace with REST APIs or Data Pump.
  • Unsupported packages: UTL_FILE, UTL_HTTP — need OCI credentials configured.
  • Directories: OS-level directory objects require migration to ADB-S Object Storage.
  • Custom database options: Spatial, Label Security — verify Oracle support on ADB-S.
  • Java stored procedures: Supported on ADB-S but require testing.

1.3 Enable Supplemental Logging on Source

GoldenGate requires supplemental logging:

-- [[email protected] ~] as sysdba
-- Enable minimal supplemental logging (database level)
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

-- Enable supplemental logging for all columns on mapped tables (PDB level)
ALTER SESSION SET CONTAINER = PDB_ERPSYS;

-- Enable for each application schema (replace ERPSYS_SCHEMA with actual name)
ALTER TABLE ERPSYS_SCHEMA.ORDERS
  ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

-- Or enable for all tables in schema:
EXEC DBMS_CAPTURE_ADM.PREPARE_TABLE_INSTANTIATION(
  table_name => 'ERPSYS_SCHEMA.%'
);

Phase 2: ZDM Configuration

2.1 ZDM Response File

# [[email protected] ~]
# File: /u01/zdm/zdm_erpsys.rsp

# Source
MIGRATION_METHOD=ONLINE_LOGICAL
DATA_TRANSFER_MEDIUM=OSS

# Source DB identification
PLATFORM_TYPE=ORACLE
SOURCE_DATABASE_UNIQUENAME=ORCL
SOURCE_PLUGGABLE_DATABASE_NAME=PDB_ERPSYS

# Target ADB-S
TARGET_DATABASE_UNIQUENAME=ADBERPSY
TARGET_REGION=westeurope
TARGET_COMPARTMENT_ID=ocid1.compartment.oc1..aaaaxxxx

# OCI Object Storage (staging)
OSS_BUCKET_NAME=zdm-migration-bucket
OSS_TENANCY=mytenancy
OSS_REGION=eu-frankfurt-1      # Use OCI Frankfurt for the staging bucket
                                # (closer to on-prem source for upload speed)

# GoldenGate
USE_GOLDENGATE=TRUE
GOLDENGATE_HUB_URL=https://gg-erpsys-deployment.goldengate.europe-west.oci.oraclecloud.com:443
GOLDENGATE_REPLICATION_LAG_MINUTES=1

# Network (ExpressRoute)
# ZDM will use the private endpoints via ExpressRoute automatically
# if routing is configured correctly

# Wallet for ADB-S mTLS
TARGET_WALLET_LOCATION=/etc/oracle/adb_wallet/

# Schema mapping (if source schema differs from target)
# SCHEMA_MAPPING=ERPSYS_SCHEMA:ERPSYS_SCHEMA   # same name: no mapping needed

# Parallel settings for Data Pump
DATAPUMP_PARALLEL_DEGREE=8
EXPORT_ENCRYPTION_KEYSTORE_LOCATION=/etc/oracle/tde_export_key/

2.2 ZDM Migration Timeline (What Happens When)

Migration Timeline:
──────────────────────────────────────────────────────────────────
 T+0h    ZDM_VALIDATE_SRC         Source DB validation
 T+0:30  ZDM_SETUP_SRC            GoldenGate Extract setup on x8db01
 T+0:45  ZDM_EXPORT_DUMP          Data Pump export to OCI Object Storage
          (3.2 TB export at ~1 GB/s → ~55 min via 10 Gbps ExpressRoute)
 T+1:45  ZDM_UPLOAD_DUMP          Object Storage transfer (parallel chunks)
 T+2:00  ZDM_IMPORT_DUMP          Data Pump import to ADB-S
          (import ~3–5x longer than export → ~2.5 hours)
 T+4:30  ZDM_SETUP_TGT_GG        GoldenGate Replicat setup on OCI GG
 T+4:35  ZDM_MONITOR_GG_LAG       Lag monitoring — waiting for near-zero
 T+~5:00 LAG REACHES < 1 MINUTE   Ready for cutover

CUTOVER WINDOW: (application downtime — total < 2 minutes)
─────────────────────────────────────────────────────────
 T+5:00  ZDM_SWITCHOVER_SRC       Stop application, quiesce source
 T+5:01  GoldenGate lag → 0       Last redo applied to ADB-S
 T+5:01  ZDM_SWITCHOVER_TGT       ADB-S is now the active database
 T+5:02  Connection redirect       Application connection strings updated
─────────────────────────────────────────────────────────
TOTAL DOWNTIME: ~60-90 seconds

Phase 3: Execute the Migration

3.1 Start the ZDM Job

# [[email protected] ~]
zdmcli migrate database \
  --sourcesid ORCL \
  --sourcenode x8db01.prod.example.com \
  --srcauth zdmauth \
  --srcarg1 user:oracle \
  --srcarg2 identity_file:/home/oracle/.ssh/id_rsa \
  --srcarg3 sudouser:oracle \
  --targetdatabaseid ocid1.autonomousdatabase.oc1.eu-amsterdam-1.aaaaxxxx \
  --rsp /u01/zdm/zdm_erpsys.rsp \
  --ociProfile DEFAULT

# ZDM returns a job ID immediately:
# Job ID: 42

3.2 Monitor ZDM Phases

# [[email protected] ~]
# Monitor job in real time
watch -n 30 "zdmcli query job -jobid 42"
ZDM Service ZDMSRVC1 started

Operation: "zdmcli migrate database"
Job ID: 42
Status: RUNNING
Started: 2026-03-01 10:00:05 UTC

Current Phase: ZDM_IMPORT_DUMP_SRC_SCHEMAS
Phase Progress:
  [COMPLETED] ZDM_VALIDATE_SRC            2026-03-01 10:00:30  (00:00:25)
  [COMPLETED] ZDM_SETUP_SRC              2026-03-01 10:03:12  (00:02:42)
  [COMPLETED] ZDM_EXPORT_DUMP            2026-03-01 11:01:47  (00:58:35)
  [COMPLETED] ZDM_UPLOAD_DUMP            2026-03-01 11:06:03  (00:04:16)
  [RUNNING  ] ZDM_IMPORT_DUMP_SRC_SCHEMAS 2026-03-01 11:06:10  (01:24:00)
  [PENDING  ] ZDM_SETUP_TGT_GG
  [PENDING  ] ZDM_MONITOR_GG_LAG
  [PENDING  ] ZDM_SWITCHOVER_SRC
  [PENDING  ] ZDM_SWITCHOVER_TGT

3.3 Monitor GoldenGate Lag Once Replication Starts

# [[email protected] ~]
# Once ZDM_SETUP_TGT_GG is complete, monitor lag via OCI GG REST API
GG_HOST="https://gg-erpsys-deployment.goldengate.europe-west.oci.oraclecloud.com"
GG_USER="oggadmin"
GG_PASS="OggPass1#"

watch -n 10 "curl -s -u ${GG_USER}:${GG_PASS} \
  ${GG_HOST}:443/services/v2/replicats/REP_ERPSYS/statistics \
  | python3 -m json.tool | grep -E '\"lag\"|\"status\"'"
{
  "lag": "00:00:08",
  "status": "running"
}

Lag of 8 seconds means the ADB-S target is 8 seconds behind the source. As application load is stable, this should converge to < 1 second within 30 minutes.

Lag Convergence Chart:

GoldenGate Lag Over Time
60s |██████
50s |████████
40s |██████████
30s |████████████
20s |██████████████████
15s |██████████████████████
10s |████████████████████████████
 8s |████████████████████████████████
 5s |████████████████████████████████████
 2s |████████████████████████████████████████
 1s |██████████████████████████████████████████── Stable here ✓
    +─────────────────────────────────────────
    T+4:00           T+4:30           T+5:00

Phase 4: Cutover (Sub-2-Minute Downtime)

When GoldenGate lag is consistently < 30 seconds, coordinate the cutover with the application team.

4.1 Cutover Checklist (Run in Order)

# Step 1: [App Team] Put application in maintenance mode (stop accepting new connections)
# Display maintenance page on application tier

# Step 2: [[email protected] ~]
# Verify no active transactions on source
sqlplus / as sysdba
SQL> SELECT COUNT(*) FROM v$transaction;  -- Should be 0

# Step 3: [[email protected] ~]
# Wait for GoldenGate lag to reach ZERO
watch -n 2 "curl -s -u oggadmin:OggPass1# \
  https://gg-erpsys-deployment.goldengate.europe-west.oci.oraclecloud.com:443/services/v2/replicats/REP_ERPSYS/statistics \
  | python3 -c \"import json,sys; d=json.load(sys.stdin); print('Lag:', d.get('lag','?'), '| Status:', d.get('status','?'))\""
Lag: 00:00:00 | Status: running   ← Lag is zero — proceed with cutover
# Step 4: [[email protected] ~]
# Trigger ZDM switchover (handles source restriction + GG stop cleanly)
zdmcli switchover job -jobid 42
# Step 5: [App Team] Update application connection strings
# FROM: jdbc:oracle:thin:@//x8db01.prod.example.com:1521/PDB_ERPSYS
# TO:   jdbc:oracle:thin:@adberpsy_high?TNS_ADMIN=/etc/oracle/adb_wallet

# Or update environment variable:
export DB_URL="jdbc:oracle:thin:@adberpsy_high?TNS_ADMIN=/etc/oracle/adb_wallet"

# Step 6: [App Team] Remove maintenance mode and verify application connects to ADB-S

4.2 Downtime Timer

10:02:15 — Application maintenance mode ACTIVE (stop accepting connections)
10:02:18 — Source quiesced (0 active transactions confirmed)
10:02:22 — GoldenGate lag = 00:00:00
10:02:25 — zdmcli switchover issued
10:02:41 — ZDM confirms switchover complete (16 seconds)
10:03:08 — Application connection string updated
10:03:12 — Application health check PASSED on ADB-S
──────────────────────────────────────────────────────────
TOTAL DOWNTIME: 57 seconds  ✓

Phase 5: Post-Migration Validation

5.1 Data Integrity Check

-- [admin@adb-erpsys-prod Oracle Database@Azure]
-- Connect to ADB-S using wallet
sqlplus admin/AdminPass1#@adberpsy_high

-- Row count comparison for critical tables
SELECT 'ORDERS' AS table_name, COUNT(*) AS row_count FROM ERPSYS_SCHEMA.ORDERS
UNION ALL
SELECT 'ORDER_ITEMS', COUNT(*) FROM ERPSYS_SCHEMA.ORDER_ITEMS
UNION ALL
SELECT 'CUSTOMERS', COUNT(*) FROM ERPSYS_SCHEMA.CUSTOMERS
UNION ALL
SELECT 'PRODUCTS', COUNT(*) FROM ERPSYS_SCHEMA.PRODUCTS;

Compare against the same query run on the source immediately before cutover.

5.2 Performance Baseline Comparison

-- On ADB-S: check automatic indexing status after 24 hours
SELECT DBMS_AUTO_INDEX.REPORT_ACTIVITY(
  activity_start => SYSDATE - 1,
  activity_end   => SYSDATE,
  type           => 'TEXT',
  section        => 'SUMMARY'
) FROM DUAL;

-- Check query performance vs source baseline
SELECT sql_id, elapsed_time / 1e6 AS elapsed_secs, executions
FROM v$sqlstats
WHERE elapsed_time / 1e6 > 5   -- queries taking more than 5 seconds
ORDER BY elapsed_time DESC
FETCH FIRST 20 ROWS ONLY;

5.3 ADB-S-Specific Post-Migration Tasks

-- Enable features that ADB-S provides automatically
-- (verify they are active)
SELECT feature_name, is_enabled
FROM dba_feature_usage_statistics
WHERE feature_name IN (
  'Automatic Indexing',
  'Real-Time Statistics',
  'SQL Plan Management'
);

-- Verify HCC compression on analytical tables
SELECT table_name, compress_for, compression
FROM dba_tables
WHERE owner = 'ERPSYS_SCHEMA'
  AND compress_for IN ('QUERY HIGH', 'QUERY LOW')
ORDER BY table_name;

Phase 6: Decommission the Exadata Source

Only after:

  • 4 weeks of stable production operation on ADB-S.
  • All application teams confirm performance and data integrity.
  • Backup retention window fulfilled (archived source backups retained for contractual period).
  • Legal/compliance sign-off on decommission.
# [[email protected] ~]
# Final: stop databases and cluster (coordinate with facilities for power-down)
srvctl stop database -d ORCL
crsctl stop cluster -all

# Notify Oracle hardware team for Exadata X8 decommission and asset return

Key Takeaways for This Architecture

  • The 70 km ExpressRoute link at 0.7ms RTT is transparent to the migration — Data Pump export achieves near-full bandwidth and GoldenGate lag converges quickly.
  • GoldenGate is the zero-downtime enabler — without it, migration would require hours of downtime for a 3.2 TB database. With it, downtime is under 2 minutes.
  • ADB-S auto-management takes over after migration — no manual patching, no manual statistics gathering, and automatic indexing progressively improves workload performance over the first days.
  • ExpressRoute vs VPN: A VPN would introduce encryption overhead and higher latency. For production migrations, dedicated ExpressRoute is the right choice.
  • OCI GoldenGate handles the replication entirely in the cloud — no GoldenGate binaries to install on the source beyond what ZDM sets up automatically.