While testing EVENTACTIONS (SUSPEND) on an extract, I noticed that nothing in INFO tells you the process is suspended. The extract shows as RUNNING, the lag might look fine for a while, and yet it has stopped capturing. You may use SUSPEND on purpose (to pause an extract when a specific DDL goes by, for instance). Or someone else put it in a parameter file and you have to monitor the result. Either way, you need another way to know.

In the end, SEND EXTRACT ... STATUS is the only command that reports the suspended state, and it works the same way through the REST API, where the text is already parsed for you. A simpler check exists in the report file, generating an OGG-01281, but it has a limit I will show at the end.

In this blog, I will run an EXT1 extract capturing from PDB1. It has a DDL EVENTACTIONS trigger on a CREATE USER statement run in PDB1. The trigger suspends the extract whenever a user is created:

EXTRACT EXT1
USERIDALIAS pdb1 DOMAIN OracleGoldenGate
EXTTRAIL pdb1/e1
DDL INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (SUSPEND)
DDLOPTIONS REPORT
TABLE APP_PDB1.*;

Extract status before SUSPEND

Once started, the extract shows as RUNNING in INFO ALL:

OGG (http://vmogg:7810 ogg_test_01) 2> INFO ALL
Program     Status      Group       Type                   Lag at Chkpt       Time Since Chkpt

EXTRACT     RUNNING     EXT1        INTEGRATED                  00:00:00           00:00:06

SEND EXTRACT EXT1 STATUS reports where the extract is in its life cycle. Here, the extract has nothing to capture, so the status is At EOF:

OGG (http://vmogg:7810 ogg_test_01) 2> SEND EXTRACT EXT1 STATUS

Sending STATUS request to Extract group EXT1 ...

EXTRACT EXT1 (PID 21617)
  Current status: Recovery complete: At EOF

  Current read position:
  Redo thread #: 0
  Sequence #: 0
  RBA: 0
  Timestamp: 2026-09-26 06:26:24.000000
  SCN: 0.115334476 (115334476)
  Current write position:
  Sequence #: 11
  RBA: 6942
  Timestamp: 2026-09-26 06:26:20.463368
  Extract Trail: pdb1/e1

Suspending the extract

Let’s create a user in PDB1, which matches the DDL rule:

SQL> CREATE USER SUSPTEST IDENTIFIED BY "Suspend_Test_1";

User created.

Half a minute later, INFO EXT1 still says RUNNING with a lag of 0 seconds, but the checkpoint was last updated 30 seconds ago:

OGG (http://vmogg:7810 ogg_test_01) 2> INFO EXT1

Extract    EXT1      Last Started 2026-09-26 06:26   Status RUNNING
Checkpoint Lag       00:00:00 (updated 00:00:30 ago)
Process ID           21617
Log Read Checkpoint  Oracle Integrated Redo Logs, per-PDB
                     2026-09-26 06:26:18
                     SCN 0.115334462 (115334462)
Encryption Profile   LocalWallet
No Replicat groups found, but some coordinated threads may have been excluded.

Two minutes after the CREATE USER, the same command gives:

OGG (http://vmogg:7810 ogg_test_01) 2> INFO EXT1

Extract    EXT1      Last Started 2026-09-26 06:26   Status RUNNING
Checkpoint Lag       00:00:00 (updated 00:02:00 ago)
Process ID           21617
Log Read Checkpoint  Oracle Integrated Redo Logs, per-PDB
                     2026-09-26 06:26:18
                     SCN 0.115334462 (115334462)
Encryption Profile   LocalWallet
No Replicat groups found, but some coordinated threads may have been excluded.

The status is still RUNNING, and the lag value does not grow: Checkpoint Lag stays at 00:00:00. What grows is the time since the checkpoint was updated (updated 00:00:30 ago, then updated 00:02:00 ago), and the checkpoint position (SCN 0.115334462) never moves. That is a hint that something is wrong (or right), but nothing in this output says it is a suspend.

SEND EXTRACT STATUS shows the suspended state

Now the same SEND EXTRACT EXT1 STATUS as before:

OGG (http://vmogg:7810 ogg_test_01) 2> SEND EXTRACT EXT1 STATUS

Sending STATUS request to Extract group EXT1 ...

EXTRACT EXT1 (PID 21617)
  Current status: Recovery complete: Suspended, waiting to be resumed

  Current read position:
  Redo thread #: 1
  Sequence #: 3045
  RBA: 58777616
  Timestamp: 2026-09-26 06:26:27.000000
  SCN: 0.115334507 (115334507)
  Current write position:
  Sequence #: 11
  RBA: 6942
  Timestamp: 2026-09-26 06:26:20.463368
  Extract Trail: pdb1/e1

Comparing the two outputs, the only line that tells you the extract is suspended is Current status:

  • Before: Current status: Recovery complete: At EOF. It could have been some other message if it was still extracting.
  • After: Current status: Recovery complete: Suspended, waiting to be resumed

Everything else in INFO is compatible with a healthy extract. To resume it, run SEND EXTRACT EXT1 RESUME.

Which command shows the suspend?

STATUS EXTRACT looks like the natural command, but it is not the same as SEND EXTRACT ... STATUS. On the suspended extract, STATUS EXTRACT gives:

OGG (http://vmogg:7810 ogg_test_01) 4> STATUS EXTRACT EXT1
EXTRACT EXT1: RUNNING

INFO EXT1 DETAIL adds the trail, the outbound server SCNs and the file locations, but its header is the same as INFO EXT1:

OGG (http://vmogg:7810 ogg_test_01) 5> INFO EXT1 DETAIL

Extract    EXT1      Last Started 2026-09-26 06:26   Status RUNNING
Checkpoint Lag       00:00:00 (updated 00:02:00 ago)
Process ID           21617
Log Read Checkpoint  Oracle Integrated Redo Logs, per-PDB
                     2026-09-26 06:26:18
                     SCN 0.115334462 (115334462)
Encryption Profile   LocalWallet

  Target Extract Trails:

  Trail Name                                       Seqno        RBA     Max MB Trail Type

  pdb1/e1                                             11       6942       2000 EXTTRAIL

Integrated Extract outbound server first scn: 0.115313606 (115313606)

Integrated Extract outbound server filtering start scn: 0.115313606 (115313606)
CommandBefore the suspendAfter the suspend
INFO ALLRUNNINGRUNNING
INFO EXT1RUNNINGRUNNING
INFO EXT1 DETAILRUNNINGRUNNING
STATUS EXTRACT EXT1RUNNINGRUNNING
SEND EXTRACT EXT1 STATUSRecovery complete: At EOFRecovery complete: Suspended, waiting to be resumed

Only SEND EXTRACT ... STATUS shows the suspend. STATUS EXTRACT, like INFO, just reports the state of the process.

Getting the status with the REST API

The SEND commands are available through the /services/{version}/extracts/{extract}/command endpoint, and the response already contains the parsed status.

With the oggrestapi Python client

With the GoldenGate Python client, execute_command_extract sends the request. First, initialize the client:

>>> from oggrestapi import OGGRestAPI
>>> ogg_client = OGGRestAPI(
    url='http://vmogg:7810',
    username='ogg',
    password='ogg'
)
Connected to OGG REST API at http://vmogg:7810

Here is the raw output given by the execute_command_extract method:

>>> resp = ogg_client.execute_command_extract('EXT1', data={'command': 'STATUS'})
>>> resp
{'$schema': 'er:commandResult', 'reply': 'OKNODOT\tEXTRACT EXT1 (PID 41522)\n  Current status: Recovery complete: Suspended, waiting to be resumed\n\n  Current read position:\n  Redo thread #: 1\n  Sequence #: 3047\n  RBA: 92686352\n  Timestamp: 2026-09-26 08:48:41.000000\n  SCN: 0.115434621 (115434621)\n  Current write position:\n  Sequence #: 1\n  RBA: 5679\n  Timestamp: 2026-09-26 08:48:37.669072\n  Extract Trail: pdb1/r1\n\n', 'replyData': {'$schema': 'er:statusResult', 'status': {'groupName': 'EXT1', 'processId': '41522', 'processType': 'extract', 'status': 'Recovery complete: Suspended, waiting to be resumed', 'extractReadingPosition': [{'$schema': 'dbms:positionInfo', 'position': {'redoThread': 1, 'csn': 115434621, 'seqno': 3047, 'rba': 92686352, 'timestamp': '2026-09-26T08:48:41.000Z'}}], 'extractWritingPosition': [{'$schema': 'ogg:trailPosition', 'sequence': 1, 'offset': 5679, 'name': 'r1', 'path': 'pdb1/'}]}}}

In GoldenGate REST API, the status is available in replyData.status.status:

>>> resp['replyData']['status']['status']
'Recovery complete: Suspended, waiting to be resumed'

To avoid repeating the replyData navigation everywhere, custom methods are available in oggrestapi:

def get_extract_status_detail(self, extract):
    result = self.execute_command_extract(extract, data={'command': 'STATUS'})
    return str(result.get('replyData', {}).get('status', {}).get('status', ''))

def is_extract_suspended(self, extract):
    return 'suspended' in self.get_extract_status_detail(extract).lower()
>>> ogg_client.get_extract_status_detail('EXT1')
'Recovery complete: Suspended, waiting to be resumed'

>>> ogg_client.is_extract_suspended('EXT1')
True

With the requests module

Without the client, send STATUS as the command with the requests library:

import requests

url = 'http://vmogg:7810/services/v2/extracts/EXT1'
auth = ('ogg', 'ogg')

response = requests.post(f'{url}/command', auth=auth, json={'command': 'STATUS'}).json()['response']

The response contains the same replyData field, with the status already extracted:

>>> response['replyData']['status']['status']
'Recovery complete: Suspended, waiting to be resumed'

Note that this is not the same as the info/status endpoint, which returns the process state as INFO does. It says running for a suspended extract, but it holds the two values behind the lag line of INFO:

>>> requests.get(f'{url}/info/status', auth=auth).json()['response']
{'$schema': 'ogg:extractStatus', 'status': 'running', 'processId': 21617, 'lastStarted': '2026-09-26T06:26:09.798Z', 'lag': 0, 'sinceLagReported': 125, 'position': '0.115334462'}

lag is the checkpoint lag of INFO, and sinceLagReported is the updated ... ago value in seconds.

Adding a lag check

For a monitoring script, the status can be paired with a lag check. get_extract_status costs a single GET call, and a healthy extract keeps updating its checkpoint. A large sinceLagReported is a cheap first filter before sending the STATUS command:

>>> status = ogg_client.get_extract_status('EXT1')
>>> status['status'] == 'running' and status['sinceLagReported'] > 60 and ogg_client.is_extract_suspended('EXT1')
True

When this returns True, you have a running extract that has not moved for more than a minute and that reports itself as suspended. Whether you should then resume it depends on why the SUSPEND was there in the first place. An alert is usually the right answer. If you do want to resume it from the script, it is another execute_command_extract call:

>>> ogg_client.execute_command_extract('EXT1', data={'command': 'RESUME'})

A simpler check: OGG-01281 in the report

The suspend also leaves a trace in the extract report file, with the OGG-01281 message:

2026-09-26 06:26:29  INFO    OGG-00487  DDL operation included [INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (SUSPEND)], optype [CREATE], objtype [USER], objowner "", objname "SUSPTEST".

2026-09-26 06:26:30  INFO    OGG-01281  Processed SUSPEND event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.

Is this message specific to SUSPEND? To check it, I ran the same DDL rule with other EVENTACTIONS, recreating the user each time:

# DDL INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (ROLLOVER)
2026-09-26 06:29:32  INFO    OGG-01285  Processed ROLLOVER event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.

# DDL INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (LOG INFO)
2026-09-26 06:30:37  INFO    OGG-06117  Processed LOG event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.

# DDL INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (LOG WARNING)
2026-09-26 06:31:40  WARNING OGG-06118  Processed LOG event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.

ROLLOVER raises OGG-01285, and LOG raises OGG-06117 (or OGG-06118 with WARNING). IGNORE raises nothing at all beyond the OGG-00487 line. So OGG-01281 is only raised by SUSPEND.

The limit of this check is that the report is a history, not a state. When resuming the extract, the OGG-01281 line stays in the report, and a new message is written after it:

2026-09-26 06:26:30  INFO    OGG-01281  Processed SUSPEND event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.
2026-09-26 06:28:29  INFO    OGG-01824  Resume processing from SUSPEND state for process EXT1.

Finding OGG-01281 in the report does not mean the extract is suspended now. You have to check that no OGG-01824 comes after it. On top of that, the report is rolled over at each restart of the extract, so it only covers the current run. With the REST API, the report is available through get_extract_report, whose lines key contains the list of lines:

>>> report = ogg_client.get_extract_report('EXT1', 'EXT1.rpt')
>>> [line for line in report['lines'] if 'OGG-01281' in line or 'OGG-01824' in line]
['2026-09-26 06:26:30  INFO    OGG-01281  Processed SUSPEND event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.']

This is useful to find out when and why the extract was suspended, since the message contains the object that triggered it. But to know whether it is suspended right now, STATUS is the reliable way.

The full check in one script

Here is a small script with everything seen in this blog. It runs the lag check, the suspend check, and the log analysis to find the culprit, then prints an info message.

from oggrestapi import OGGRestAPI

ogg_client = OGGRestAPI(url='http://vmogg:7810', username='ogg', password='ogg')

extract = 'EXT1'
status = ogg_client.get_extract_status(extract)

# Lag check: a running extract whose checkpoint has not moved for a minute
if status['status'] == 'running' and status['sinceLagReported'] > 60:
    # Suspend check
    if ogg_client.is_extract_suspended(extract):
        # Log analysis: the last OGG-01281 or OGG-01824 tells who suspended it
        report = ogg_client.get_extract_report(extract, f'{extract}.rpt')
        events = [line for line in report['lines'] if 'OGG-01281' in line or 'OGG-01824' in line]
        if events and 'OGG-01281' in events[-1]:
            print(f'INFO: {extract} is suspended. Culprit: {events[-1]}')
        else:
            print(f'INFO: {extract} is suspended, but no OGG-01281 in the current report')
    else:
        print(f'INFO: {extract} is not suspended, but its checkpoint has not moved for {status["sinceLagReported"]} seconds')
else:
    print(f'INFO: {extract} is not suspended')
INFO: EXT1 is suspended. Culprit: 2026-09-26 06:26:30  INFO    OGG-01281  Processed SUSPEND event from DDL on object name SUSPTEST, DDL seqno 0, marker seqno 0.

What about replicats?

It works the same way for a replicat. I tested it with an integrated replicat applying the trail of EXT1, with DDL INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (SUSPEND) in its parameter file. INFO reports RUNNING, and SEND REPLICAT REP1 STATUS reports the suspended state. is_replicat_suspended returns True, and SEND REPLICAT REP1 RESUME resumes it with an OGG-01824.

The suspend is still logged with OGG-01281, but the culprit is not named. The replicat suspends before applying the DDL, so the report says object name N/A. The user name only appears in the OGG-00487 line after the resume operation:

2026-09-26 08:56:19  INFO    OGG-01281  Processed SUSPEND event from DDL on object name N/A in file /u01/app/ogg/deployments/ogg_test_01/var/lib/data/pdb1/q1000000000, RBA 5284.
2026-09-26 08:58:02  INFO    OGG-01824  Resume processing from SUSPEND state for process REP1.
2026-09-26 08:58:02  INFO    OGG-00487  DDL operation included [INCLUDE ALL OBJTYPE 'USER' OPTYPE CREATE EVENTACTIONS (SUSPEND)], optype [CREATE], objtype [USER], objowner "", objname "SUSPTEST".

Summary

To know whether a GoldenGate extract is suspended by an EVENTACTIONS (SUSPEND) rule:

  • Do not rely on INFO ALL, INFO, INFO DETAIL or STATUS EXTRACT. They all report RUNNING, and the checkpoint lag stays the same. Only the updated ... ago value grows.
  • Run SEND EXTRACT EXT1 STATUS in the adminclient: Current status: Recovery complete: Suspended, waiting to be resumed appears when the extract is suspended.
  • In a script, use is_extract_suspended from the Python client, or send the same STATUS command to /services/v2/extracts/EXT1/command and read replyData.status.status.
  • Filter with sinceLagReported from info/status (for instance more than 60 seconds) before sending the STATUS command.
  • Use OGG-01281 in the report to find out when and why the extract was suspended, and check that no OGG-01824 came after it.
  • Resume with SEND EXTRACT EXT1 RESUME, or with the RESUME command through execute_command_extract.