Kotlin on the server, and what it needs
Kotlin has quietly become a first-class backend language. Spring Boot with Kotlin, JetBrains' own Ktor, and Quarkus (with native compilation) cover everything from monoliths to lightweight microservices. The hosting considerations are mostly JVM considerations: heap sizing, JVM startup time, and — if you use GraalVM native image — a very different, fast-starting binary.
What matters for Kotlin/JVM
- Enough memory. A typical Spring Boot app wants 512MB–1GB+ to be comfortable; under-provisioning causes OOM kills.
- Startup time awareness. JVM cold starts are slow; scale-to-zero hurts unless you use native image.
- Container support. The JVM ecosystem ships great container tooling (Jib, buildpacks).
- GraalVM native option for fast-starting, low-memory binaries.
The options
| Platform | JVM-friendly | Native image | Managed DB | Notes |
|---|---|---|---|---|
| Render / Railway | Yes | Via Dockerfile | Some | Easy push-to-deploy |
| Fly.io | Yes | Via Dockerfile | Postgres | Edge VMs |
| AWS/GCP/Azure | Yes | Yes | Yes | Full control, more ops |
| Heroku | Yes (buildpack) | Limited | Add-ons | Classic JVM support |
| PandaStack | Yes | Via Dockerfile | Yes | GKE + auto-wired DB |
General PaaS and hyperscalers
Kotlin runs anywhere the JVM does, so the question is mostly developer experience and memory headroom. Render, Railway, and Fly all accept a Dockerfile or buildpack. Hyperscalers give full control at the cost of setup. Heroku's JVM buildpack is a long-standing, reliable path.
Where PandaStack fits
PandaStack deploys Kotlin via any Dockerfile or auto-detected buildpacks (the JVM is a well-supported buildpack target). Build happens in rootless BuildKit job pods; the image is deployed via Helm on GKE. The key practical advantages for JVM apps: pick a compute tier with enough memory, and attach a managed Postgres/MySQL with DATABASE_URL injected — ideal for Spring Data or Exposed.
# Spring Boot (Kotlin) layered image for fast rebuilds
FROM eclipse-temurin:21-jre AS run
WORKDIR /app
COPY build/libs/app.jar app.jar
ENV JAVA_OPTS="-XX:MaxRAMPercentage=75"
ENV PORT=8080
ENTRYPOINT ["sh","-c","java $JAVA_OPTS -jar app.jar"]Compute tiers go from Free (0.25 CPU / 512MB — fine for a small Ktor app, tight for full Spring Boot) up through memory-optimized m1/m2 tiers and compute-optimized c1/c2, to C2-2XCompute (8 CPU / 16GB). For Spring Boot, choose a memory-optimized tier or a higher standard tier.
Honest guidance on scale-to-zero: our free tier uses KEDA scale-to-zero on spot nodes, and JVM cold starts are slow — a Spring Boot app can take many seconds to boot. For production Kotlin, run a warm instance on a paid tier, or compile to a GraalVM native image (which starts in milliseconds and uses far less memory) and deploy that binary. If you go native with Quarkus or Spring Native, free-tier scale-to-zero becomes much more viable.
Tip: shrink the JVM footprint
# Use MMaxRAMPercentage so the JVM respects container limits
java -XX:MaxRAMPercentage=75 -jar app.jar
# Or go native with Quarkus for ~tens-of-MB RSS and ms startup
./mvnw package -DnativeDecision guide
- Small Ktor service → any PaaS; PandaStack free tier works.
- Spring Boot in production → memory-optimized tier with a warm instance.
- Want scale-to-zero to actually help → GraalVM native image (Quarkus/Spring Native).
References
- Ktor docs: https://ktor.io/docs/
- Spring Boot: https://docs.spring.io/spring-boot/index.html
- Quarkus: https://quarkus.io/guides/
- GraalVM native image: https://www.graalvm.org/latest/reference-manual/native-image/
- Cloud Native Buildpacks: https://buildpacks.io/
---
Deploying a Kotlin backend? PandaStack builds your JAR or native image and wires in a managed database automatically. Pick a memory tier and ship — free tier at https://dashboard.pandastack.io