GoldenGate replication has three stages, and each one fails differently under load: Extract can fall behind on redo mining, the Pump/Distribution path can saturate the network, and Replicat can bottleneck applying changes to the target. Tuning the wrong stage wastes time and rarely moves the needle — the first job is always figuring out where the lag actually is.
1. Locate the Bottleneck Before Touching Parameters
Every tuning exercise starts with LAG and INFO, not with changing parameters blindly.
GGSCI> SEND EXTRACT EXT1, GETLAG
GGSCI> LAG EXTRACT EXT1
GGSCI> LAG REPLICAT REP1
GGSCI> STATS EXTRACT EXT1, TOTALSONLY *
GGSCI> STATS REPLICAT REP1, TOTALSONLY *
Two lag numbers matter, and they point at different problems:
| Symptom | Likely Cause | Where to Look |
|---|---|---|
| Extract lag grows, Replicat lag stays flat | Source redo mining can’t keep up | Extract parallelism, TRANLOGOPTIONS, undo retention |
| Extract lag flat, Replicat lag grows | Target apply can’t keep up | Replicat parallelism, target indexing, BATCHSQL |
| Both grow together | Network/trail path bottleneck | Pump compression, trail file size, bandwidth |
| Lag spikes only during batch windows | Source workload burst (bulk loads, month-end) | Coordinated Replicat, temporary parallelism increase |
In Microservices deployments, the Performance Metrics Service exposes the same data over REST, which is easier to feed into a dashboard than parsing GGSCI output:
curl -u oggadmin:Password1 \
http://localhost:9011/services/v2/extracts/EXT1/statistics
2. Extract-Side Tuning
Integrated Extract Parallelism
On 19c+, Integrated Extract can mine redo in parallel via the logmining server. This is the single biggest lever for high-volume OLTP sources.
-- Check current mining session parallelism
SELECT CAPTURE_NAME, PARALLELISM, STATUS
FROM V$GOLDENGATE_CAPTURE;
-- Increase mining parallelism (source-side, requires DBA privilege)
BEGIN
DBMS_CAPTURE_ADM.SET_PARAMETER(
capture_name => 'OGG$CAP_EXT1',
parameter => 'parallelism',
value => '4');
END;
/
Reduce Unnecessary Capture Work
Every extra table or column captured costs mining throughput. Scope TABLE statements tightly and use COLSEXCEPT rather than capturing wide tables you don’t need in full:
TABLE hr.employees, COLSEXCEPT (large_notes_column, audit_blob);
Checkpoint and Read Buffer Tuning
-- ext1.prm
TRANLOGOPTIONS INTEGRATEDPARAMS (MAX_SGA_SIZE 512, PARALLELISM 4)
CHECKPOINTSECS 10
DBOPTIONS ALLOWUNUSEDCOLUMN
CHECKPOINTSECS trades checkpoint overhead against recovery time on restart — 10-30 seconds is a reasonable middle ground for most production sources. Going too low adds I/O overhead for no real benefit; going too high increases how much Extract has to re-mine after a crash.
Undo Retention
Long-running transactions plus insufficient undo retention cause ORA-01555 on the mining session, which stalls Extract entirely, not just slows it down. If your source has long transactions, verify undo retention is sized for the longest expected transaction, not just the default:
SELECT tablespace_name, retention FROM dba_tablespaces
WHERE tablespace_name = (SELECT value FROM v$parameter WHERE name = 'undo_tablespace');
3. Trail Files and the Distribution Path
Trail File Sizing
Trail files that are too small generate excessive file-switch overhead; too large delays Pump/Replicat catching up after a restart because more data has to be reread.
EXTTRAIL ./dirdat/lt, MEGABYTES 500
500MB-1GB is a reasonable default for most OLTP workloads. Bump it to 2GB+ only for very high-throughput pipelines where file-switch frequency is itself measurable overhead.
Network Compression
For WAN-distributed topologies (cross-region DR, cross-cloud replication), compression on the Distribution Service or Pump extract materially reduces bandwidth cost at a modest CPU tax:
-- In the Distribution Service path, or classic Pump parameter file
RMTHOST target-host, MGRPORT 7809, COMPRESS
Benchmark this — compression helps most when the network is the bottleneck (cross-region), and helps least when CPU on the sending host is already the constraint (e.g., a heavily loaded Exadata compute node also running Extract).
Parallel Pump Paths
A single Pump process serializes everything flowing to a target. For high-throughput pipelines, splitting into multiple Pumps by table range or schema avoids a single-threaded distribution bottleneck:
GGSCI> ADD EXTRACT PMP1, EXTTRAILSOURCE ./dirdat/lt
GGSCI> ADD RMTTRAIL ./dirdat/rt, EXTRACT PMP1
-- PMP1 handles schema A, PMP2 handles schema B, etc.
4. Replicat-Side Tuning
This is where most real-world bottlenecks live, because apply on the target is usually more expensive than capture on the source (constraint checks, index maintenance, trigger overhead).
Parallel / Coordinated Replicat
Classic Replicat is single-threaded per process. Coordinated Replicat splits apply across multiple threads while preserving transactional dependency ordering:
-- rep1.prm
REPLICAT REP1
COORDINATED MAXTHREADS 8
MAP source.*, TARGET target.*;
On 19c+, Parallel Replicat goes further, using an in-memory dependency graph to apply non-conflicting transactions concurrently without manual thread-to-table mapping:
GGSCI> ADD REPLICAT REP1, PARALLEL, EXTTRAIL ./dirdat/rt
Parallel Replicat is generally the better default on modern versions — Coordinated Replicat still has a place when you need explicit control over which threads handle which tables (e.g., to avoid hot-row contention on a specific table).
BATCHSQL
Batches multiple DML operations into fewer round trips to the target database. Large win for high-volume inserts/updates with low conflict rates:
REPLICAT REP1
BATCHSQL BATCHTRANSOPS 1000, BATCHESPERQUEUE 10
Turn this off (or reduce batch size) if the target table has heavy trigger logic or foreign key constraints that behave poorly under batched apply — batching can obscure which individual statement failed, complicating troubleshooting.
Target-Side Indexing
Replicat apply performance is bound by target index maintenance as much as anything GoldenGate-side. Two common fixes:
- Ensure every table being replicated into has a primary key or unique index GoldenGate can use for
UPDATE/DELETErow lookups — without one, GoldenGate falls back to full-table-scan-per-row logic (KEYCOLScan help if no real key exists). - Drop non-essential secondary indexes during large initial loads, rebuild after.
-- Explicit key mapping when no PK/UK is usable
MAP source.orders, TARGET target.orders, KEYCOLS (order_id, order_date);
Handling Long-Running or Skewed Transactions
A single large source transaction (bulk update touching millions of rows) will serialize apply on that transaction regardless of parallelism settings elsewhere, since GoldenGate preserves transactional boundaries by default. There’s no tuning parameter that fixes this — it has to be addressed at the source, either by breaking large batch jobs into smaller committed chunks or by accepting that lag will spike during those windows and sizing SLAs accordingly.
5. Quick Reference: Parameter Impact
| Parameter | Stage | Effect |
|---|---|---|
TRANLOGOPTIONS INTEGRATEDPARAMS PARALLELISM |
Extract | More mining threads on source redo |
CHECKPOINTSECS |
Extract | Checkpoint frequency vs. overhead |
MEGABYTES (trail) |
Trail | File-switch frequency vs. reread cost |
COMPRESS |
Pump/Distribution | Bandwidth vs. CPU tradeoff |
COORDINATED MAXTHREADS |
Replicat | Manual parallel apply |
PARALLEL |
Replicat | Automatic dependency-aware parallel apply |
BATCHSQL |
Replicat | Fewer round trips, less per-row visibility |
KEYCOLS |
Replicat | Avoids full-scan row lookups on keyless tables |
6. A Worked Example
A pipeline replicating an OLTP order-processing schema (200 tables, ~15M row changes/day) was showing steady Replicat lag growth during nightly batch windows only.
LAGconfirmed Extract was flat; Replicat lag climbed from 09:00 UTC batch start.STATS REPLICATshowed apply throughput capped well below Extract’s capture rate.- Target-side investigation found the
order_line_itemstable had no usable key for 40% of the row volume — GoldenGate was falling back to full-row-image matching. - Adding explicit
KEYCOLSmapping plus switching from Coordinated to Parallel Replicat closed the gap; lag during batch windows dropped from ~45 minutes to under 3.
The fix wasn’t a GoldenGate parameter in isolation — it was diagnosing that the bottleneck was target-side row lookup cost, which no amount of Extract tuning would have touched.
Summary
Tune in this order: confirm which side is actually lagging, fix Extract mining parallelism and undo retention if the source is the bottleneck, tune trail size and compression if the network path is the bottleneck, and reach for Parallel Replicat, BATCHSQL, and target-side keys/indexes if apply is the bottleneck. Changing Replicat parameters when Extract is the actual constraint (or vice versa) is the most common wasted-effort mistake in GoldenGate tuning.