A Spring Boot application can be packaged as one self-contained JAR with every dependency inside, or as a thin JAR that carries only your classes and fetches the rest when it starts. The marketplace has a builder package for each, and the choice is less about elegance than about your pipeline: how often you deploy, how many nodes receive the artefact, and whether they can reach a repository. This post follows a Java developer measuring both on MassiveGRID PaaS, which is built on Virtuozzo Application Platform, formerly Jelastic.
The developer maintains a dozen Spring Boot services for a logistics SaaS we will call Cordage Freight. The Spring Boot Fat Jar Builder deploys a Java Engine node with Maven that clones a Git project, builds a fat JAR and runs it; the Spring Boot Thin Jar Builder does the same with the Thin Launcher, producing a JAR of only the application's classes that resolves dependencies at start-up.
What the two packages install
Both create a single Java Engine node, a lightweight container with an LTS JDK, with Apache Maven installed and a sample Spring Boot project cloned and built on first deploy so the pipeline is proven before you touch it. The fat variant caches the Spring Boot starter dependencies for fast builds and produces the familiar 60 to 100 MB executable. The thin variant's sample project includes the Thin Launcher Maven plugin; the build produces a JAR of a few megabytes, and at start the launcher resolves the dependencies declared in the project's pom.xml into a local Maven repository on the node, then runs. Either package becomes yours by changing the Git URL and Maven goals in the node's configuration and redeploying.
Measuring on a real service
The developer takes the order-tracking service and builds it both ways on two nodes.
| Measure | Fat JAR | Thin JAR |
|---|---|---|
| Artefact size | 84 MB | 3.7 MB |
| Build time on the node (warm Maven cache) | 48 s | 41 s |
| First start on a fresh node | 6 s (JVM start only) | 58 s (dependency resolution from Maven Central) then 6 s |
| First start with a Nexus proxy on the internal network | 6 s | 14 s then 6 s |
| Subsequent starts on the same node | 6 s | 6 s (dependencies cached) |
| Redeploy after a code-only change | Upload 84 MB, restart | Upload 3.7 MB, restart; no fetch |
| Redeploy after a dependency bump | Upload 84 MB, restart | Upload 3.7 MB, fetch the changed artefacts, restart |
| Works without network at start | Yes | Only if the local Maven repository is already populated |
Reading the table
For a service that deploys twice a week to two nodes, none of this matters and the fat JAR's simplicity wins: one file, no network dependency at start, no repository to keep available. For Cordage's busiest services, which deploy several times a day to layers that auto-scale to six nodes, the arithmetic changes. Every fat deploy moves 84 MB to every node; every scale-out event copies it again. Thin JARs move 4 MB and rely on each node's cache, and the platform's stateful scaling mode, which clones new nodes from the layer's master, brings the populated Maven repository along, so a scaled node starts in six seconds too. The one hard requirement the developer writes down: thin JARs need a repository reachable from the nodes at first start, and the public Maven Central is slow and rate-limited from a fleet. The Nexus Repository package on the internal network cut the first start from 58 to 14 seconds and made the fetch reproducible.
Where the builder nodes sit in the pipeline
Neither package is meant to be production by itself; each is a single node. Their role is the build. Cordage runs one builder node per service on a schedule from the Start/Stop Scheduler, building from the release branch and publishing the JAR to Nexus's hosted Maven repository. The production layers are Spring Boot Clusters, which deploy the artefact from Nexus through the Deployment Manager, sequentially across nodes. The builder is where the fat-or-thin decision is made per service, and the cluster does not care which arrives.
For teams with a CI server already, the builders are still a useful template: the node's Maven goals and Git configuration show exactly how the platform expects a Spring Boot build to be wired, and the Git-Push-Deploy add-on for Java creates the same kind of Maven build node automatically.
The decision rule Cordage adopted
- Fat JAR for services that deploy infrequently, run on one or two nodes, or must start with no network dependency (the batch jobs).
- Thin JAR for services that deploy often to auto-scaling layers, with Nexus on the internal network as the repository and stateful scaling so new nodes inherit the cache.
- Either way, dependencies are locked in the
pom.xmland resolved through Nexus, so a build from last year reproduces.
Seven of the twelve services went thin, five stayed fat. Deploy traffic across the estate fell by an order of magnitude, and the developer stopped waiting for uploads.
Cost
A builder node runs only while building; stopped, it bills for disk. Cordage's twelve builders together consume a few cloudlet-hours a day. The production clusters are unaffected by the artefact format except that thin JARs' first starts on fresh nodes use a little CPU for resolution. At MassiveGRID's published $0.003372 per cloudlet-hour the builders add a low two-figure monthly sum before discounts, which is the cost of never building on a laptop again.
Frequently Asked Questions
Can a thin JAR start if Maven Central is down?
Only if the node's local Maven repository already holds every dependency, which is the case after the first start on that node and on nodes cloned from it. Pointing the launcher at a Nexus proxy on the internal network removes the dependence on the public registry entirely, since Nexus serves cached artefacts even when upstream is unreachable.
Do container images make this choice moot?
Partly. A layered container image achieves a similar effect to a thin JAR by caching dependency layers. On the platform's Java Engine nodes, which run JARs directly without an image build step, the fat-or-thin choice is the equivalent lever.
Can I use Gradle instead of Maven?
The builder packages are configured for Maven. A Gradle project can produce a fat JAR (bootJar) or a thin JAR with the Thin Launcher's Gradle plugin in your CI, and the resulting artefact deploys to the Spring Boot cluster the same way; the builder nodes' Maven goals would need replacing with a Gradle invocation on the node.
Build it the way your pipeline needs
The Spring Boot Thin Jar and Fat Jar Builder packages deploy a Java Engine node with Maven that builds your project from Git on MassiveGRID PaaS, with a working sample to start from. Per cloudlet-hour, free 14-day trial.
Spring Boot Builders on MassiveGRID PaaS