z/OS has native scheduling controls inside JES2 that are often overlooked because many sites rely on enterprise schedulers like IBM Work Scheduler, BMC Control-M or Broadcom AutoSys Workload Automation. Those external schedulers are important, but it is still useful to know what JES2 can do by itself for individual jobs in the job stream.
This article is deliberately practical. It focuses on the SCHEDULE statement for individual jobs and shows how to:
- Hold a job until a future time with
HOLDUNTL - Create a simple dependency between jobs with
AFTER - Prevent false starts in a dynamic sequence with
DELAY=YES
1. Lab goals
By the end of this lab you should be able to:
- Explain what the JES2
SCHEDULEstatement does - Delay a job until a future time with
HOLDUNTL - Build a simple parent-dependent sequence with
AFTER - Understand why
DELAY=YESmatters in dynamic sequencing - Recognize the practical limits of native JES2 scheduling
2. Required environment
For this lab, use:
- z/OS 2.2 or later
- JES2
- TSO/ISPF access with permission to submit and monitor batch jobs
- SDSF access, or any equivalent tool that lets you observe submitted jobs
Important note:
- IBM documents the
SCHEDULEstatement as a JES2-only capability - The JES2
SCHEDULEstatement was introduced in z/OS 2.2.
3. What native JES2 scheduling can do
The SCHEDULE statement lets you specify scheduling attributes for a job.
For this article, the most useful keywords are:
| Keyword | Practical use |
|---|---|
HOLDUNTL | Keep the job from becoming eligible for execution until a future time |
AFTER | Make a job wait until another job has ended |
BEFORE | Express the reverse side of a dependency |
DELAY=YES | Tell JES2 that a missing parent or dependent should be treated as “not here yet”, not “already finished” |
The key point is that these controls affect when a job becomes eligible for execution. They do not replace a full enterprise workload scheduler, but they are useful for simple native sequencing.
4. Important limitations to understand first
Before the lab, keep these points in mind:
- The
SCHEDULEstatement is supported by JES2, not JES3 - It must appear after the
JOBstatement and before the firstEXECorIF - Only one
SCHEDULEstatement is allowed in a job - Dynamic sequencing with
BEFORE/AFTER/DELAY=YESis lighter and more limited than a full scheduler usage.
That last point matters. Native dynamic sequencing is useful but it is not the same thing as a full production scheduler with calendars, restart logic, and richer dependency management.
5. Lab 1: delay a job until a future time
This first job shows the simplest useful capability: do not let a submitted job execute immediately.
Create a member such as SCHHOLD1:
//SCHHOLD1 JOB ,'SCHEDULE LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE HOLDUNTL='+00:02'
//STEP1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
SET MAXCC=0
/*Submit the job.
What to observe:
- The job enters JES2 immediately
- You will be able to see it in the Input Queue. It does not become eligible for execution right away
- After roughly two minutes, it is released and completes normally
Why this matters:
- You can submit work in advance
- JES2 keeps the job from being selected until the requested time window
Practical note:
'+00:02'is a relative time interval- For longer real-world scheduling, IBM also documents absolute time and date forms for
HOLDUNTL
6. What HOLDUNTL is and is not
HOLDUNTL is useful when you want to delay eligibility for execution, but it is still very simple and limited compared with a full scheduler.
It is good for:
- Short deferrals
- Controlled job release
- Giving a related set of jobs time to enter the system before dependency logic is evaluated
It is not a replacement for:
- Enterprise calendars
- Holiday rules
- Complex workload forecasting
- Dependency chains spread across many applications and business dates
7. Lab 2: a simple parent-dependent sequence
Now we build a small two-job sequence:
JOBAcreates a test data setJOBBchecks that the data set existsJOBBmust not run beforeJOBAhas completed
Create a single input stream member such as SCHSEQ1 with both jobs:
//JOBA JOB ,'SCHEDULE LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE HOLDUNTL='+00:02'
//STEP1 EXEC PGM=IEFBR14
//PARENTDD DD DSN=&SYSUID..SCHEDLAB.PARENT,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(TRK,(1,1)),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//*
//JOBB JOB ,'SCHEDULE LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
// SCHEDULE AFTER=JOBA,DELAY=YES
//STEP1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
SET MAXCC=0
/*Submit the member once so both jobs enter JES2 close together.
What to observe:
JOBAandJOBBboth enter the systemJOBAis delayed byHOLDUNTLJOBBremains ineligible untilJOBAhas ended- after
JOBAcompletes,JOBBruns JOBAcompletes withCC 0000JOBBcompletes withCC 0000
8. Why DELAY=YES matters
This is one of the most important details in native JES2 sequencing.
IBM documents that AFTER= by itself can produce a false positive if the parent job does not currently exist. In that case, JES2 can interpret the parent as “already executed and purged”, which makes the dependent job eligible.
DELAY=YES changes that meaning:
- Without
DELAY=YES, a missing parent can be interpreted as already complete - With
DELAY=YES, a missing parent is treated as not yet submitted
That is why the previous lab uses:
SCHEDULE AFTER=JOBA,DELAY=YESThe combination is deliberate:
AFTER=JOBAexpresses the dependencyDELAY=YESprevents a false release
In this version, HOLDUNTL is applied only to JOBA. That keeps the parent job delayed, while still showing that JOBB waits because of AFTER=JOBA. If both jobs were held to the same time, the example would no longer isolate the effect of AFTER.
9. A useful mental model for native sequencing
Think of the native JES2 model like this:
| Need | Native JES2 answer |
|---|---|
| Delay a job until later | HOLDUNTL |
| Express “run after job X” | AFTER=X |
| Express “job X must finish before this job” | BEFORE=X |
| Avoid treating a not-yet-submitted job as already complete | DELAY=YES |
10. When this is a good fit
These capabilities are a good fit when:
- You need a small local dependency with no external scheduler involved
- You want to stage a small set of jobs for later release
- You need a practical JES2-only solution for a narrow batch flow
- You want to prototype sequencing logic before moving it into a broader scheduling framework
11. When you should use something stronger
Native JES2 scheduling is not the best answer when you need:
- Business calendars
- Long dependency chains across many applications
- Robust restart and recovery logic
- Workload balancing policies across large production streams
- Central audit and workload governance
Dynamic sequencing with BEFORE / AFTER / DELAY=YES is less robust and usually less efficient than JOBGROUP.
So the practical message is:
- Use native JES2 scheduling for small, local, tactical sequencing
- Use richer scheduler constructs when the workload is larger or business-critical
12. Cleanup
If you want to remove the data set created by JOBA, submit:
//SCHCLN1 JOB ,'SCHEDULE LAB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE '&SYSUID..SCHEDLAB.PARENT'
IF LASTCC = 8 THEN SET MAXCC = 0
/*Summary
The native JES2 scheduling capabilities are simple, but useful.
The two illustrated patterns were:
//JOB1 JOB ...
// SCHEDULE HOLDUNTL='+00:02'and:
//JOBB JOB ...
// SCHEDULE AFTER=JOBA,DELAY=YESThe first delays a job until a later time. The second creates a lightweight dependency and reduces the risk of false early execution.
Used carefully, these controls give you a practical native scheduling layer for individual jobs inside JES2 without involving an external scheduler.