Deploy spring-boot-railway-template

The Java starter that deploys: Spring Boot 4.1 + Postgres in one click

Deploy spring-boot-railway-template

/var/lib/postgresql/data

Spring Boot on Railway — the Java starter that actually deploys

Deploy on Railway

One click gives you a production-shaped Spring Boot 4.1 (Java 25 LTS) application wired to a PostgreSQL 18 database — with schema migrations, a real REST API, and a healthcheck that goes green on the first deploy. No port errors, no out-of-memory crashes, no version surprises: every classic Railway-Java failure mode is already handled in this template.

What's inside

ServiceWhat it runs
appSpring Boot 4.1.1 on Java 25 (Eclipse Temurin), built by a multi-stage Dockerfile (maven:3.9-eclipse-temurin-25eclipse-temurin:25-jre)
PostgresRailway's official postgres-ssl:18 image with a persistent volume

The app service ships a working reference application, not a hello-world stub:

  • REST API for a todo list (GET/POST/PATCH/DELETE /api/todos) on Spring Data JPA
  • Flyway migration (V1__init.sql) that creates the schema on first boot
  • Spring Boot Actuator with /actuator/health wired as Railway's healthcheck
  • Graceful shutdown so redeploys don't drop in-flight requests

Everything is pinned: Java 25 LTS in both Docker stages, Spring Boot 4.1.1 in pom.xml, the Postgres 18 image tag. Nothing floats, so a deploy that works today works next month.

Railway wiring (done for you)

  • SERVER_PORT = ${{PORT}} binds the JVM to Railway's injected port; the app falls back gracefully (server.port=${SERVER_PORT:${PORT:8080}} in application.properties).
  • JVM memory flags in the Dockerfile entrypoint: -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError — the heap scales with the container and never fights the OOM killer.
  • Healthcheck: /actuator/health, 300 s timeout, restart-on-failure (×10).
  • Database credentials are auto-generated and injected via variable references — SPRING_DATASOURCE_URL=jdbc:postgresql://${{Postgres.PGHOST}}:${{Postgres.PGPORT}}/${{Postgres.PGDATABASE}}, SPRING_DATASOURCE_USERNAME=${{Postgres.PGUSER}}, SPRING_DATASOURCE_PASSWORD=${{Postgres.PGPASSWORD}}. Zero hardcoded secrets.

Deploy and Host

About Hosting

Deploying provisions two services: the Spring Boot app (built from the linked GitHub repo with Docker) and a Postgres database with persistent storage. The first build runs a full Maven build, so expect roughly 3–5 minutes before the healthcheck goes green; subsequent deploys are faster thanks to Docker layer caching. Hosting cost scales with usage — a typical small instance runs the JVM at 0.5–1 GB of RAM, which lands around $5–10/month including the Postgres service. After deploy, Railway assigns a public domain; open it to see the app metadata JSON, then try curl https://YOUR-DOMAIN/api/todos.

Why Deploy

Because every other path to Java on Railway tends to fail in one of four ways, and this template fixes all four before you click:

  1. Port mismatch — Spring defaults to 8080 while Railway expects the app to listen on its injected PORT. This template binds SERVER_PORT to ${{PORT}} and the domain targets it.
  2. OOM kills — a JVM with default heap settings on a small container gets killed by the kernel. MaxRAMPercentage=75 keeps the heap inside the container.
  3. Failed healthchecks — Railway needs an endpoint that actually reports readiness. Actuator's /actuator/health is wired as the deploy gate.
  4. Stale versions — the old Spring Boot templates on Railway pin Boot 3.3.x and a single-stage alpine build. This one pins the current GA line (Boot 4.1.1) and the current LTS (Java 25) in a cached multi-stage build.

You also get a database that's actually wired: Flyway migrates on boot, and data survives redeploys because it lives in Postgres, not in the container.

Common Use Cases

  • A real starting point for a Spring Boot service on Railway — swap the todo package for your own entities and controllers, keep the wiring, push to deploy.
  • REST API backends for web and mobile apps, with validated inputs and a migrated schema.
  • Enterprise-style reference architecture — JPA + Flyway + actuator is the layout most Java teams already know; use it as a template for internal services.
  • Learning Spring Boot — the repo has a README with local-dev instructions, a test suite that runs without a database, and CI (GitHub Actions) building on every push.

Dependencies for

Deployment Dependencies

  • A Railway account (the deploy button handles project creation).
  • The GitHub repository lNamelessl/spring-boot-railway-template — public, MIT-licensed; the app service builds from it.
  • The Postgres service is provisioned by the template itself (official postgres-ssl:18 image); no external database is needed.
  • No deploy-form inputs: all variables are pre-wired references, database credentials are generated per deployment, and there is nothing to type.

Troubleshooting

  • Healthcheck fails on first deploy — the first build is the slow one; check the deploy logs for Started …Application. If the app started but the check still fails, confirm the domain's target port matches SERVER_PORT (8080 by default).
  • Connection refused to Postgres at boot — the app can start before Postgres finishes booting on the very first deploy. The template sets a 60 s connection-patient Hikari timeout and restarts on failure, so it self-heals; press Redeploy once if you're impatient.
  • Killed / exit 137 — the JVM outgrew the container. Lower the heap via a JAVA_OPTS service variable or add memory in the service settings.
  • Build timeout — free-plan builds can time out during the first dependency download. Redeploy: Docker layer caching resumes where the build left off.
  • Flyway errors after you change the schema — never edit an applied migration; add a new V{n}__*.sql file instead.

Bring your own app

Fork the repo, replace the todo package with your own code, add your migrations as V2__…, V3__…, and keep four things untouched: the port line in application.properties, the healthcheck lines, the Dockerfile, and railway.json. Push to main — Railway redeploys automatically.


Template Content

More templates in this category

View Template
open-excalidraw
Self-hostable collaborative drawing built on Excalidraw

Prateek Mohanty
3
View Template
caring-vibrancy
Deploy and Host caring-vibrancy with Railway

5
View Template
Appsmith
Low-code platform for internal tools, dashboards, and admin panels.

Agaz Self-Host
0