IBM i and RPG standards
Criteria verified as of August 2026. Re-verify on the web before committing to anything (§8).
1. Scope and triggers
IBM i (AS/400) is the legacy platform that ages best and is worst understood from the outside. It
is not frozen: it has new releases, periodic Technology Refreshes, new hardware (Power11) and a
public roadmap (§2). Backward compatibility is real: an RPG program from the 90s compiles and runs
today. That is an engineering virtue, not a symptom of abandonment.
What is true —and has to be said here— is this:
- It is a single-vendor platform. Operating system, database, hardware and a good part of the
tooling come from IBM. There is no partial exit: you are either on it or you are not.
- The licensing model has moved to subscription (§2), which turns a previously amortised cost
into a recurring one. That is the relevant economic change of recent years, not the syntax of the
language.
- Writing new applications in RPG only makes sense inside an existing RPG base that is going to be
kept, and in that case it is written in fully free-form format (§3), without exception.
- The real debt in almost all of these shops is not the language: it is the style — monolithic
programs with native record-level access, no ILE, no version control and the logic tied to the
5250 screen.
Covers: releases and support; licence economics; RPG and the free-form rule; ILE (modules,
service programs, activation groups); Db2 for i and SQL versus native access; modern tooling and
real version control; integration (IWS, web services, IBM i Services); screen modernisation; and
profile and authority security.
Not applicable:
legacy-modernization-standards (umbrella skill for this block): theirs is the modernisation
strategy for this system —which "R" applies to it and with what seam— and the routing to the
skill of each inherited platform; here the technical criteria of what each "R" implies on IBM i.
migration-projects-standards: theirs is the execution of the cutover — rehearsal, window,
coexistence and reconciliation between IBM i and the target, rollback criteria and decommissioning.
enterprise-architecture-standards: theirs are the application inventory and the TIME model
at portfolio level —which systems get touched, in what order and with what budget—; the "R" for
this system is decided by legacy-modernization-standards within that frame, and here what
each option technically implies on IBM i. The three levels, in one sentence: the portfolio is
EA's, the system is legacy-modernization's, the platform is ours.
erp-sap-standards (frequent target when this system is replaced by a package, its
§3.8: the standard-versus-own-process decision, the deployment and the licence are theirs —and
they drive the date—; here where the rule comes from and where the data comes from, §3.4 and §3.5. The
warning both uphold: SAP bringing a standard process does not by itself uncover the rules
this system executes today, and those have to be extracted all the same).
tech-leadership-standards and project-management-standards (how it is funded and decided).
refactoring-tech-debt-standards (theirs are strangler fig, branch by abstraction and
characterization of untested code as a technique; here where the business logic lives on
this platform, what you locate it with and what shape the executable case takes, §3.4).
streaming-cdc-standards (CDC as a discipline is theirs: log versus triggers versus
polling, ordering and delivery semantics, event schema, initial snapshot and operation of the
stream. Here the mechanism of this platform —journals and receivers, what to turn on, what it
costs and what it breaks—, §3.5. Short rule: the journal is ours; reading it as a change stream is theirs.
Warning: their catalogue of mechanisms by engine does not include Db2 for i (§8)).
testing-qa-standards (test strategy), cicd-standards (the pipeline),
git-workflow-standards (branches, commits, releases).
sql-standards and data-platform-standards (the SQL language and generic data design;
here Db2 for i only in what it decides about the program), oracle-dba-standards and
sqlserver-dba-standards (other engines).
dotnet-standards, jvm-spring-standards, python-standards, go-standards (targets of a
rewrite: the quality of the target code is theirs).
grc-compliance-standards, privacy-engineering-standards,
identity-access-management-standards, bcdr-standards, backup-recovery-standards,
observability-standards, vulnerability-management-standards.
offensive-security-standards: this skill is defensive.
mainframe-zos-cobol-standards and mumps-standards: they are three distinct platforms that
people lump into the same "legacy" bag and that share almost nothing — IBM i is not a
mainframe, it does not charge by MSU, it does not use JCL and its database is part of the operating
system. Do not extrapolate criteria between them.
aix-solaris-hpux-standards (the most frequent confusion of all, because they share
hardware): AIX and IBM i run on Power and can coexist as partitions of the same
server, but they are different operating systems and share nothing of the application criteria.
AIX is Unix —smit, LVM, JFS2, mksysb, shell and binaries— and belongs to that skill; IBM i has objects,
libraries, ILE and Db2 integrated into the operating system, and belongs here. What they do share and
lives there: PowerVM, LPAR, VIOS and the HMC, the Power hardware lifecycle and the support
contract. Short rule: if the answer changes when you change partition, it belongs to the operating
system skill; if it is about the hypervisor or the iron, it belongs to the proprietary Unix one.
2. Default decisions
Verify the latest version on the web before pinning it in a real project (§8).
| Decision |
Criteria |
Verified note |
| Target release |
IBM i 7.6 for new hardware; 7.5 if there is Power9 in the estate |
7.6: announced 8 Apr 2025, GA 18 Apr 2025; requires Power10 or higher. 7.5 available since May 2022 |
| Release to abandon |
7.4 |
Withdrawn from marketing 30 Apr 2026; service level date change 30 Sep 2026; paid extension until 30 Sep 2029 (Enhanced policy: 5 years + 3 of extension). 7.4 GA: 21 Jun 2019 |
| Hardware ceiling |
The release is limited by the Power generation, not by the software |
Power8 → 7.4 is the last; Power9 → 7.5 is the last; Power10/11 → 7.5 and 7.6 |
| Cadence |
Apply Technology Refresh on its own calendar |
A TR brings new functions, not just fixes; staying on an old TR closes doors (IBM i Services, open source) |
| Licence |
By processor tier (P05/P10/P20/P30) and, in low tiers, by users |
P05/P10: processor + users (with unlimited option); P20 and above: by core only. Verified in IBM's software tiers document |
| Commercial model |
Subscription: perpetual is being withdrawn |
P05/P10 perpetuals withdrawn 7 May 2024; P20/P30 withdrawn effective 1 Jan 2026; on Power11 IBM i licences are subscription only |
| Language |
RPG in fully free-form format (**FREE) for everything new |
See §3 |
| Data access |
Embedded SQL (.sqlrpgle) by default |
See §3.2 |
| Program architecture |
ILE: modules + service programs + binding directory |
See §3.1 |
| IDE |
VS Code + Code for IBM i as the default option; RDi if already licensed |
Code for IBM i: repo codefori/vscode-ibmi, MIT licence (verified in the repo's package.json), published on the Marketplace by HalcyonTech. It is not an IBM product and has no IBM support |
| RDi |
Watch its calendar |
RDi 9.8 support discontinued 30 Apr 2026; 9.9 released 5 Dec 2025. RDi is an IBM product developed and supported by Fortra |
| Administration |
IBM i Services (SQL views and procedures in QSYS2/SYSTOOLS) |
See §3.3 |
| SCM |
Git, with the source in the IFS (not in source members) |
See §4 |
Declared discrepancy: IBM's terminology changed — what used to be called end of
standard support is now announced as date change for service level. Third-party sources publish
it as "end of support for 7.4 on 30 Sep 2026", but it is not end of life: there is a paid
extension until 2029. Do not quote "EOL 2026" without that nuance.
On the perpetual vs. subscription cost comparison: percentages circulate (of the order of
+20 %/+40 % over seven years) coming from trade-press analyses, not from published
tariffs. IBM does not publish prices in announcement letters: any figure you use has to
come from your own partner quote. See §8.
3. Structure and conventions
3.1 ILE is the line that separates maintainable from unmaintainable
- No new monolithic programs. Logic in modules (
CRTRPGMOD), grouped into
service programs (CRTSRVPGM) and linked by binding directory. The
entry program only orchestrates.
- Prototypes and interface
/COPY: the signature of each exported procedure lives in a shared
copy source; nobody calls a procedure with a hand-written signature.
- Activation groups: a deliberate and documented choice.
*NEW per call is a startup
cost; *CALLER propagates; a named group per application is the usual. *DFTACTGRP is
OPM compatibility: not in new code. The activation group determines the scope of the
commitment control and of the open files: getting this wrong produces transaction bugs,
not performance ones.
- Service program signature: manage the export file under version control.
Adding exports at the end is compatible; reordering them forces a recompile of all
clients. It is a binary contract.
3.2 SQL versus native record-level access
- Embedded SQL is the modern default, and not out of fashion: the optimiser (SQE) works on
sets, exploits indexes you do not have to open by hand, and the code says what it wants, not
how to traverse it. A
CHAIN/READE inside a loop is a hand-written join with no
statistics.
- What has to be replaced when leaving the native opcodes: explicit control of record locking
and the "read one row by key" (cursor or
SELECT INTO). Neither of the two justifies
writing the whole application in native access.
- Hard rule: new code with SQL; the old converts only when it has to be touched for another
reason and with a test that compares results. There is no mass conversion campaign that ends well.
- DDS in maintenance mode for data: new tables, views and indexes with SQL DDL, not
PF/LF. DDS is still what there is for screens (DSPF) and printouts (PRTF).
- Journaling and commitment control enabled on every business file: it is the prerequisite
for recovery and for replication, and it is discovered late.
- The
*LIBL is dynamic resolution and an inexhaustible source of incidents: the library
list of a production job is versioned configuration, not a session setting.
3.3 Administer with SQL, not with screens
IBM i Services (SQL views and procedures in QSYS2/SYSTOOLS) are the modern way to
administer: objects, PTFs, jobs, authorities, users and network are queried with SELECT, which
is automatable, comparable across environments and auditable — a WRKxxx leaves no evidence. Every
periodic check (excessive public authorities, inactive profiles, pending PTFs) is written
as a saved query in the repository, not as a manual procedure.
3.4 Where the business logic lives and how it is located
This is the work that decides whether an IBM i migration succeeds or not, and the one nobody does
before signing the project. legacy-modernization-standards turns it into a gate —no
characterization, no change— and refactoring-tech-debt-standards provides the generic technique
(characterization test, golden master). What is decided here is where to look on this
platform, what you search with and what limit each tool has.
The rule is not in "the RPG programs". It is spread across at least eight places:
- Fixed-format RPG and RPG III/OPM: beyond the code, the logic is in the program
cycle (what runs without anyone writing it), in the output specifications and in
the numeric indicators — an
*IN37 that decides a discount is a business rule, and
you do not find it by searching text. It is the most expensive to read and where most of the rule is.
- Free-form RPG and ILE: it is the readable part, and that is why it gets overweighted. If the system is already in
procedures and service programs (§3.1), extraction is cheaper, but it covers the part
of the system with the least risk.
- CL: it passes for "plumbing" and it is not always that. A
CL that decides which program to call according to the
content of a data area, or that sets the *LIBL of a process, carries rules
—calendar, company, environment— that appear in no RPG.
- The database: triggers (
ADDPFTRG, or CREATE TRIGGER in SQL) and constraints
(ADDPFCST: key, check, referential). A trigger is logic that runs without
any program calling it: if you migrate the data without migrating the trigger, the rule disappears in
silence.
- DDS: validity checking lives in the keywords of the DDS itself —
COMP/CMP,
RANGE, VALUES, CHECK, with CHKMSGID for the message— and is copied from the physical file to
the display file by field reference at the moment the DSPF is created. Verified in the
IBM DDS documentation. Double consequence: (a) there are domain rules declared outside every
program; (b) they only apply when going through the screen: ODBC, DFU, SQL or a web service
write without them. If the rule matters, it is not where people think it is.
- The 5250 screen itself: field order, fields protected depending on the case, the sequence
of screens that prevents reaching an invalid state. It is process design turned into access
control; it is lost entirely when the interface is replaced.
- Exit points: programs registered in the registration facility
(
WRKREGINF, and the SQL views QSYS2.EXIT_POINT_INFO and QSYS2.EXIT_PROGRAM_INFO, available
since 7.4 TR3 / 7.3 TR9 — verified in the IBM i Services documentation). They filter FTP, ODBC,
DDM or session startup, and often carry business rules ("this user cannot
download this table"). They do not show up by reading the application: you have to go looking for them.
- What lives outside the code: Query/400 definitions (
*QRYDFN objects, WRKQRY /
RUNQRY; the product is still shipped with the operating system after IBM's licensing
simplification, it is not withdrawn) and, above all, the end user's spreadsheets
hanging off the system over ODBC. That is where the real calculation of commissions, margins
or forecasting usually is — the system only stores the data. An inventory that does not include them underestimates the
scope completely.
The system's own tools, and what they do NOT see:
| Tool |
What it gives |
Limit that has to be declared |
DSPPGMREF |
Objects referenced by each program or SQL package: files (with their use: input/output/update), programs, data areas, *SRVPGM |
It is what there was at compile time, not what there is: names may not match if there was an override. When updating an ILE program (UPDPGM/UPDSRVPGM) entries are added but never removed, so there is stale information left over. It does not accept more than one library per invocation: you have to walk them. Output to file with format QWHDRPPR (QADSPPGM in QSYS) so it can be queried with SQL |
DSPDBR |
Logical and physical files dependent on a given one, and dependencies at member level |
It does not show all parent/child constraint relationships — a limit acknowledged by IBM support itself, which publishes DSPEDBR inside QMGTOOLS to cover it |
IBM i Services (QSYS2.PROGRAM_INFO, BOUND_MODULE_INFO, BOUND_SRVPGM_INFO, PROGRAM_EXPORT_IMPORT_INFO) |
The full ILE graph in SQL: which modules are in each program, which service programs are bound, what is exported and imported, with which source it was compiled |
Expensive to materialise at system level; IBM expressly recommends taking a snapshot into a table and querying over it. They only cover ILE with useful depth |
SQL catalogue (QSYS2.SYSTRIGGERS, SYSCST, SYSKEYCST, SYSINDEXES, SYSTABLES, SYSCOLUMNS) |
The logic declared in the database: existing triggers and constraints |
Only what is declared in the database; nothing of what the program does |
QSYS2.EXIT_POINT_INFO / EXIT_PROGRAM_INFO |
Exit points and registered programs |
See point 7 above |
The common blind spot, and it has to be said before promising coverage: everything above is
static analysis. It does not see calls resolved at runtime (CALL with the name in a
variable), nor dynamic SQL, nor which library actually resolved the *LIBL of that job. A
static analysis of IBM i is never complete, and the gap has exactly the shape of what you least
expect. It is complemented with execution evidence (trace, audit journal, real object
usage) to know what is used, and with the ecosystem's commercial analysis tools
if the budget allows — do not quote one by name without verifying that it is still alive and what it covers
(§8).
What is a business rule and what is plumbing. Without this filter, 200,000 lines get "extracted" and
nothing gets characterized. It is a rule if a business owner could want to change it without
touching technology: calculation (price, discount, commission, tax, interest), eligibility and
condition ("this customer cannot order on credit above X"), state transition (what happens
when an order is confirmed and what becomes forbidden afterwards), deadline and calendar, and data derivation
(how a field is filled from others). It is plumbing —and it is not extracted, it is discarded or
rewritten in the target with its own rules— screen navigation, format validation,
number and date formatting and editing, subfile and window handling, I/O error
handling, file overrides, *LIBL handling and opening and closing
of files. Hard rule: if describing it in one sentence brings up a company concept, it is a
rule; if only platform concepts appear, it is plumbing. The doubtful case —the validation
that is both format and domain— is resolved on the expensive side: it is treated as a rule.
The warning that holds up everything else: a rule that only exists in the code and that nobody in the
business recognises is still the rule the company runs on today. It is not discarded because it does not
appear in any document nor because the owner says "that is not how it is done": it has been deciding
for years, and the target that does not reproduce it will change results on day one. It is documented as
observed behaviour, taken to an explicit business decision —keep, change or
remove— and the change, if decided, is a functional change separate from the cutover, never a side
effect of the migration. The same with defects: a calculation that has been wrong since 1998 is
characterized as it is and corrected afterwards.
What is delivered (it is the artifact that legacy-modernization-standards requires as a gate, with the
shape it takes on this platform):
- Inventory of objects with owner and real usage: programs, files, triggers, constraints,
exit points,
*QRYDFN and external consumers over ODBC/DDM — generated with SQL over the
views above, versioned in Git and regenerable, not a one-off Excel.
- Rule catalogue: each rule with identifier, statement in business language, inputs and
outputs, exceptions, evidence (program, procedure and line; or trigger; or DDS
keyword) and business owner who has confirmed or rejected it.
- One executable characterization case per rule, with its data: on this platform, what
works is comparing the outputs of batch processes against reference files and the
direct call to ILE procedures (§3.1, §4). A rule without an executable case is not
characterized: it is noted.
- Explicit list of what is not covered: the dynamic, the interactive that can only be tested over 5250 and
what lives in spreadsheets. A declared gap is the deliverable; a silent gap is the
risk.
3.5 Db2 for i as a data source: journals, extraction and reconciliation
Explicit split of authority: streaming-cdc-standards owns CDC as a discipline
—why the log beats triggers and timestamp polling, ordering and delivery semantics,
event schema and contract, management of the backfill and the initial snapshot, and the operation of the
stream—. Ours is the concrete mechanism of this platform: what the journal is, what has to be
turned on, what it costs and what it breaks. And it has to be said because the confusion is expensive: the catalogue of
capture mechanisms by engine does not include Db2 for i (§8), so whoever arrives looking for "the
binlog of the AS/400" finds nothing. The equivalent exists and is first class: the journal.
What a journal and a journal receiver are. The journal (*JRN) is the logical object that
defines what is recorded; the journal receiver (*JRNRCV) is the object that physically
contains the change entries. Each change to a journalled file writes an entry with the
type of operation, the record image, and who, which program, which job and when. It is the same
mechanism that underpins commitment control, recovery and the high-availability replication
of the platform: that is why, in most of these shops, it is already turned on, and
discovering it changes the budget of the migration. When creating an SQL schema, Db2 for i creates journal and
receiver and automatically journals the tables created in it (QSQJRN); what is created with DDS, no —
there it has to be enabled by hand.
What has to be turned on and what it costs:
- The receiver is created (
CRTJRNRCV), the journal is created (CRTJRN) and journalling of each
physical file is started (STRJRNPF). Commands verified in the IBM documentation.
IMAGES(*BOTH) versus IMAGES(*AFTER) is the decision that most conditions the target:
*AFTER records only the after image; *BOTH also records the before one, and it is what allows
reconstructing an UPDATE as a change and not as a "new state". Commercial CDC tools
require *BOTH or *AFTER depending on the case. It costs twice the writing in the receiver: it is decided,
not inherited.
- Receiver management: with
MNGRCV(*SYSTEM) the system detaches the full receiver and attaches
a new one when the threshold is reached; DLTRCV decides whether it also deletes them. This is the number one
operational trap of a CDC over IBM i: if the system deletes receivers that the reader has not yet
processed, there is silent data loss. Receiver retention is a requirement
agreed with the systems team before connecting anything, and coordinated with the backup policy
(receivers live on disk and are among the fastest growing things).
- Cost: journalling writes to disk on every change and there is additional overhead from opening and
closing objects; the more journalled objects, the more impact. It is sized with the operations
team, it is not turned on massively on a Friday.
- Journal cache (
JRNCACHE, option **42 of the operating system, HA Journal Performance,
chargeable): improves performance by grouping entries in memory, but cached entries are
not visible to DSPJRN, RCVJRNE, RTVJRNE nor the QjoRetrieveJournalEntries API, nor are they
sent to the remote journal. Verified in the IBM documentation. Translation: if the CDC reader
"keeps losing the tail", it may not be a fault of the reader. And on a system crash, what is in
memory is lost.
- Remote journal: it is added with
ADDRMTJRN (not with CRTJRN) and allows reading the stream from another
machine, distinguishing between committed and uncommitted entries. It is the way not to put the
CDC reader on the production system.
Reading and extraction routes, with criteria:
| Route |
When |
Warning |
QSYS2.DISPLAY_JOURNAL (SQL table function, available since 7.1) |
Reading journal entries with SQL; it is what several commercial tools build on |
The input parameters have to be bounded or the cost explodes; interpreting the BLOB with the record image is not trivial and it is where everyone who builds it by hand gets stuck |
RCVJRNE / RTVJRNE / QjoRetrieveJournalEntries API |
The program route: RCVJRNE delivers entries continuously to an exit program, and it is what replication products use |
Exit program on the machine; subject to the journal cache (above) |
SQL over the catalogue and the tables (JDBC/ODBC, Run SQL Scripts) |
Initial load, profiling and reconciliation |
It is the correct route for the snapshot; the impact on the production system is negotiated and executed in a window |
CPYTOIMPF to a stream file in the IFS |
Delimited dump when there is no direct connectivity |
The CCSID is decided explicitly (STMFCCSID): the stream inherits by default the EBCDIC CCSID of the table. Verified in the IBM documentation |
| DDM / DRDA / web services (IWS, §6) |
Point integration and querying, not bulk load |
DDM and DRDA are also an access surface to control (§5) |
| Third-party tools |
When the CDC is continuous and the project pays for it |
Verify product, version and mechanism before quoting it (§8) |
On third-party tools, without marketing: the ones that lean on this platform read the
journal, by one of the two routes above. As of Aug 2026 it has been verified that Qlik Replicate and the
Fivetran/HVR connector capture via DISPLAY_JOURNAL, that Informatica PowerExchange captures
from the receivers, and that Matillion publishes a streaming connector for Db2 for i based on
journal entries. Debezium's official Db2 connector is for Db2 for Linux/UNIX/Windows and does not
cover Db2 for i; there is a third-party community connector that does read the journal — do not treat it
as equivalent in support. This list is a market signal, not a recommendation: it gets re-verified (§8).
The data traps that break the migration (this is what makes the project slip, not
the volume):
- Packed and signed (packed / zoned): numbers stored with the sign in the last
half byte. Decades of programs writing directly leave values with an invalid sign or digit
nibble that no sample
SELECT uncovers and that blow up when converting in bulk.
100 % of the numeric columns are profiled before moving anything, not a sample.
- Dates in numeric of 6, 7 or 8 digits:
YYMMDD, the 7-digit format with the century in front, or
YYYYMMDD. It brings 0, 999999, day 31 in months of 30, and century windows implicit in the
code ("less than 40 is 20xx") that have to be extracted as a rule (§3.4), not guessed. Each
sentinel combination is decided with the business: not all of them mean "null".
- Multi-member files: a physical file with several members —typically a history per
year or per company—. SQL has no equivalent and uses the first member by default, so an
extraction over SQL takes one chunk and looks correct. Verified in the IBM documentation: it
is accessed with
CREATE ALIAS over the specific member (or with a logical over all of them, or OVRDBF).
Checking for the existence of multiple members is a mandatory step of the inventory, and moreover
partitioning by member is an implicit business rule.
- Fixed length with padding:
CHAR values come padded with blanks; business keys that in the
target are compared with VARCHAR stop matching. A trimming policy is decided once and
applied the same way in load and in reconciliation.
- EBCDIC and CCSID: the data is born in EBCDIC.
CCSID 65535 (*HEX) means "do not convert" and is
the classic finding: the ODBC/JDBC client treats it as binary or fails. You have to distinguish the
column that is truly binary from the one that is text that was never tagged, and tag it; done
blind, accents, Ñ and currency symbols get corrupted. Redefining the CCSID does not rewrite the
bytes: it changes how they are interpreted — so an error here is invisible until someone reads
a proper name.
- Redefined and reused fields: a field whose meaning depends on the value of another, a
CHAR(30) that carries three subfields inside, a "status code" to which new meanings were added
without changing the structure, or fields declared and no longer used that are still
full of old data. No tool detects it: it comes out of profiling real values plus
the rule extraction of §3.4. A field with two meanings is split into two in the
target, and that is a business decision with an owner.
Reconciliation is not optional and is designed before extracting. Minimum: row counts and control
sums per business numeric column (amounts, not identifiers) per partition
—fiscal year/company/warehouse—, compared against the source at the same logical instant; count
of distinct values and of nulls/sentinels in the key columns; and for CDC, the lag between the
last applied journal entry and the source's. Reconciliation is executed in the rehearsal and in the
cutover, with the tolerance agreed in writing beforehand —the execution of the cutover and its
reconciliation belong to migration-projects-standards; the definition of what is reconciled on this
platform belongs here—. An extraction that does not reconcile is not fixed by hand in the target: the
process is fixed and it is executed again, because the manual fix is not repeatable and the cutover is
executed more than once.
4. Quality, version control and CI
- The source lives in Git, in the IFS (
.rpgle/.sqlrpgle/.clle/.sql), not in members of
QSYS.LIB: a member with a modification date is not history and does not allow branches, diff nor
review. It is the change with the highest return of the whole modernisation, and it comes before the others.
- Reproducible build: versioned script (Code for IBM i ecosystem utilities, or your own CL)
that rebuilds from scratch in a clean library. If nobody knows how to recompile everything, there is no
delivery: there is patching.
- Environments separated by library and
*LIBL, with their own masked test data.
- Tests: unit over ILE procedures (made possible by the design of §3.1) and regression by
comparison of batch outputs. A monolithic program that can only be tested over 5250 is, in
practice, not testable: that is the first thing that has to be broken.
- Minimum CI gate: compiles clean without ignoring warnings, the suite passes, and no object is
created by hand in production.
5. Stack security
QSECURITY 40 as a minimum; 50 in regulated environments. Below 40 the integrity of the
system is not guaranteed; raising it is a project, but staying at 30 is not defensible.
*ALLOBJ is the problem. Every profile with *ALLOBJ/*SECOFR is a total administrator of the system
and of the data. Inventory who has it —including via group profile—, justify it one
by one and remove the rest: this is where application profiles and service users with total
authority show up.
- Public authority:
*EXCLUDE on data objects and granting by authorization list.
*PUBLIC *CHANGE on business libraries is the guaranteed audit finding.
- Adopted authority (
USRPRF(*OWNER)) grants access only while the program runs, and it is a risk
if the program allows reaching a command line. Adopt from the smallest object possible,
control propagation (USEADPAUT), and no program that adopts authority offers command
entry.
- The back door is not the 5250: it is the open interfaces (FTP, ODBC/JDBC, DRDA, DDM,
REST). A user limited by menu can read all the tables over ODBC if there are no exit
programs nor object-level authority. Security goes on the object, not on the menu.
- Native MFA: 7.6 incorporates TOTP into the operating system, applicable to all authentication
points (5250, FTP) and to SST/DST profiles, at no additional cost — reason enough, by
itself, to plan the jump. 7.6 also adds encryption of the system ASP (SYSBAS): verify
the operational impact before enabling it.
QAUDJRN enabled and exported to the SIEM: if the audit journal does not leave the machine, it is
a blind spot.
6. Integration and interface modernisation
- Web services: IWS exposes a program or procedure as REST/SOAP without leaving the
platform; for consumption, native HTTP client or SQL functions. With volume or complex integration,
the alternative is an external service that speaks Db2 for i over SQL.
- The usual trap: wrapping the 5250 screen in web without redesigning the flow. Out comes the same
sequence of screens with CSS, with its step-by-step navigation, its field-by-field validation and its
conversational session: you gain looks, not usability nor decoupling. Prerequisite to
any new interface: that the logic be in ILE procedures callable without a screen
(§3.1). While it lives in the DSPF's program, the web layer is make-up.
- API before screen: the unit of reuse is the procedure, not the interactive
program.
7. When to stay, when to migrate and prohibitions
Staying is correct —and it is more often than people think— when:
- The application covers the business, the total cost (licence + support + staff) is known and
competitive, and there is Power hardware in support with a path to 7.5/7.6.
- The operation is what the platform does exceptionally well: reliable batch, integrated
database, very little administration per transaction, high availability with a small team.
- It can be modernised inside: ILE, SQL, Git, CI, APIs. That route is dramatically cheaper
than rewriting and almost nobody exhausts it before raising migration.
Migrating makes sense when the single vendor is a risk accepted by management, when the
subscription cost stops being competitive against the value, when the functionality is bought ready
made (ERP), or when there is no staff and there will not be — measured in your shop, not in an article.
Prohibitions:
- ❌ FORBIDDEN to write new code in fixed-format RPG (columns), in RPG III/OPM or with
numeric indicators as logic. Everything new:
**FREE, procedures, named
variables.
- ❌ New monolithic programs without ILE, or
DFTACTGRP(*YES) in new code.
- ❌ Native record-level access for new set logic (
CHAIN/READE loops that are a
join).
- ❌ Defining new tables with DDS instead of SQL DDL.
- ❌
QSYS.LIB source members as version control. The source goes to Git, in the IFS.
- ❌ Compiling or creating objects by hand in production.
- ❌
QSECURITY below 40; *ALLOBJ handed around; *PUBLIC *CHANGE on data libraries.
- ❌ Programs that adopt authority and allow a command line.
- ❌ Entrusting security to the 5250 menu while leaving ODBC/FTP/DDM uncontrolled.
- ❌ Presenting as modernisation a web wrapper of the same 5250 screens (§6).
- ❌ Promising that the business logic has been extracted from static analysis (
DSPPGMREF,
IBM i Services views) without declaring the blind spot: dynamic calls, dynamic SQL and
resolution by *LIBL are not seen there (§3.4).
- ❌ Discarding a rule because nobody in the business recognises it, or fixing it inside the same change
that migrates it. It is characterized as it is and the functional change goes separately (§3.4).
- ❌ Considering the logic inventoried without having looked at triggers, constraints, validity
keywords in DDS, exit point programs,
*QRYDFN and the spreadsheets over ODBC (§3.4).
- ❌ Extracting over SQL from a multi-member file without checking the members: SQL uses the first and
the result looks correct (§3.5).
- ❌ Converting numeric columns or numeric dates over a sample: profiling is of
100 % of the rows (§3.5).
- ❌ Moving data ignoring the CCSID, or "fixing" a
CCSID 65535 by changing the tag without deciding
first whether the column is binary or untagged text (§3.5).
- ❌ Setting up a CDC over journals without agreeing receiver retention beforehand with the systems
team: if they are deleted before being processed, the loss is silent (§3.5).
- ❌ Diagnosing a CDC reader "that loses the tail" without ruling out the journal cache: its
entries are not visible nor sent to the remote journal (§3.5).
- ❌ Executing a cutover without a defined reconciliation and a tolerance agreed in writing, or repairing by hand in the
target what did not reconcile (§3.5).
- ❌ Planning a release upgrade without first checking the ceiling imposed by the Power generation.
- ❌ Quoting perpetual-vs-subscription cost figures or IDE market share without naming the
source and its method (§8).
8. Mandatory web verification
Before pinning anything in a real project, check on the web:
- Current IBM i release and its calendar: as of Aug 2026, 7.6, 7.5 and 7.4 are supported (the last
one with a service level change on 30 Sep 2026 and extension until 30 Sep 2029). Declared
gap: IBM had not announced end-of-support dates for 7.5 or 7.6. Do not infer them
as if they were an announcement; consult IBM's official release support page (PID
5770-SS1).
- Release ↔ Power generation matrix and minimum firmware level before committing to an
upgrade.
- Current licensing model: which tiers still have perpetual, conditions of the
subscription and of the 5250 Enterprise Enablement. Prices are not documented here: IBM does not
publish them in announcement letters and they are only reliable via a partner quote.
- Status and licence of Code for IBM i: as of Aug 2026,
codefori/vscode-ibmi, MIT licence
verified in the repository; community project, without IBM support. Verify also whether
it is still the active repository before basing a decision on it — the GitHub releases
feed is not the source of truth if the project moves.
- RDi status: 9.8 with support discontinuation on 30 Apr 2026; 9.9 released
5 Dec 2025. Verify the 9.9 calendar and who supports it (IBM contracts Fortra).
- Technology Refresh level current for your release and which IBM i Services it adds: the list of
SQL views grows with each TR and determines what you can automate.
- IBM i security bulletins, cumulative security PTFs and CVEs of the ported open
source components (which arrive on their own calendar).
- Tool adoption figures (market surveys of the Fortra type): they are self-reported
surveys with an unpublished sample; use them as a trend signal, never as hard data.
- Every command or SQL view name in this skill, against
ibm.com/docs for the client's
release, before typing it. Verified as of Aug 2026 in IBM documentation: DSPPGMREF
(output format QWHDRPPR over QADSPPGM, a single library per invocation, entries that
are added but not removed when updating an ILE program), DSPDBR (and the limit with the
parent/child constraints, which IBM covers with DSPEDBR from QMGTOOLS), WRKREGINF,
QSYS2.EXIT_POINT_INFO and EXIT_PROGRAM_INFO (7.4 TR3 / 7.3 TR9), QSYS2.PROGRAM_INFO,
BOUND_MODULE_INFO, BOUND_SRVPGM_INFO,
…(truncated)
1---2name: ibm-i-rpg-standards3description: IBM i (AS/400, iSeries, System i) application engineering on Power. Use when working with RPG sources (.rpgle, .sqlrpgle, RPG III/RPGLE, **FREE fully free-form, /COPY and /INCLUDE prototypes), CL programs (.clle, CRTBNDCL, CL commands like WRKACTJOB, WRKSPLF, DSPFFD), DDS physical and logical files and display files (.pf, .lf, .dspf, .prtf), ILE modules, service programs, binding directories and activation groups (CRTRPGMOD, CRTSRVPGM, CRTPGM, ACTGRP), IFS and QSYS.LIB objects, library lists and *LIBL, Db2 for i with embedded SQL, SQL stored procedures, Run SQL Scripts, ACS, and IBM i Services SQL views (QSYS2, SYSTOOLS), record-level access opcodes (CHAIN, SETLL, READE, WRITE, UPDATE), journaling and commitment control, extracting business rules from RPG/CL/DDS for a characterization or modernization gate (DSPPGMREF, DSPDBR, QSYS2.PROGRAM_INFO, BOUND_MODULE_INFO, exit points via WRKREGINF or QSYS2.EXIT_POINT_INFO, Query/400 *QRYDFN, DDS validity-checking keywords, ADDPFTRG/ADDPFCST triggers and constraints),4---56# IBM i and RPG standards78Criteria verified as of **August 2026**. Re-verify on the web before committing to anything (§8).910## 1. Scope and triggers1112**IBM i (AS/400) is the legacy platform that ages best and is worst understood from the outside.** It13is not frozen: it has new releases, periodic *Technology Refreshes*, new hardware (Power11) and a14public roadmap (§2). Backward compatibility is real: an RPG program from the 90s compiles and runs15today. That is an engineering virtue, not a symptom of abandonment.1617What is true —and has to be said here— is this:18- **It is a single-vendor platform.** Operating system, database, hardware and a good part of the19 tooling come from IBM. There is no partial exit: you are either on it or you are not.20- **The licensing model has moved to subscription** (§2), which turns a previously amortised cost21 into a recurring one. That is the relevant economic change of recent years, not the syntax of the22 language.23- **Writing new applications in RPG only makes sense inside an existing RPG base that is going to be24 kept**, and in that case it is written in **fully free-form format** (§3), without exception.25- **The real debt in almost all of these shops is not the language: it is the style** — monolithic26 programs with native record-level access, no ILE, no version control and the logic tied to the27 5250 screen.2829Covers: releases and support; licence economics; RPG and the free-form rule; **ILE** (modules,30service programs, activation groups); **Db2 for i** and SQL versus native access; modern tooling and31real version control; integration (IWS, web services, **IBM i Services**); screen modernisation; and32profile and authority security.3334**Not applicable**:35- `legacy-modernization-standards` (**umbrella skill for this block**): theirs is the modernisation36 strategy **for this system** —which "R" applies to it and with what seam— and the routing to the37 skill of each inherited platform; **here the technical criteria of what each "R" implies on IBM i**.38- `migration-projects-standards`: theirs is the **execution of the cutover** — rehearsal, window,39 coexistence and reconciliation between IBM i and the target, rollback criteria and decommissioning.40- `enterprise-architecture-standards`: theirs are the application inventory and the **TIME** model41 **at portfolio level** —which systems get touched, in what order and with what budget—; the "R" for42 **this** system is decided by `legacy-modernization-standards` within that frame, and **here what43 each option technically implies on IBM i**. The three levels, in one sentence: *the portfolio is44 EA's, the system is `legacy-modernization`'s, the platform is ours.*45- `erp-sap-standards` (**frequent target when this system is replaced by a package**, its46 §3.8: the standard-versus-own-process decision, the deployment and the licence are theirs —and47 they drive the date—; **here where the rule comes from and where the data comes from**, §3.4 and §3.5. The48 warning both uphold: **SAP bringing a standard process does not by itself uncover the rules49 this system executes today**, and those have to be extracted all the same).50- `tech-leadership-standards` and `project-management-standards` (how it is funded and decided).51- `refactoring-tech-debt-standards` (**theirs** are *strangler fig*, branch by abstraction and52 characterization of untested code **as a technique**; **here where the business logic lives on53 this platform, what you locate it with and what shape the executable case takes**, §3.4).54- `streaming-cdc-standards` (**CDC as a discipline is theirs**: log versus triggers versus55 polling, ordering and delivery semantics, event schema, initial *snapshot* and operation of the56 stream. **Here the mechanism of this platform** —journals and receivers, what to turn on, what it57 costs and what it breaks—, §3.5. Short rule: **the journal is ours; reading it as a change stream is theirs.**58 Warning: **their catalogue of mechanisms by engine does not include Db2 for i** (§8)).59- `testing-qa-standards` (test strategy), `cicd-standards` (the pipeline),60 `git-workflow-standards` (branches, commits, releases).61- `sql-standards` and `data-platform-standards` (the SQL language and generic data design;62 **here Db2 for i only in what it decides about the program**), `oracle-dba-standards` and63 `sqlserver-dba-standards` (other engines).64- `dotnet-standards`, `jvm-spring-standards`, `python-standards`, `go-standards` (targets of a65 rewrite: **the quality of the target code is theirs**).66- `grc-compliance-standards`, `privacy-engineering-standards`,67 `identity-access-management-standards`, `bcdr-standards`, `backup-recovery-standards`,68 `observability-standards`, `vulnerability-management-standards`.69- `offensive-security-standards`: **this skill is defensive**.70- `mainframe-zos-cobol-standards` and `mumps-standards`: **they are three distinct platforms that71 people lump into the same "legacy" bag and that share almost nothing** — IBM i is not a72 mainframe, it does not charge by MSU, it does not use JCL and its database is part of the operating73 system. Do not extrapolate criteria between them.74- `aix-solaris-hpux-standards` (**the most frequent confusion of all, because they share75 hardware**): **AIX and IBM i run on Power and can coexist as partitions of the same76 server, but they are different operating systems and share nothing of the application criteria.**77 AIX is Unix —`smit`, LVM, JFS2, `mksysb`, shell and binaries— and belongs to that skill; IBM i has objects,78 libraries, ILE and Db2 integrated into the operating system, and belongs here. **What they do share and79 lives there**: PowerVM, LPAR, VIOS and the HMC, the Power hardware lifecycle and the support80 contract. Short rule: **if the answer changes when you change partition, it belongs to the operating81 system skill; if it is about the hypervisor or the iron, it belongs to the proprietary Unix one.**8283## 2. Default decisions8485> Verify the latest version on the web before pinning it in a real project (§8).8687| Decision | Criteria | Verified note |88|---|---|---|89| Target release | **IBM i 7.6** for new hardware; **7.5** if there is Power9 in the estate | 7.6: announced 8 Apr 2025, **GA 18 Apr 2025**; requires **Power10 or higher**. 7.5 available since May 2022 |90| Release to abandon | **7.4** | Withdrawn from marketing 30 Apr 2026; **service level date change 30 Sep 2026**; paid extension until 30 Sep 2029 (*Enhanced* policy: 5 years + 3 of extension). 7.4 GA: 21 Jun 2019 |91| Hardware ceiling | The release is limited by the Power generation, not by the software | Power8 → 7.4 is the last; Power9 → 7.5 is the last; Power10/11 → 7.5 and 7.6 |92| Cadence | Apply **Technology Refresh** on its own calendar | A TR brings new functions, not just fixes; staying on an old TR closes doors (IBM i Services, open source) |93| Licence | **By processor *tier* (P05/P10/P20/P30) and, in low tiers, by users** | P05/P10: processor + users (with unlimited option); **P20 and above: by core only**. Verified in IBM's *software tiers* document |94| Commercial model | **Subscription**: perpetual is being withdrawn | P05/P10 perpetuals withdrawn 7 May 2024; **P20/P30 withdrawn effective 1 Jan 2026**; on Power11 IBM i licences are **subscription only** |95| Language | **RPG in fully free-form format (`**FREE`)** for everything new | See §3 |96| Data access | **Embedded SQL (`.sqlrpgle`) by default** | See §3.2 |97| Program architecture | **ILE**: modules + service programs + binding directory | See §3.1 |98| IDE | **VS Code + Code for IBM i** as the default option; **RDi** if already licensed | Code for IBM i: repo `codefori/vscode-ibmi`, **MIT licence** (verified in the repo's `package.json`), published on the Marketplace by HalcyonTech. **It is not an IBM product and has no IBM support** |99| RDi | Watch its calendar | RDi **9.8 support discontinued 30 Apr 2026**; **9.9** released 5 Dec 2025. RDi is an IBM product developed and supported by Fortra |100| Administration | **IBM i Services** (SQL views and procedures in `QSYS2`/`SYSTOOLS`) | See §3.3 |101| SCM | **Git**, with the source in the **IFS** (not in source members) | See §4 |102103**Declared discrepancy**: IBM's terminology changed — what used to be called *end of104standard support* is now announced as *date change for service level*. Third-party sources publish105it as "end of support for 7.4 on 30 Sep 2026", but **it is not end of life**: there is a paid106extension until 2029. Do not quote "EOL 2026" without that nuance.107108**On the perpetual vs. subscription cost comparison**: percentages circulate (of the order of109+20 %/+40 % over seven years) coming from trade-press analyses, not from published110tariffs. **IBM does not publish prices in announcement letters**: any figure you use has to111come from your own partner quote. See §8.112113## 3. Structure and conventions114115### 3.1 ILE is the line that separates maintainable from unmaintainable116117- **No new monolithic programs.** Logic in **modules** (`CRTRPGMOD`), grouped into118 **service programs** (`CRTSRVPGM`) and linked by **binding directory**. The119 entry program only orchestrates.120- **Prototypes and interface `/COPY`**: the signature of each exported procedure lives in a shared121 copy source; nobody calls a procedure with a hand-written signature.122- **Activation groups**: a deliberate and documented choice. `*NEW` per call is a startup123 cost; `*CALLER` propagates; a named group per application is the usual. **`*DFTACTGRP` is124 OPM compatibility: not in new code.** The activation group determines the scope of the125 commitment control and of the open files: getting this wrong produces transaction bugs,126 not performance ones.127- **Service program signature**: manage the export file under version control.128 Adding exports at the end is compatible; reordering them forces a recompile of all129 clients. It is a binary contract.130131### 3.2 SQL versus native record-level access132133- **Embedded SQL is the modern default**, and not out of fashion: the optimiser (SQE) works on134 sets, exploits indexes you do not have to open by hand, and **the code says what it wants, not135 how to traverse it**. A `CHAIN`/`READE` inside a loop is a hand-written *join* with no136 statistics.137- What has to be replaced when leaving the native *opcodes*: explicit control of record locking138 and the "read one row by key" (cursor or `SELECT INTO`). Neither of the two justifies139 writing the whole application in native access.140- **Hard rule**: new code with SQL; the old converts **only** when it has to be touched for another141 reason and with a test that compares results. **There is no mass conversion campaign that ends well.**142- **DDS in maintenance mode for data**: new tables, views and indexes **with SQL DDL**, not143 PF/LF. DDS is still what there is for screens (DSPF) and printouts (PRTF).144- **Journaling and commitment control enabled** on every business file: it is the prerequisite145 for recovery and for replication, and it is discovered late.146- The **`*LIBL`** is dynamic resolution and an inexhaustible source of incidents: **the library147 list of a production job is versioned configuration**, not a session setting.148149### 3.3 Administer with SQL, not with screens150151**IBM i Services** (SQL views and procedures in `QSYS2`/`SYSTOOLS`) are **the modern way to152administer**: objects, PTFs, jobs, authorities, users and network are queried with `SELECT`, which153is automatable, comparable across environments and auditable — a `WRKxxx` leaves no evidence. Every154periodic check (excessive public authorities, inactive profiles, pending PTFs) is written155as a saved query in the repository, not as a manual procedure.156157### 3.4 Where the business logic lives and how it is located158159**This is the work that decides whether an IBM i migration succeeds or not**, and the one nobody does160before signing the project. `legacy-modernization-standards` turns it into a gate —*no161characterization, no change*— and `refactoring-tech-debt-standards` provides the generic technique162(*characterization test*, *golden master*). **What is decided here is where to look on this163platform, what you search with and what limit each tool has.**164165**The rule is not in "the RPG programs". It is spread across at least eight places:**1661671. **Fixed-format RPG and RPG III/OPM**: beyond the code, the logic is in the **program168 cycle** (what runs without anyone writing it), in the **output specifications** and in169 the **numeric indicators** — an `*IN37` that decides a discount **is** a business rule, and170 you do not find it by searching text. It is the most expensive to read and where most of the rule is.1712. **Free-form RPG and ILE**: it is the readable part, and that is why it gets overweighted. If the system is already in172 procedures and service programs (§3.1), extraction is cheaper, but **it covers the part173 of the system with the least risk**.1743. **CL**: it passes for "plumbing" and it is not always that. A `CL` that decides which program to call according to the175 content of a data area, or that sets the `*LIBL` of a process, carries rules176 —calendar, company, environment— that appear in no RPG.1774. **The database**: *triggers* (`ADDPFTRG`, or `CREATE TRIGGER` in SQL) and **constraints**178 (`ADDPFCST`: key, check, referential). A trigger is logic that runs **without179 any program calling it**: if you migrate the data without migrating the trigger, the rule disappears in180 silence.1815. **DDS**: validity checking lives in the keywords of the DDS itself —`COMP`/`CMP`,182 `RANGE`, `VALUES`, `CHECK`, with `CHKMSGID` for the message— and **is copied from the physical file to183 the display file by field reference at the moment the DSPF is created**. Verified in the184 IBM DDS documentation. Double consequence: (a) there are domain rules declared outside every185 program; (b) **they only apply when going through the screen**: ODBC, DFU, SQL or a web service186 write without them. If the rule matters, it is not where people think it is.1876. **The 5250 screen itself**: field order, fields protected depending on the case, the sequence188 of screens that prevents reaching an invalid state. It is process design turned into access189 control; it is lost entirely when the interface is replaced.1907. **Exit points**: programs registered in the **registration facility**191 (`WRKREGINF`, and the SQL views `QSYS2.EXIT_POINT_INFO` and `QSYS2.EXIT_PROGRAM_INFO`, available192 since 7.4 TR3 / 7.3 TR9 — verified in the IBM i Services documentation). They filter FTP, ODBC,193 DDM or session startup, and often carry business rules ("this user cannot194 download this table"). **They do not show up by reading the application**: you have to go looking for them.1958. **What lives outside the code**: **Query/400** definitions (`*QRYDFN` objects, `WRKQRY` /196 `RUNQRY`; the product is still shipped with the operating system after IBM's licensing197 simplification, it is not withdrawn) and, above all, **the end user's spreadsheets**198 hanging off the system over ODBC. That is where the real calculation of commissions, margins199 or forecasting usually is — the system only stores the data. **An inventory that does not include them underestimates the200 scope completely.**201202**The system's own tools, and what they do NOT see:**203204| Tool | What it gives | Limit that has to be declared |205|---|---|---|206| `DSPPGMREF` | Objects referenced by each program or SQL package: files (with their use: input/output/update), programs, data areas, `*SRVPGM` | **It is what there was at compile time**, not what there is: names may not match if there was an *override*. When updating an ILE program (`UPDPGM`/`UPDSRVPGM`) **entries are added but never removed**, so there is stale information left over. **It does not accept more than one library per invocation**: you have to walk them. Output to file with format `QWHDRPPR` (`QADSPPGM` in `QSYS`) so it can be queried with SQL |207| `DSPDBR` | Logical and physical files dependent on a given one, and dependencies at member level | **It does not show all parent/child constraint relationships** — a limit acknowledged by IBM support itself, which publishes `DSPEDBR` inside `QMGTOOLS` to cover it |208| IBM i Services (`QSYS2.PROGRAM_INFO`, `BOUND_MODULE_INFO`, `BOUND_SRVPGM_INFO`, `PROGRAM_EXPORT_IMPORT_INFO`) | The full ILE graph **in SQL**: which modules are in each program, which service programs are bound, what is exported and imported, with which source it was compiled | Expensive to materialise at system level; **IBM expressly recommends taking a snapshot into a table** and querying over it. They only cover ILE with useful depth |209| SQL catalogue (`QSYS2.SYSTRIGGERS`, `SYSCST`, `SYSKEYCST`, `SYSINDEXES`, `SYSTABLES`, `SYSCOLUMNS`) | The logic declared **in the database**: existing triggers and constraints | Only what is declared in the database; nothing of what the program does |210| `QSYS2.EXIT_POINT_INFO` / `EXIT_PROGRAM_INFO` | Exit points and registered programs | See point 7 above |211212**The common blind spot, and it has to be said before promising coverage**: everything above is213**static analysis**. It does not see calls resolved at runtime (`CALL` with the name in a214variable), nor dynamic SQL, nor which library actually resolved the `*LIBL` of that job. **A215static analysis of IBM i is never complete**, and the gap has exactly the shape of what you least216expect. It is complemented with execution evidence (trace, audit journal, real object217usage) to know **what is used**, and with the ecosystem's commercial analysis tools218if the budget allows — **do not quote one by name without verifying that it is still alive and what it covers**219(§8).220221**What is a business rule and what is plumbing.** Without this filter, 200,000 lines get "extracted" and222nothing gets characterized. **It is a rule** if a business owner could want to change it without223touching technology: calculation (price, discount, commission, tax, interest), eligibility and224condition ("this customer cannot order on credit above X"), state transition (what happens225when an order is confirmed and what becomes forbidden afterwards), deadline and calendar, and **data derivation**226(how a field is filled from others). **It is plumbing** —and it is not extracted, it is discarded or227rewritten in the target with its own rules— screen navigation, format validation,228number and date formatting and editing, subfile and window handling, I/O error229handling, file *overrides*, `*LIBL` handling and opening and closing230of files. **Hard rule: if describing it in one sentence brings up a company concept, it is a231rule; if only platform concepts appear, it is plumbing.** The doubtful case —the validation232that is both format and domain— is resolved on the expensive side: it is treated as a rule.233234**The warning that holds up everything else**: **a rule that only exists in the code and that nobody in the235business recognises is still the rule the company runs on today.** It is not discarded because it does not236appear in any document nor because the owner says "that is not how it is done": it has been deciding237for years, and the target that does not reproduce it will change results on day one. It is documented as238**observed behaviour**, taken to an explicit business decision —keep, change or239remove— and **the change, if decided, is a functional change separate from the cutover**, never a side240effect of the migration. The same with defects: a calculation that has been wrong since 1998 is241characterized **as it is** and corrected afterwards.242243**What is delivered** (it is the artifact that `legacy-modernization-standards` requires as a gate, with the244shape it takes on this platform):245- **Inventory of objects with owner and real usage**: programs, files, triggers, constraints,246 exit points, `*QRYDFN` and external consumers over ODBC/DDM — generated with SQL over the247 views above, **versioned in Git and regenerable**, not a one-off Excel.248- **Rule catalogue**: each rule with identifier, statement in business language, inputs and249 outputs, exceptions, **evidence** (program, procedure and line; or trigger; or DDS250 keyword) and business owner who has confirmed or rejected it.251- **One executable characterization case per rule**, with its data: on this platform, what252 works is comparing the outputs of **batch processes** against reference files and the253 direct call to ILE procedures (§3.1, §4). A rule without an executable case **is not254 characterized**: it is noted.255- **Explicit list of what is not covered**: the dynamic, the interactive that can only be tested over 5250 and256 what lives in spreadsheets. **A declared gap is the deliverable; a silent gap is the257 risk.**258259### 3.5 Db2 for i as a data source: journals, extraction and reconciliation260261**Explicit split of authority**: `streaming-cdc-standards` owns **CDC as a discipline**262—why the log beats triggers and timestamp polling, ordering and delivery semantics,263event schema and contract, management of the *backfill* and the initial *snapshot*, and the operation of the264stream—. **Ours is the concrete mechanism of this platform**: what the journal is, what has to be265turned on, what it costs and what it breaks. And it has to be said because the confusion is expensive: **the catalogue of266capture mechanisms by engine does not include Db2 for i** (§8), so whoever arrives looking for "the267binlog of the AS/400" finds nothing. The equivalent exists and **is first class**: the *journal*.268269**What a *journal* and a *journal receiver* are.** The **journal** (`*JRN`) is the logical object that270defines what is recorded; the **journal receiver** (`*JRNRCV`) is the object that **physically271contains the change entries**. Each change to a journalled file writes an entry with the272type of operation, the record image, and who, which program, which job and when. It is the same273mechanism that underpins commitment control, recovery and the high-availability replication274of the platform: **that is why, in most of these shops, it is already turned on**, and275discovering it changes the budget of the migration. When creating an SQL schema, Db2 for i creates journal and276receiver and **automatically journals** the tables created in it (`QSQJRN`); what is created with DDS, no —277there it has to be enabled by hand.278279**What has to be turned on and what it costs:**280- The receiver is created (`CRTJRNRCV`), the journal is created (`CRTJRN`) and journalling of each281 physical file is started (`STRJRNPF`). Commands verified in the IBM documentation.282- **`IMAGES(*BOTH)` versus `IMAGES(*AFTER)`** is the decision that most conditions the target:283 `*AFTER` records only the after image; `*BOTH` also records the before one, and **it is what allows284 reconstructing an `UPDATE` as a change and not as a "new state"**. Commercial CDC tools285 require `*BOTH` or `*AFTER` depending on the case. It costs twice the writing in the receiver: it is decided,286 not inherited.287- **Receiver management**: with `MNGRCV(*SYSTEM)` the system detaches the full receiver and attaches288 a new one when the threshold is reached; `DLTRCV` decides whether it also deletes them. **This is the number one289 operational trap of a CDC over IBM i**: if the system deletes receivers that the reader has not yet290 processed, **there is silent data loss**. Receiver retention is a requirement291 agreed with the systems team before connecting anything, and coordinated with the backup policy292 (receivers live on disk and are among the fastest growing things).293- **Cost**: journalling writes to disk on every change and there is additional overhead from opening and294 closing objects; the more journalled objects, the more impact. It is sized with the operations295 team, it is not turned on massively on a Friday.296- **Journal cache** (`JRNCACHE`, option **42 of the operating system, *HA Journal Performance*,297 chargeable): improves performance by grouping entries in memory, but **cached entries are298 not visible** to `DSPJRN`, `RCVJRNE`, `RTVJRNE` nor the `QjoRetrieveJournalEntries` API, **nor are they299 sent to the remote journal**. Verified in the IBM documentation. Translation: if the CDC reader300 "keeps losing the tail", it may not be a fault of the reader. And on a system crash, what is in301 memory is lost.302- **Remote journal**: it is added with `ADDRMTJRN` (not with `CRTJRN`) and allows reading the stream from another303 machine, distinguishing between committed and uncommitted entries. **It is the way not to put the304 CDC reader on the production system.**305306**Reading and extraction routes, with criteria:**307308| Route | When | Warning |309|---|---|---|310| `QSYS2.DISPLAY_JOURNAL` (SQL table function, available since 7.1) | Reading journal entries **with SQL**; it is what several commercial tools build on | The input parameters have to be bounded or the cost explodes; **interpreting the BLOB with the record image is not trivial** and it is where everyone who builds it by hand gets stuck |311| `RCVJRNE` / `RTVJRNE` / `QjoRetrieveJournalEntries` API | The program route: `RCVJRNE` delivers entries continuously to an exit program, and it is what replication products use | Exit program on the machine; subject to the journal cache (above) |312| **SQL over the catalogue and the tables** (JDBC/ODBC, `Run SQL Scripts`) | Initial load, profiling and reconciliation | It is the correct route for the *snapshot*; the impact on the production system is negotiated and executed in a window |313| `CPYTOIMPF` to a stream file in the IFS | Delimited dump when there is no direct connectivity | **The CCSID is decided explicitly** (`STMFCCSID`): the stream inherits by default the EBCDIC CCSID of the table. Verified in the IBM documentation |314| DDM / DRDA / web services (IWS, §6) | Point integration and querying, not bulk load | DDM and DRDA are also an access surface to control (§5) |315| Third-party tools | When the CDC is continuous and the project pays for it | **Verify product, version and mechanism before quoting it** (§8) |316317**On third-party tools, without marketing**: the ones that lean on this platform read the318journal, by one of the two routes above. As of Aug 2026 it has been verified that **Qlik Replicate** and the319**Fivetran/HVR** connector capture via `DISPLAY_JOURNAL`, that **Informatica PowerExchange** captures320from the receivers, and that **Matillion** publishes a *streaming* connector for Db2 for i based on321journal entries. **Debezium's official Db2 connector is for Db2 for Linux/UNIX/Windows and does not322cover Db2 for i**; there is a third-party community connector that does read the journal — **do not treat it323as equivalent in support**. This list is a market signal, not a recommendation: it gets re-verified (§8).324325**The data traps that break the migration** (this is what makes the project slip, not326the volume):327- **Packed and signed** (*packed* / *zoned*): numbers stored with the sign in the last328 half byte. Decades of programs writing directly leave **values with an invalid sign or digit329 nibble** that no sample `SELECT` uncovers and that blow up when converting in bulk.330 **100 % of the numeric columns are profiled before moving anything**, not a sample.331- **Dates in numeric of 6, 7 or 8 digits**: `YYMMDD`, the 7-digit format with the century in front, or332 `YYYYMMDD`. It brings `0`, `999999`, day 31 in months of 30, and **century windows implicit in the333 code** ("less than 40 is 20xx") that have to be extracted as a rule (§3.4), not guessed. Each334 sentinel combination is decided with the business: not all of them mean "null".335- **Multi-member files**: a physical file with several members —typically a history per336 year or per company—. **SQL has no equivalent and uses the first member by default**, so an337 extraction over SQL takes one chunk and looks correct. Verified in the IBM documentation: it338 is accessed with `CREATE ALIAS` over the specific member (or with a logical over all of them, or `OVRDBF`).339 **Checking for the existence of multiple members is a mandatory step of the inventory**, and moreover340 partitioning by member **is** an implicit business rule.341- **Fixed length with padding**: `CHAR` values come padded with blanks; business keys that in the342 target are compared with `VARCHAR` stop matching. A trimming policy is decided **once** and343 applied the same way in load and in reconciliation.344- **EBCDIC and CCSID**: the data is born in EBCDIC. **`CCSID 65535` (`*HEX`) means "do not convert"** and is345 the classic finding: the ODBC/JDBC client treats it as binary or fails. You have to distinguish the346 column that is **truly binary** from the one that is text that was never tagged, and tag it; done347 blind, accents, `Ñ` and currency symbols get corrupted. **Redefining the CCSID does not rewrite the348 bytes: it changes how they are interpreted** — so an error here is invisible until someone reads349 a proper name.350- **Redefined and reused fields**: a field whose meaning depends on the value of another, a351 `CHAR(30)` that carries three subfields inside, a "status code" to which new meanings were added352 without changing the structure, or fields declared and no longer used that are still353 full of old data. **No tool detects it: it comes out of profiling real values plus354 the rule extraction of §3.4.** A field with two meanings **is split into two in the355 target**, and that is a business decision with an owner.356357**Reconciliation is not optional and is designed before extracting.** Minimum: row counts and **control358sums per business numeric column** (amounts, not identifiers) per partition359—fiscal year/company/warehouse—, compared against the source **at the same logical instant**; count360of distinct values and of nulls/sentinels in the key columns; and for CDC, the lag between the361last applied journal entry and the source's. Reconciliation **is executed in the rehearsal and in the362cutover**, with the tolerance agreed **in writing beforehand** —the execution of the cutover and its363reconciliation belong to `migration-projects-standards`; **the definition of what is reconciled on this364platform belongs here**—. An extraction that does not reconcile **is not fixed by hand in the target**: the365process is fixed and it is executed again, because the manual fix is not repeatable and the cutover is366executed more than once.367368## 4. Quality, version control and CI369370- **The source lives in Git, in the IFS** (`.rpgle`/`.sqlrpgle`/`.clle`/`.sql`), **not in members of371 `QSYS.LIB`**: a member with a modification date is not history and does not allow branches, diff nor372 review. **It is the change with the highest return of the whole modernisation, and it comes before the others.**373- **Reproducible build**: versioned script (Code for IBM i ecosystem utilities, or your own CL)374 that rebuilds from scratch in a clean library. If nobody knows how to recompile everything, there is no375 delivery: there is patching.376- **Environments separated by library and `*LIBL`**, with their own **masked** test data.377- **Tests**: unit over ILE procedures (made possible by the design of §3.1) and regression by378 comparison of batch outputs. A monolithic program that can only be tested over 5250 is, in379 practice, not testable: that is the first thing that has to be broken.380- **Minimum CI gate**: compiles clean without ignoring warnings, the suite passes, and **no object is381 created by hand in production**.382383## 5. Stack security384385- **`QSECURITY` 40 as a minimum**; 50 in regulated environments. Below 40 the integrity of the386 system is not guaranteed; raising it is a project, but **staying at 30 is not defensible**.387- **`*ALLOBJ` is the problem.** Every profile with `*ALLOBJ`/`*SECOFR` is a total administrator of the system388 and of the data. Inventory who has it —including via group profile—, justify it one389 by one and remove the rest: this is where application profiles and service users with total390 authority show up.391- **Public authority**: `*EXCLUDE` on data objects and granting by authorization list.392 `*PUBLIC *CHANGE` on business libraries is the guaranteed audit finding.393- **Adopted authority (`USRPRF(*OWNER)`)** grants access only while the program runs, and it is a risk394 if the program allows reaching a command line. Adopt from the smallest object possible,395 control propagation (`USEADPAUT`), and **no program that adopts authority offers command396 entry**.397- **The back door is not the 5250**: it is the open interfaces (FTP, ODBC/JDBC, DRDA, DDM,398 REST). A user limited by menu can read all the tables over ODBC if there are no exit399 programs nor object-level authority. **Security goes on the object, not on the menu.**400- **Native MFA**: 7.6 incorporates TOTP into the operating system, applicable to all authentication401 points (5250, FTP) and to SST/DST profiles, at no additional cost — reason enough, by402 itself, to plan the jump. 7.6 also adds encryption of the system ASP (SYSBAS): verify403 the operational impact before enabling it.404- **`QAUDJRN` enabled and exported to the SIEM**: if the audit journal does not leave the machine, it is405 a blind spot.406407## 6. Integration and interface modernisation408409- **Web services**: **IWS** exposes a program or procedure as REST/SOAP without leaving the410 platform; for consumption, native HTTP client or SQL functions. With volume or complex integration,411 the alternative is an external service that speaks Db2 for i over SQL.412- **The usual trap: wrapping the 5250 screen in web without redesigning the flow.** Out comes the same413 sequence of screens with CSS, with its step-by-step navigation, its field-by-field validation and its414 conversational session: **you gain looks, not usability nor decoupling**. Prerequisite to415 any new interface: that the logic be in ILE procedures callable without a screen416 (§3.1). While it lives in the DSPF's program, the web layer is make-up.417- **API before screen**: the unit of reuse is the procedure, not the interactive418 program.419420## 7. When to stay, when to migrate and prohibitions421422**Staying is correct —and it is more often than people think— when:**423- The application covers the business, the total cost (licence + support + staff) is known and424 competitive, and there is Power hardware in support with a path to 7.5/7.6.425- The operation is what the platform does exceptionally well: reliable batch, integrated426 database, very little administration per transaction, high availability with a small team.427- It can be modernised *inside*: ILE, SQL, Git, CI, APIs. **That route is dramatically cheaper428 than rewriting and almost nobody exhausts it before raising migration.**429430**Migrating makes sense when** the single vendor is a risk accepted by management, when the431subscription cost stops being competitive against the value, when the functionality is bought ready432made (ERP), or when there is no staff and there will not be — **measured in your shop, not in an article**.433434**Prohibitions:**435436- ❌ **FORBIDDEN** to write new code in fixed-format RPG (columns), in RPG III/OPM or with437 numeric indicators as logic. Everything new: **`**FREE`**, procedures, named438 variables.439- ❌ New monolithic programs without ILE, or `DFTACTGRP(*YES)` in new code.440- ❌ Native record-level access for new set logic (`CHAIN`/`READE` loops that are a441 *join*).442- ❌ Defining new tables with DDS instead of SQL DDL.443- ❌ **`QSYS.LIB` source members as version control.** The source goes to Git, in the IFS.444- ❌ Compiling or creating objects by hand in production.445- ❌ `QSECURITY` below 40; `*ALLOBJ` handed around; `*PUBLIC *CHANGE` on data libraries.446- ❌ Programs that adopt authority and allow a command line.447- ❌ Entrusting security to the 5250 menu while leaving ODBC/FTP/DDM uncontrolled.448- ❌ Presenting as modernisation a web wrapper of the same 5250 screens (§6).449- ❌ **Promising that the business logic has been extracted from static analysis** (`DSPPGMREF`,450 IBM i Services views) **without declaring the blind spot**: dynamic calls, dynamic SQL and451 resolution by `*LIBL` are not seen there (§3.4).452- ❌ Discarding a rule because nobody in the business recognises it, or fixing it inside the same change453 that migrates it. It is characterized as it is and the functional change goes separately (§3.4).454- ❌ Considering the logic inventoried without having looked at **triggers, constraints, validity455 keywords in DDS, exit point programs, `*QRYDFN` and the spreadsheets over ODBC** (§3.4).456- ❌ **Extracting over SQL from a multi-member file without checking the members**: SQL uses the first and457 the result looks correct (§3.5).458- ❌ Converting numeric columns or numeric dates **over a sample**: profiling is of459 100 % of the rows (§3.5).460- ❌ Moving data ignoring the CCSID, or "fixing" a `CCSID 65535` by changing the tag without deciding461 first whether the column is binary or untagged text (§3.5).462- ❌ Setting up a CDC over journals **without agreeing receiver retention beforehand** with the systems463 team: if they are deleted before being processed, the loss is silent (§3.5).464- ❌ Diagnosing a CDC reader "that loses the tail" without ruling out the **journal cache**: its465 entries are not visible nor sent to the remote journal (§3.5).466- ❌ Executing a cutover without a defined reconciliation and a tolerance agreed in writing, or repairing by hand in the467 target what did not reconcile (§3.5).468- ❌ Planning a release upgrade without first checking the ceiling imposed by the Power generation.469- ❌ Quoting perpetual-vs-subscription cost figures or IDE market share without naming the470 source and its method (§8).471472## 8. Mandatory web verification473474Before pinning anything in a real project, check on the web:4754761. **Current IBM i release and its calendar**: as of Aug 2026, 7.6, 7.5 and 7.4 are supported (the last477 one with a service level change on 30 Sep 2026 and extension until 30 Sep 2029). **Declared478 gap: IBM had not announced end-of-support dates for 7.5 or 7.6.** Do not infer them479 as if they were an announcement; consult IBM's official release support page (PID480 5770-SS1).4812. **Release ↔ Power generation matrix** and minimum firmware level before committing to an482 upgrade.4833. **Current licensing model**: which tiers still have perpetual, conditions of the484 subscription and of the *5250 Enterprise Enablement*. **Prices are not documented here: IBM does not485 publish them in announcement letters and they are only reliable via a partner quote.**4864. **Status and licence of Code for IBM i**: as of Aug 2026, `codefori/vscode-ibmi`, **MIT licence**487 verified in the repository; **community** project, **without IBM support**. Verify also whether488 it is still the active repository before basing a decision on it — the GitHub releases489 feed is not the source of truth if the project moves.4905. **RDi status**: 9.8 with support discontinuation on 30 Apr 2026; 9.9 released491 5 Dec 2025. Verify the 9.9 calendar and who supports it (IBM contracts Fortra).4926. **Technology Refresh level** current for your release and which IBM i Services it adds: the list of493 SQL views grows with each TR and determines what you can automate.4947. IBM i security bulletins, cumulative security PTFs and CVEs of the ported open495 source components (which arrive on their own calendar).4968. **Tool adoption figures** (market surveys of the Fortra type): they are self-reported497 surveys with an unpublished sample; **use them as a trend signal, never as hard data**.4989. **Every command or SQL view name in this skill, against `ibm.com/docs` for the client's499 release, before typing it.** Verified as of Aug 2026 in IBM documentation: `DSPPGMREF`500 (output format `QWHDRPPR` over `QADSPPGM`, a single library per invocation, entries that501 are added but not removed when updating an ILE program), `DSPDBR` (and the limit with the502 parent/child constraints, which IBM covers with `DSPEDBR` from `QMGTOOLS`), `WRKREGINF`,503 `QSYS2.EXIT_POINT_INFO` and `EXIT_PROGRAM_INFO` (7.4 TR3 / 7.3 TR9), `QSYS2.PROGRAM_INFO`,504 `BOUND_MODULE_INFO`, `BOUND_SRVPGM_INFO`, 505506…(truncated)