The standardized Spring Boot app we deploy to every platform for StackVia hosting benchmarks. Same app, same Dockerfile, everywhere → honest apples-to-apples numbers.
It's open source (MIT) so our benchmarks are fully reproducible — clone it, deploy it, and check our numbers yourself. Spotted something we could measure better? PRs welcome.
- Spring Boot 3.3.5, Java 21,
spring-boot-starter-web+actuator. GET /→ JSON: version (for redeploy checks) + uptime + how much RAM/CPUs the JVM actually sees (proves whether a plan can really run a JVM).GET /actuator/health→ health probe for platform health checks.- Binds to
$PORT(falls back to 8080).
mvn -q clean package -DskipTests # -> target/bench.jar
java -jar target/bench.jar # local run on :8080
# or, exactly how the platforms build it:
docker build -t bench . && docker run -p 8080:8080 -e PORT=8080 benchLocal baseline startup: ~4s (fast desktop). Expect more on constrained cloud plans.
Deploy this repo to each platform, then record the fields below. Measure identically.
- Railway — New Project → Deploy from GitHub repo → it detects the
Dockerfileand injects$PORT. Nearly one-click. - DigitalOcean — App Platform → create from GitHub repo → Dockerfile deploy (this is
the managed/PaaS experience, comparable to Railway). (Droplet +
docker runis the raw-VPS alternative — worth a note if you have time.) - Vultr — raw VPS: smallest Cloud Compute instance → install Docker →
docker build+docker run -p 80:8080 -e PORT=8080 bench. Most manual; time the steps.
| Field | How to get it |
|---|---|
deployMethod |
Dockerfile auto-detected? buildpack? manual? Any Java-specific friction. |
deployMinutes |
Wall-clock from "create" to a live URL responding (first deploy). |
redeploySeconds / redeployAutoOnPush |
Bump version.txt, git push, poll GET / until version changes = push-to-live time. Note whether it auto-deploys on push or needs a manual trigger. |
startingPricePerMonthUsd |
Cheapest plan that actually RUNS it. If the smallest OOMs, note it and size up — that's gold for "cheapest way to host a Java app". |
planRam / planCpu |
RAM + vCPU at that price (JVM is RAM-hungry — this is the story). |
springStartupSeconds |
From logs: Started BenchApplication in X seconds. |
coldStartMs |
If the plan scales-to-zero/sleeps: curl -w "%{time_total}" after idle. Else N/A. |
jvmDetectedMaxHeapMb / jvmDetectedProcessors |
jvmMaxMemoryMB and availableProcessors from GET /. Compare to the advertised RAM/vCPU — the gap ("plan says 0.5 GB / 1 vCPU, JVM sees ~700 MB / 2") is prime page material. |
freeTier |
Yes/No + limits (trial credit, sleep, hours). Can it run the JVM app? |
httpsIncluded |
Automatic HTTPS + custom domain? |
dxNotes |
Logs, rollbacks, CLI, dashboard, restart behaviour. |
gotchas |
OOM, build timeouts, port issues, anything that bit you. |
screenshots |
Dashboard, deploy logs, running /, pricing page. |
platform: railway
planName: # e.g. Free, Hobby ($5)
startingPricePerMonthUsd: # cheapest plan that actually RUNS the JVM
planRamMb: # advertised RAM
planVcpu: # advertised vCPU (e.g. 0.5, 1)
jvmDetectedMaxHeapMb: # jvmMaxMemoryMB from GET /
jvmDetectedProcessors: # availableProcessors from GET /
jvmIdleUsedMb: # jvmUsedMemoryMB from GET /
springStartupSeconds: # logs: "Started BenchApplication in X seconds"
coldStartMs: # or N/A if always-on
deployMinutes:
deployMethod: # Dockerfile / buildpack / manual
redeployAutoOnPush: # does git push auto-trigger a deploy?
redeploySeconds: # bump version.txt, push -> version changes in GET /
freeTier: # yes/no + limits
httpsIncluded:
dxNotes:
gotchas:
screenshots: # file names / links (page assets, not a data field)
measuredOn: 2026-07-08
Fill three of these (Railway, DigitalOcean, Vultr), hand them back, and they become
best-host-for-spring-boot.