Pyxis Logo
Home / IBM Training / Technical article

“ A Second look into the z/OS JCL GDGBIAS Parameter"

A practical article that shows how GDGBIAS=JOB and GDGBIAS=STEP change GDG relative generation resolution across job steps.

16 min read
Published 2026-05-25
Pyxis editorial team
Rate this article
Average rating: Not rated
Your rating: Not rated
visualizations: 0
Abstract mainframe-style illustration showing sequential generation data groups shifting across z/OS job steps

GDGBIAS is one of those JCL controls that looks small on the JOB statement and then changes the meaning of an entire batch flow.

If a job creates and later reuses MY.GDG(+1), we can ask the following question:

  • Should later steps keep using the same relative-to-absolute mapping established earlier in the job?
  • or should z/OS recalculate the meaning of (0) and (+1) at each step boundary?

That is exactly what GDGBIAS controls. This article discusses the GDGBIAS behaviour and shows JCL you can run to observe how GDGBIAS=JOB and GDGBIAS=STEP behave differently.

1. Lab goals

By the end of this article you should be able to:

  • Explain the difference between GDGBIAS=JOB and GDGBIAS=STEP
  • Predict how (0) and (+1) are resolved after a prior step catalogs a new generation
  • Build a small test GDG and reproduce the difference in batch
  • Recognize where VOL=REF, passed data sets, and utility-driven catalog changes make the choice more important

2. Required environment

For the practical part, use:

  • z/OS 2.1 or later
  • JES2 or JES3

3. First things first

z/OS keeps an internal mapping between a GDG relative reference and the absolute generation name that will actually be allocated.

Assume that your catalog currently contains the current generation as:

&SYSUID..GDGTEST.BASE.G0010V00

then the relative names are resolved as shown below:

  • (0) is mapped to G0010V00 (unless there is Vnn with nn > 00)
  • (+1) maps to the next generation, for example G0011V00

The question is what happens after a step in the same job catalogs that G0011V00 generation. And the GDGBIAS value will matter. GDGBIAS accepts two values (JOB and STEP) that provide different behaviours:

AttributeGDGBIAS=JOBGDGBIAS=STEP
Resolution pointFirst GDG reference in the jobStart of each step
Mapping persistencePreserved across later stepsRebuilt at every step boundary
Step 2 meaning of (0) after Step 1 created (+1)Still the generation that was current before Step 1The generation just created by Step 1
Step 2 meaning of (+1) after Step 1 created (+1)Still the generation created earlier in the jobA brand new next generation

That means GDGBIAS=JOB gives step-to-step stability inside one job, while GDGBIAS=STEP gives step-to-step recataloging against current catalog state.

4. Practical setup: Define a disposable test GDG

Before comparing the two bias modes, create a small GDG base and one initial generation. Copy and submit the JCL below (you may need to adjust the JOB card to fit your installation requirements):

//GDGPREP  JOB ,'GDG PREP',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//DELETE   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DELETE &SYSUID..GDGTEST.BASE GDG FORCE
  IF LASTCC LE 8 THEN SET MAXCC = 0
