Guru: Service Programs And Activation Groups – Design Decisions That Matter
February 9, 2026 Gregory Simmons
If you have been writing service programs for a while, you might treat binding like flipping a light switch: write some code, compile it, bind it, done. It works – until it doesn’t. Behind the scenes, IBM i is doing a lot more than just connecting your program to a library of procedures. And if you’re not paying attention to activation groups and how you structure your service programs, you might be setting yourself up for sluggish performance or debugging nightmares down the road.
Let’s demystify what is really happening when you bind and why activation groups deserve more of your attention.
When you bind a program to a service program, IBM i doesn’t stuff the service program code into your program object. Instead, it stores references – pointers to the procedures in the service program. At runtime, those procedures get loaded into memory the first time they’re called, and if you have got multiple programs bound to the same service program, they can all share that single loaded copy. This is one of the reasons ILE is so powerful: modularity with memory efficiency.
But this efficiency hinges on activation groups. A service program lives inside an activation group. If that group goes away, so does the service program and its data. Pick the wrong activation group strategy, and you’ll spend more time chasing down “weird behavior” than writing business logic.
There are three common activation group settings every RPG developer should know:
- *CALLER: The program or service program runs in the activation group of whatever called it. This is efficient because the service program doesn’t reload with every call, but it can make debugging trickier – your state and variables persist longer than you might expect.
- *NEW: A fresh activation group spins up every time the program is run. Great for isolation but expensive on performance, especially in high-volume environments.
- Named activation groups: These are the sweet spot for many applications. You get the efficiency of shared memory and better control over when things are cleaned up.
If you have ever had a “ghost” value show up in a global variable or a routine that worked yesterday suddenly misbehaving, there’s a good chance activation group choices were part of the problem.
Here’s a quick example. Suppose you’re binding your service program with:
CRTSRVPGM SRVPGM(MYLIB/MSHRMUTILS) MODULE(MYLIB/MSHRMUTILS) ACTGRP(*CALLER) EXPORT(*SRCFILE)
With *CALLER, the service program will reuse the caller’s activation group, meaning it doesn’t reload every time. Great for performance, but if you’re storing any global data, you need to be extra careful. If you instead use:
CRTSRVPGM SRVPGM(MYLIB/MSHRMUTILS) MODULE(MYLIB/MSHRMUTILS) ACTGRP(MSHRMUTILS) EXPORT(*SRCFILE)
Now you have got a named activation group (MSHRMUTILS) where your service program lives persistently. This gives you predictable memory usage while letting you control teardown by explicitly ending that activation group.
Another performance trap I see often is what I like to call the “junk drawer service program.” Someone decides to throw every utility procedure they’ve ever written into one massive service program because, hey, why not? The problem is that every time a program binds to that monster, it’s carrying all that baggage – even if it only calls one or two procedures.
Large service programs can also slow down your development workflow. If a single procedure changes, everything that’s bound to that service program has to be rebuilt. That’s a lot of compile time wasted because of sloppy organization.
The better approach is to group procedures logically. A general purpose utilities service program is fine if it really contains things you use everywhere. But when you have domain-specific logic – say, mushroom inventory tracking or customer billing – keep those in smaller, focused service programs. This modular design means fewer surprises, faster compiles, and simpler debugging.
Here’s the bottom line: Activation groups and service program design aren’t just technical trivia; they’re design decisions that will either save or sink your project in the long run. If you’re in a performance-sensitive environment, understanding activation group behavior is critical. Named activation groups give you predictability and stability, while *CALLER offers speed at the cost of more complexity. *NEW should be reserved for when isolation is non-negotiable.
And don’t underestimate the maintenance impact of your service program structure. Modular, well-organized service programs save developers countless hours when debugging or deploying updates. Poorly organized ones? They’ll turn every release into a fire drill.
ILE is one of the most powerful parts of IBM i, but like all power, it comes with responsibility. Service programs give you modularity and memory efficiency. Activation groups give you flexibility. But both can burn you if you ignore the details.
Start small: review your activation group settings and break apart any service programs that have become dumping grounds. Make deliberate choices now, and you’ll avoid the “why is this so slow?” questions later.
In the next article, we will take a hard look at binding directories – a feature that can either simplify your builds or make your dependencies a tangled mess.
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: Binder Source Is Your Service Program’s Owner’s Manual
Guru: Access Client Solutions 1.1.9.11 – Security First, With Continued Investment In SQL Tooling
Guru: Taming The CRTSRVPGM Command – Options That Can Save Your Sanity
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

