Containerizing IBM ACE: A Blog Series - Scoping your runtimes
Packiging containers isn’t complicated, right? Just throw everything in there. Well, it is, until it isn’t. Stack too much in one and you overload. Mix fragile with flammable, and things get risky. Leave half of it empty, and you're wasting capacity. Sound familiar?
Let’s be real. “One app per container” sounds clean on paper, but you’d be staring at hundreds of containers before lunch. So you bundle. But how?
The trick is knowing what belongs together and what absolutely doesn't. This post lays out the logic. Grounded, brutal, and battle-tested. How to scope your runtimes without blowing up performance, security, or your own sanity.
Performance and startup
Some loads are just heavy. You don't toss an engine block into a shipping container without expecting extra handling, extra time, and a few complaints from whoever has to lift it. The same goes for big schemas. They blow up compile times and drag out cold starts. That first sentence probably deserves a that’s what she said, but we’re being professional. Mostly.
So what do you do? You front-load the work. Compile at build time, not runtime. Get those hits out of the way before anything lands in prod. Track cold start behavior in test or UAT. Know what it costs to spin something up. Set a threshold that makes sense for your environment, and alert when you blow past it. Curious how to do that? I blogged about that: Bar Build Commands: Unraveling the Differences
If you don’t measure startup time, you’re just hoping it’s fast enough. Spoiler: it won’t be.
Resource interference
You wouldn’t pack volatile chemicals next to fresh produce. If one leaks, everything’s toast. Same deal with runtimes. Put two unrelated applications in the same container, and one bad actor can tank the whole thing.
A CPU spike in one flow means the other gets starved. A memory leak in some forgotten listener takes down your critical path. Or worse, one flow mounts a file system that the other has no business even seeing. Now you’ve got an attack surface no one asked for.
If you can't explain, clearly and in one sentence, why two peas are in the same pod, they shouldn't be. “Because we always did it that way” is NOT a reason. It's a red flag. If that’s your answer, stop what you’re doing and go fix it. And don’t say it out loud. Ever.
When in doubt, split. Isolation costs less than cleanup.
Bundling logic
Bundling isn’t inherently bad. But bundling for the wrong reasons will rot your runtime from the inside out. The points below are just that: points. Not rules. Not guarantees. They’re starting positions. Use your brain.
Good reasons to bundle:
- They hit the same endpoint or interface and have the same criticality.
- They’re owned and operated by the same team. One team, one runtime is easier to live with.
- They’re a small set of resources that share a library and get updated together.
- They’re part of a bigger, tightly coupled setup that moves as one.
- They’re legacy apps with low change rates or a clear decommission plan. Keeping them together makes cleanup easy. No one wants to babysit a runtime for something that dies next quarter.
Bad reasons to bundle:
- You want to scale them differently.
- One is critical, the other isn’t. Don’t mix a payment flow with a reporting job and hope for the best.
- They handle data with different sensitivity levels.
- They’re loosely coupled and can fail independently. That’s a feature, not a flaw.
- You’re ignoring technical spillover. In ACE, if one app needs a feature, ibmint optimize keeps it on for all. One weird edge case, and nine other apps pay for it.
- You’re bundling out of convenience. Just because two flows came from the same BAR file doesn’t mean they belong together. That’s packaging, not architecture.
- You’re crossing team boundaries. If the apps don’t share ownership, support, or deployment cadence, you’re building in friction. Someone always ends up blocked.
If you can’t defend the bundle under fire, it’s not a bundle. It’s baggage.
Libraries and shared code
Shared code sounds smart. Until it drags half your runtime down with it.
It only makes sense to keep things together if they actually move together. If one flow needs a fix and you’re afraid to touch the lib because five others might break in the process, that’s not shared. That’s hostage-taking. Stockholm syndrome be damned.
It’s fine to keep flows together if they share a library and always get upgraded together. But don’t pretend one shared dependency means they belong in the same runtime. If half your flows use one subflow and the other half use another? Don’t lump them together. Split the library and run two runtimes.
Libraries enable reuse, and that’s great. But when you're managing runtimes, the goal isn’t optimal reuse. It’s control.
Scaling strategy
We can keep this one short.
Scaling costs money. So be mindful. Don’t scale if you don’t need to. Next.
Whether it’s horizontal, vertical, or startup scaling (yes, that last one is a teaser, watch for a dedicated blog), if an application needs to scale, separate it from the rest. You don’t scale an app. You scale a container.
Security and data sensitivity
Not all data is created equal. And not all flows should live next to each other.
If one flow handles sensitive data and the other doesn’t, keep them apart. Don’t let a sloppy debug endpoint or overly verbose log expose your payroll system. The same goes for trust boundaries. If the security level isn't the same, split it. And if bundling makes audits harder to explain, it’s probably the wrong setup.
Security isn’t where you get clever. Keep things predictable and contained.
Ownership and operations
A runtime is one unit. You restart it. You redeploy it. You roll it back. Everything inside gets hit.
So if multiple teams own different apps, don’t shove them into the same container. You’ll spend more time figuring out who’s on call and when you're even allowed to fix the issue than actually fixing the issue. Different owners means different responsibilities. Keep those lines sharp.
The same goes for the update strategy. You don’t patch a container. You rebuild it and restart it. That means even the untouched apps get bounced. If one team ships weekly and another ships quarterly, someone’s going to be caught in the crossfire.
Runtime boundaries should follow ownership and release patterns. If they don’t, enjoy the finger-pointing. If you ever find a patch window.
Runtime boundaries and coupling
If two flows are tightly coupled and always move together, they can share a runtime.
If they’re loosely coupled, keep them apart. Independent failure is not a flaw. It’s a feature. Don’t erase that by bundling them together.
In ACE, a crash in one flow can trigger a restart that hits everything in the container. Bundling loosely coupled apps turns isolated issues into shared outages. Don’t do that to yourself.
Build and release shape
Do the work at build time. Compile everything upfront. Your runtime should start fast and stay out of the way. If you're still allowing the runtime to compile your resources, you’re setting yourself up for slow starts and runtime surprises.
If you use fry
, make sure the exact artifact that passed tests is the one that goes to prod. If you use bake
, you’re already wrong. Just kidding. Have I mentioned I’m not a big fan of baking?
Compile early. Build clean. Test what you ship. Deploy without surprises. This isn’t hard.
A few more worth adding
Not everything fits neatly into design patterns or flow diagrams. But the following still matter. A lot.
Licensing cost
More CPU often means more PVU. And more PVU means more money. If scaling your runtime triggers a licensing bump, rethink your grouping.
Observability and failure impact
When a container dies, what goes with it? Which dashboards go blank? Which alerts go off? Keep failure domains small. Don’t let one noisy app tank the whole runtime.
Configuration variance
If two apps need different secrets, configs, or trust levels, they shouldn’t share a runtime. Separate them before that difference bites you during deployment.
Upgrade cadence
If one app gets updated weekly and another only once a quarter, split them. You don’t want stable apps getting rebooted every time someone else ships a fix.
Final note
Whatever you do, or however you do it, scope your runtimes with intent. If you're bundling by accident or just filling up runtimes, you're doing it wrong.
Other blogs from the Containerizing IBM ACE series
Written by Matthias Blomme and Kim Meynendonckx
#IBMChampion
#IBMAppConnect