/*
//DEFINE   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DEFINE GDG (NAME(&SYSUID..GDGTEST.BASE) LIMIT(5) NOEMPTY SCRATCH)
/*
//SEED     EXEC PGM=IEFBR14
//G0001    DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA

Verify the starting point with ISPF 3.4 or LISTCAT. At this point you should have exactly one current generation under the base.:

//GDGLIST  JOB ,'GDG LIST',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//LISTCAT  EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  LISTCAT ENTRIES(&SYSUID..GDGTEST.BASE) ALL
/*

6. GDGBIAS=JOB behaviour

Submit a two-step job that:

1. Creates a new (+1) generation 2. In the next step, tries to read (+1) as a cataloged data set

//GDGJOB   JOB ,'GDG JOB BIAS',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID,
//             GDGBIAS=JOB
//STEP1    EXEC PGM=IEFBR14
//NEWGEN   DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA
//STEP2    EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   DSN=&SYSUID..GDGTEST.BASE(+1),DISP=SHR
//SYSUT2   DD   SYSOUT=*
//SYSIN    DD   DUMMY

As expected outcome, STEP1 catalogs a new generation and STEP2 succeeds because:

  • Under GDGBIAS=JOB, the relative mapping built earlier in the job remains in effect
  • The (+1) in STEP2 still means the same absolute generation created in STEP1

This is the classic frozen-job-view behaviour.

7. GDGBIAS=STEP behaviour

Now submit the same job logic with step-level GDGBIAS:

//GDGSTEP  JOB ,'GDG STEP BIAS',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID,
//             GDGBIAS=STEP
//STEP1    EXEC PGM=IEFBR14
//NEWGEN   DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA
//STEP2    EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   DSN=&SYSUID..GDGTEST.BASE(+1),DISP=SHR
//SYSUT2   DD   SYSOUT=*
//SYSIN    DD   DUMMY

This time, STEP1 succeeds and catalogs a new generation but STEP2 fails allocation. Why does it fail?

  • Under GDGBIAS=STEP, z/OS clears the earlier mapping at the step boundary
  • When STEP2 starts, the generation just created in STEP1 has become the new (0)
  • (+1) now means the next not-yet-created generation
  • DISP=SHR on a not-yet-existing generation fails

8. Let’s prove that (0) also shifts under STEP

The previous two jobs show the effect on (+1). This next pair shows the effect on (0). First, create a new current generation:

//GDGMAKE  JOB ,'GDG MAKE',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP1    EXEC PGM=IEFBR14
//NEWGEN   DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA

Then compare these two readers.

Reader with GDGBIAS=JOB:

//READJOB  JOB ,'READ JOB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID,
//             GDGBIAS=JOB
//STEP1    EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   DSN=&SYSUID..GDGTEST.BASE(0),DISP=SHR
//SYSUT2   DD   SYSOUT=*
//SYSIN    DD   DUMMY

Reader with GDGBIAS=STEP in a multi-step flow:

//READSTEP JOB ,'READ STEP',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID,
//             GDGBIAS=STEP
//STEP1    EXEC PGM=IEFBR14
//NEWGEN   DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA
//STEP2    EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   DSN=&SYSUID..GDGTEST.BASE(0),DISP=SHR
//SYSUT2   DD   SYSOUT=*
//SYSIN    DD   DUMMY

What to observe:

  • With JOB, (0) in a later step still means the generation that was current before the job first resolved the base
  • With STEP, (0) in the later step means the generation just created by STEP1

That distinction matters whenever a job expects “current” to mean “current when the job started” rather than “current right now.”

9. Advanced edge case 1: the VOL=REF paradox

VOL=REF is one of the places where teams get surprised because the volume reference does not behave like a normal cached GDG DSN reference. The practical trap is this:

  • Under GDGBIAS=JOB, a later DSN=base(+1) can still refer to the same absolute generation created earlier in the job
  • But a VOL=REF reference can still be resolved from the step-time catalog view rather than the earlier job-level GDG mapping you expected

Use a pattern like this to reason about it:

//GDGVREF  JOB ,'VOL REF',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID,
//             GDGBIAS=JOB
//STEP1    EXEC PGM=IEFBR14
//OUT1     DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA
//STEP2    EXEC PGM=IEFBR14
//IN1      DD   DSN=&SYSUID..GDGTEST.BASE(+1),DISP=SHR
//VOLX     DD   DSN=&SYSUID..GDGTEST.WORK,
//              DISP=(NEW,CATLG,DELETE),
//              UNIT=SYSDA,
//              SPACE=(TRK,(1,1)),
//              VOL=REF=*.IN1

What makes this worth calling out is that people often assume:

  • IN1 is reopening the generation just created in STEP1
  • therefore any volume inheritance based on that logical intent should remain aligned

That assumption is unsafe when GDGs are involved.

The safer practical rule is:

  • If you need volume inheritance from a data set created earlier in the same job, prefer a concrete reference such as VOL=REF=*.stepname.ddname
  • Do not assume VOL=REF=MY.GDG(+1) will behave like the step-stable DSN reference you had in mind

10. Advanced edge case 2: cross-job concurrency contamination

The most architectural difference between JOB and STEP shows up when another workload updates the same GDG base while your job is still running.

Under GDGBIAS=JOB:

  • Your job effectively works from a frozen in-job mapping once the base is first resolved
  • Later external catalog updates do not change the meaning of your already-established relative references

Under GDGBIAS=STEP:

  • Every step boundary is a new catalog consultation point
  • If another job catalogs a new generation between your STEP1 and STEP2, your STEP2 can inherit that shifted baseline

That means STEP is not just “more current.” It is also more exposed to unrelated concurrent catalog activity.

Practical consequence:

  • If your flow assumes “the same (+1) I meant earlier is still the one I mean now,” JOB is usually safer
  • If your flow intentionally wants to follow the current catalog state at every step, STEP is the correct choice, but you must design around that moving baseline

11. Advanced edge case 3: utility-driven catalog desynchronization

If a step uses a utility such as IDCAMS to manipulate GDG entries directly, it can change the catalog in a way that is not equivalent to ordinary JCL allocation sequencing.

For example:

//FIXCAT   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DELETE &SYSUID..GDGTEST.BASE(0)
/*

Why this matters:

  • Under GDGBIAS=JOB, later JCL steps can continue to work from the earlier in-job mapping even though the catalog was changed underneath that mapping
  • Under GDGBIAS=STEP, the next step boundary forces a fresh lookup and naturally reflects the new catalog state

This is one of the few places where STEP can look self-healing while JOB can look stubborn. The same persistence that protects a job from outside interference can also preserve a mapping that no longer matches the live catalog after utility-driven changes.

12. Passed data sets: practical safe and unsafe patterns

When the created generation is passed rather than immediately reopened from the catalog, the behaviour is easier to reason about if you code the handoff explicitly.

Safer handoff pattern:

//PASSJOB  JOB ,'PASS GDG',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID,
//             GDGBIAS=STEP
//STEP1    EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   *
STEP1 WRITES THIS RECORD
/*
//SYSUT2   DD   DSN=&SYSUID..GDGTEST.BASE(+1),
//              DISP=(NEW,PASS,DELETE),
//              SPACE=(TRK,(1,1)),
//              DCB=(RECFM=FB,LRECL=80,BLKSIZE=0),
//              UNIT=SYSDA
//SYSIN    DD   DUMMY
//STEP2    EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   DSN=*.STEP1.SYSUT2,DISP=OLD
//SYSUT2   DD   SYSOUT=*
//SYSIN    DD   DUMMY

Why this is safer:

  • The receiving step uses the passed data set directly
  • It does not depend on recalculating GDG relative numbering after a step boundary

Less safe pattern under GDGBIAS=STEP:

//SYSUT1   DD   DSN=&SYSUID..GDGTEST.BASE(+1),DISP=SHR

If the generation was cataloged before the receiving step starts, that (+1) may no longer refer to the file you intended.

There is also a more subtle distinction between uncataloged and cataloged passes.

Uncataloged pass pattern:

  • If a step creates base(+1) with DISP=(NEW,PASS,DELETE), the catalog baseline does not move yet
  • The receiving step can safely use the passed DD reference because it is not asking z/OS to reinterpret the GDG through the catalog

Cataloged pass pattern:

  • If the created generation is cataloged before the receiving step starts, the next step under GDGBIAS=STEP sees a new current (0)
  • A receiving step that tries to reopen the data set through DSN=base(+1) may now point to the next uncreated generation instead of the one just passed

The practical rule is simple:

  • If you are passing a GDG generation between steps, prefer *.step.dd over re-deriving the target from a relative GDG reference

13. GDG ALL concatenations

Referencing the bare GDG base name without an explicit relative generation produces a GDG ALL allocation.

Example:

//READALL  EXEC PGM=IEBGENER
//SYSPRINT DD   SYSOUT=*
//SYSUT1   DD   DSN=&SYSUID..GDGTEST.BASE,DISP=SHR
//SYSUT2   DD   SYSOUT=*
//SYSIN    DD   DUMMY

That tells z/OS to build a concatenation of active generations for the base.

Why GDGBIAS matters here:

  • Under JOB, the logical list behind that concatenation is tied to the job's earlier GDG view
  • Under STEP, the concatenation is rebuilt from the current catalog view at the start of the step

So if an earlier step catalogs a new generation:

  • JOB tends to keep the earlier concatenation view stable
  • STEP tends to include the newer generation automatically in the later step's GDG ALL view

This matters in reporting or replay jobs where a bare base name is used as shorthand for “all current generations.”

14. Deferred step restarts

Restart behaviour is another place where the choice becomes architectural rather than stylistic.

Under GDGBIAS=JOB:

  • The restarted execution rebuilds its in-memory view from the catalog state that exists at restart time
  • If earlier steps in the original run already cataloged new generations, that restart-time baseline can differ from the baseline assumed by the original unrestarted flow

Under GDGBIAS=STEP:

  • Step entry already assumes a fresh recalculation model
  • Restart behaviour is therefore more naturally aligned with the design of the bias mode

This does not mean STEP is always better for restart. It means STEP is usually easier to reason about when restart semantics are expected to follow current catalog state without extra mental offset calculations.

15. How to choose

If we need to reduce the decision to one sentence:

  • Choose JOB when the job needs a stable internal snapshot
  • Choose STEP when the job should rebind itself to the live catalog at each step boundary

Use GDGBIAS=JOB when:

  • The job should operate against a stable in-job snapshot of GDG relative numbering
  • Later steps must keep referring to the same absolute generations chosen earlier in the flow
  • Concurrent external catalog updates should not change the meaning of your relative references mid-run

Use GDGBIAS=STEP when:

  • Each step should reflect the current catalog state
  • Utility-driven or restart-oriented processing benefits from step-boundary reevaluation
  • You are prepared for (0) and (+1) to shift after intermediate catalog activity

16. Coding and scope

GDGBIAS can be controlled at several levels:

  • JES or job class default (JOBCLASS(n) GDGBIAS=...)
  • Explicit override on the JOB statement
//DAILYJOB JOB (ACCT),'DATA PROCESSING',CLASS=A,GDGBIAS=STEP

The operator can modify the JES job class setting dynamically

$T JOBCLASS(A),GDGBIAS=STEP

If you omit it, the system or job-class default applies.

17. What to remember

The most important practical rule is simple:

  • GDGBIAS=JOB freezes relative GDG meaning inside the job
  • GDGBIAS=STEP recalculates relative GDG meaning at each step boundary

That is why GDGBIAS belongs in the architectural design of a batch flow, not as an afterthought on the job card.

18. Useful IBM documentation

If you want to validate the mechanics described in this article against IBM documentation, these are the most useful references:

More in this area

More in this area

Back to training
Article category

z/OS Articles

Browse all technical articles for z/OS in one category page.

Open category z/OS