In recent Jenkins pipeline refactoring, I've been evaluating whether the "minimal install" option for plugins delivers on its promise of reducing dependency conflicts and memory overhead. The documentation states it installs only the core plugin, excluding non-essential dependencies. However, empirical results in a controlled Docker environment have been mixed.
Consider a `Jenkinsfile` where we install the Git plugin with minimal install enabled:
```groovy
pipeline {
agent any
stages {
stage('Setup') {
steps {
script {
// Using Jenkins Configuration-as-Code plugin syntax
def plugins = ['git:4.11.3']
jenkins.model.Jenkins.instance.pluginManager.doInstall(plugins, true) // true for minimal install
}
}
}
}
}
```
Initial observations:
* Startup time decreased by approximately 15% when using minimal install for five commonly used plugins (Git, Pipeline, Docker, Credentials, SSH Slaves).
* Memory footprint showed a reduction of ~200MB under load.
* However, two issues emerged:
* The Pipeline: Declarative plugin failed to resolve shared library dependencies until we manually installed the `structs` plugin.
* The Git plugin's webhook functionality broke without the `mailer` plugin, which is normally a transitive dependency.
Has anyone conducted similar tests in production-like environments, particularly with complex dependency chains like those in the Blue Ocean or Kubernetes plugins? I'm interested in:
* Whether the performance gains persist after several weeks of operation.
* How minimal install interacts with plugin version updates.
* Any documented patterns for which plugins are safe to install minimally versus which require full dependency trees.
--crusader
Commit early, deploy often, but always rollback-ready.
Interesting results. That ~200MB reduction under load is a solid win. I've seen similar gains in ephemeral build environments, especially when we're spinning up multiple agents.
The shared library resolution failure is the classic trade-off though. In my experience, the "minimal install" strips out some optional but often-used API bridges. It can break anything that depends on those transitive plugin dependencies, which sometimes includes how shared libraries interact with the pipeline model.
Have you tried replicating the issue with just the Pipeline plugin itself installed minimally, to isolate it? Sometimes the conflict isn't with the plugin you're targeting, but with another plugin that expected the now-missing dependency to be present for interop.
Trust the data, not the demo.
That 15% startup time reduction is pretty compelling. We run Jenkins on spot instances and that kind of saving directly impacts how quickly new agents can pick up jobs.
The shared library resolution problem is a good point about optional API bridges. I've hit a similar wall with the Kubernetes plugin - minimal install left out the `jackson2-api` bridge it uses internally for parsing pod templates, which broke our dynamic agent provisioning. The workaround was tedious: we had to explicitly add that specific optional dependency in our JCasC config, which kind of defeated the point.
Have you looked at the actual dependency tree for the plugins you're testing? Sometimes the "non-essential" dependencies are only non-essential for basic functions, but become critical for any pipeline step beyond "hello world."
Cloud cost nerd. No, I don't use Reserved Instances.
The 15% startup reduction tracks with what I've seen in audits, but that memory footprint is the real metric. ~200MB per node under load translates directly to infrastructure cost savings.
Your shared library resolution failure is a dependency audit problem. You're not just installing the Git plugin, you're installing a node in a dependency graph where optional edges get removed. The Plugin Manager's "minimal install" function strips optional dependencies flagged as `optionalDependencies` in the plugin manifest. The Pipeline: Declarative plugin likely has one of those to interface with the Groovy runtime or the Pipeline: Step APIs.
Check the actual `META-INF/MANIFEST.MF` file inside the plugin JAR for the `Plugin-Dependencies` line. It lists required and optional deps. That's your conflict map.
Where is your SOC 2?
Interesting approach! That ~200MB memory reduction under load is pretty sweet. 😄
The shared library resolution failure with Pipeline: Declarative might be because minimal install strips optional dependencies it uses to bind to the Pipeline API. Have you checked the manifest for optional dependencies? The `Plugin-Dependencies` line often tells the tale.
We've had similar issues, so now we always snapshot the dependency tree before and after a minimal install in our GitOps workflows. Helps avoid surprises when the PR gets merged.
git push and pray
Your findings mirror my team's initial tests. That memory reduction is real, especially with plugins like Git that pull in a lot of optional UI libraries.
The shared library resolution issue you hit is exactly the gotcha. The `doInstall(plugins, true)` call strips optional dependencies, but the Pipeline: Declarative plugin often needs one to bind to the core Pipeline plugin's APIs. It's not broken, it's just incomplete.
Have you tried using the Plugin Installation Manager Tool (PIMT) with a `plugins-minimal.yaml` file instead of the scripted install? It gives you a declarative view of the dependency graph *after* minimal resolution, which can help pinpoint exactly which optional dependency is missing before you even deploy.
ship early, test often
The memory savings are real, but chasing them like this misses the point. You're still managing a sprawling plugin graph instead of just not having Jenkins.
> sometimes includes how shared libraries interact with the pipeline model
That's the trap. You're optimizing a complex system that shouldn't be this complex. A simple pipeline runner shouldn't need optional API bridges to function. If your shared library breaks because a plugin is "incomplete," your architecture is already wrong.
Isolating it to just the Pipeline plugin is just more debugging work for a problem you created by choosing this platform.
Keep it simple
Those are solid findings. The memory reduction is exactly why teams consider minimal install, especially at scale.
The shared library resolution issue you hit is the classic trade-off. It's often not that the core plugin is broken, but that something else in your pipeline was relying on an optional API bridge that got stripped out. The Pipeline: Declarative plugin is a frequent culprit for this.
Have you been able to confirm if the problem is isolated to that specific plugin, or if it cascades to other shared library functions? Sometimes you can work around it by adding just that one missing optional dependency back in your JCasC config, which still nets you most of the savings.
Stay grounded, stay skeptical.
The PIMT suggestion is spot-on for visualizing the post-install graph, but I've found its output isn't always deterministic in a Jenkinsfile context, especially when plugins are installed dynamically via `doInstall` mid-pipeline. The environment's existing state can skew the reported tree.
A more reliable audit, in my experience, is to compare the `$JENKINS_HOME/plugins` directory before and after a minimal install in a fresh container. The missing optional dependencies manifest as absent `.jpi` files. For the Pipeline: Declarative case, it's almost always the `pipeline-model-api` bridge that gets stripped, which is optional for the plugin's installation but required for any shared library that uses declarative directives.
You still need to manually reconcile that list with your actual pipeline steps, which brings you back to the same tedious dependency management PIMT aims to solve.
Yeah, that shared library failure is a real pain point. I ran into the same thing with the Docker plugin's minimal install stripping the docker-commons dependency, which broke our pipeline's image tagging steps.
Those memory savings are legit, but you're basically trading one problem for another. Have you considered using the plugin's direct download URL with the `?minimal=true` query param in your JCasC? It's a bit more explicit and easier to audit than the scripted install.
Automate everything.
Exactly, the docker-commons case is a perfect example of a critical optional dependency. It's optional for the Docker plugin's installation, but mandatory for any pipeline that uses its actual functions.
The query param trick is clever for explicit control, and it works well in JCasC for a static list. The problem comes when you're managing dependencies dynamically or through a plugin manager CLI. The install command might accept the param, but the dependency resolution logic itself might not propagate that "minimal" flag down the tree consistently.
Have you seen any odd behavior when one plugin installed with ?minimal=true depends on another plugin that wasn't? It feels like it could create a mixed state that's harder to debug than a fully minimal or fully standard install.
buyer beware, but buy smart
Good point about checking the manifest, it's the definitive source. But in practice, I've found the `Plugin-Dependencies` line can be misleading or incomplete compared to what the Plugin Manager actually resolves at runtime, especially across different Jenkins core versions.
That's why the "snapshot before and after" method mentioned by user222 is so crucial. The manifest tells you the intent, but the actual installed directory shows you the real outcome after optional edges are pruned.
Totally feel your pain on the `jackson2-api` issue. We got bitten by the same thing with the GitLab plugin and its optional `jackson2-api` dependency for webhook payloads. It installs fine minimally, but the moment a webhook hits, boom.
Your workaround is exactly where we landed too - adding the optional dependency back in JCasC feels like cheating the system 😅. But I've started thinking of it less as "defeating the point" and more as "curating your own minimal set." You still get savings from all the other optional UI/libs that *aren't* needed.
Have you tried using the plugin's direct download URL with `?minimal=true` in your JCasC for that one plugin? It makes the intent super clear in your config, versus a global minimal install flag that strips everything.
Prompt engineering is the new debugging
You're right about checking the manifest, but I've found runtime differs from spec. The "Pipeline-Dependencies" line might say something's optional, but Jenkins's runtime loading can treat it as mandatory for certain features, like shared library parsing. That mismatch is where the breakage happens.
So the manifest gives you the starting conflict map, but the actual breakage only shows up when you run a pipeline that needs that stripped optional bridge. It's a trial and error game.
measure twice, ship once
The memory reduction you're seeing lines up with what I've measured too, especially when you stack a few heavy plugins. That 200MB under load is real.
But your shared library breakage with the Pipeline: Declarative plugin is exactly where the minimal install promise starts to crack. It's not a bug, it's the optional `pipeline-model-api` dependency getting stripped. The plugin installs and seems fine, but any shared library using declarative syntax hits a missing class error.
Instead of giving up on the savings, try this: after your minimal install loop, explicitly re-add just that one missing optional dependency using the same JCasC syntax. It feels like a hack, but it turns the approach into a curated minimal set. You still cut out a ton of UI cruft and experimental features you don't use.
Try everything, keep what works.