Guru: Taming The CRTSRVPGM Command – Options That Can Save Your Sanity
January 19, 2026 Gregory Simmons
If you have ever run CRTSRVPGM without paying attention to its parameters, you are not alone. Many developers just accept the defaults and move on, only to discover later that those defaults can introduce subtle bugs or unnecessary headaches. The command looks simple, but it is packed with options that can either make your life easier or create a ticking time bomb in your system. Let’s talk about a couple of the most important ones.
One parameter that deserves special attention is OPTION. By default, this parameter is blank, which seems harmless, but that blank value means you’re allowing duplicate procedures and variables in your service program: essentially OPTION(*DUPPROC *DUPVAR). On the surface, that might sound like flexibility, but in practice, it’s an open invitation for confusion. Two procedures with the same name in different modules? That’s a debugging nightmare. By explicitly setting OPTION(*NODUPPROC *NODUPVAR), you prevent duplicates at compile time. Your build might fail sooner, but trust me, that’s a much better problem than chasing down runtime errors later.
Binding directories are another parameter that often stirs debate. Some developers love them because they simplify program creation: point to a directory, compile, and everything just works. Others argue they are a crutch that hides too much from the developer. My take? Binding directories are great when used intentionally and consistently. They centralize your service program references, which makes maintenance easier – if you are disciplined about what goes into them. If you throw everything into a single “catch-all” directory, you will lose the benefit and end up with a mess that’s hard to untangle later.
In my shop, we take this a step further with naming conventions that make it impossible to confuse which procedure belongs to which service program. Every procedure name begins with the service program’s name. For example, in a service program called MSHRMUTILS, you might find procedures like MSHRMUTILS_SAVE_NEW_SPECIES or MSHRMUTILS_IS_EDIBLE. This has two major benefits. First, we completely avoid duplicate procedure names across different service programs. Second, when you see a call to a procedure, you immediately know which service program it came from, without needing to dig through binding directories or module definitions.
We apply the same convention to global variables – although we use them sparingly. Local variables are almost always the better choice, both for readability and to avoid unintended side effects. If you’re curious about why local variables should be your default, I wrote a deep dive on that topic here: Procedure-Driven RPG Means Keeping Your Variables Local.
When you take the time to explicitly set parameters like OPTION and thoughtfully design your binding directories, your service programs become easier to maintain and far more predictable. You don’t have to guess whether duplicate procedure names will cause a problem because you’ve already prevented it at compile time. And your naming conventions become a form of documentation that future developers will thank you for.
Until next time, happy coding.
Gregory Simmons is a Project Manager with PC Richard & Son. He started on the IBM i platform in 1994, graduated with a degree in Computer Information Systems in 1997 and has been working on the OS/400 and IBM i platform ever since. He has been a registered instructor with the IBM Academic Initiative since 2007, an IBM Champion and holds a COMMON Application Developer certification. When he’s not trying to figure out how to speed up legacy programs, he enjoys speaking at technical conferences, running, backpacking, hunting, and fishing.
RELATED STORIES
Guru: CRTSRVPGM Parameters That Can Save or Sink You
Guru: A First Look at Bob, The IBM i Assistant That’s Closer Than You Think
Bob More Than Just A Code Assistant, IBM i Chief Architect Will Says
IBM Pulls The Curtain Back A Smidge On Project Bob
Big Blue Converges IBM i RPG And System Z COBOL Code Assistants Into “Project Bob”
Guru: When Attention Turns To You – Writing Your Own ATTN Program
Guru: WCA4i And Granite – Because You’ve Got Bigger Things To Build
Guru: When Procedure Driven RPG Really Works
Guru: Unlocking The Power Of %CONCAT And %CONCATARR In RPG
Guru: AI Pair Programming In RPG With Continue
Guru: AI Pair Programming In RPG With GitHub Copilot
Guru: RPG Receives Enumerator Operator
Guru: RPG Select Operation Gets Some Sweet Upgrades
Guru: Growing A More Productive Team With Procedure Driven RPG
Guru: With Procedure Driven RPG, Be Precise With Options(*Exact)
Guru: Testing URLs With HTTP_GET_VERBOSE
Guru: Fooling Around With SQL And RPG
Guru: Procedure Driven RPG And Adopting The Pillars Of Object-Oriented Programming
Guru: Getting Started With The Code 4 i Extension Within VS Code
Guru: Procedure Driven RPG Means Keeping Your Variables Local
Guru: Procedure Driven RPG With Linear-Main Programs
Guru: Speeding Up RPG By Reducing I/O Operations, Part 2
Guru: Speeding Up RPG By Reducing I/O Operations, Part 1
Guru: Watch Out For This Pitfall When Working With Integer Columns

