Skip to main content

Deploy Apps on RailPush

RailPush deploys web apps, APIs, workers, cron jobs, static sites, and Docker images from one control plane. Connect a GitHub repo, push to the RailPush remote, paste a Docker image, or use a Deploy to RailPush button.

Every deploy gets a build log, health check, rollout state, deploy history, rollback path, and a live HTTPS URL.

Pick a deploy path

PathBest forWhat RailPush handles
GitHub importApps that already live in GitHubRepo connection, framework detection, build command, start command, auto deploys
Git pushHeroku-style terminal deploysGit Smart HTTP remote, build trigger, deploy status in terminal output
DockerfileCustom runtimes and monoreposDocker build context, Dockerfile path, command override, health checks
Prebuilt imageExisting CI pipelinesPulling the image, setting ports/env vars, rolling out the service
Static siteSPAs and docs sitesBuild output hosting, nginx, TLS, cache headers
Deploy buttonPublic templates and examplesOne-click repo import with optional branch and service name

Quick start from GitHub

  1. Sign in to RailPush and click New -> Web Service.
  2. Pick a GitHub repository and branch.
  3. Review the detected framework, build command, start command, and port.
  4. Add required environment variables such as DATABASE_URL, SENTRY_DSN, DISCORD_BOT_TOKEN, or provider API keys.
  5. Create the service. RailPush builds, deploys, health-checks, and gives you a live URL.
Deploy again later
git push origin main

If auto deploy is enabled, the push starts a new deployment. You can also trigger deploys from the dashboard, REST API, CLI, or MCP tools.

Heroku to RailPush mapping

Heroku conceptRailPush equivalent
DynoService
Worker dynoWorker service
Heroku PostgresManaged PostgreSQL
Heroku RedisManaged Redis
Config varsService environment variables
Procfile web processStart command
git push heroku maingit push railpush main
Add-onsManaged databases, object storage, queues, log drains, and alerts

For a practical migration, start with Git Push Deploys, move config vars with Environment Variables, then provision PostgreSQL or Redis as needed.

Deploy configuration

RailPush can infer most settings, but explicit configuration keeps migrations predictable:

railpush.yaml
services:
- type: web
name: api
repo: https://github.com/acme/api
branch: main
buildCommand: npm ci && npm run build
startCommand: npm start
port: 3000
healthCheckPath: /health
plan: s
envVars:
- key: NODE_ENV
value: production
- key: DATABASE_URL
value: ${{ databases.api-db.internal_url }}
is_secret: true

The same settings can be managed from the dashboard, API, CLI, or MCP server.

Slow cold starts and rollout timeout

After a build, RailPush waits for the new pod to pass its health check before marking the deploy live. If the pod is not ready within the rollout timeout (5 minutes by default), the deploy fails and RailPush auto-rolls-back to the last good image.

Apps with a slow cold start — large dependency/module graphs, JIT or cache warmup, or a first-pull of a big image onto a cold node — can legitimately need longer. Raise the budget with a service environment variable and redeploy:

Env varDefaultBoundsEffect
RAILPUSH_ROLLOUT_TIMEOUT_SECONDS300601800How long the rollout waits for the new pod to become ready before failing and rolling back. The startup-probe budget and the Kubernetes progress deadline are scaled up automatically to match, so this single knob is usually all you need.
RAILPUSH_STARTUP_FAILURE_THRESHOLD601600Number of consecutive startup-probe failures tolerated before the container is restarted. Effective startup budget = this × interval. Set only if you want a startup budget larger than the rollout timeout implies.
RAILPUSH_STARTUP_INTERVAL_SECONDS51300Seconds between startup-probe attempts.

For example, to give a service a 12-minute cold-start window, set RAILPUSH_ROLLOUT_TIMEOUT_SECONDS=720 and redeploy.

tip

The fastest durable fix is usually to start listening on your port early — bind the HTTP server before running migrations or other startup work, and do that work asynchronously. A health check that returns 200 as soon as the port is open lets the rollout succeed while initialization continues in the background.

Long-lived connections and graceful shutdown

A deploy is marked live as soon as the new pod is Ready — it does not wait for the old pod to finish shutting down. Old pods drain in the background up to the service's Max Shutdown Delay (terminationGracePeriodSeconds), which is configured per-service and is independent of RAILPUSH_ROLLOUT_TIMEOUT_SECONDS. The rollout timeout does not change the shutdown grace.

If your app holds long-lived connections (SSE, WebSockets, streaming responses), raise Max Shutdown Delay so the old pod can close them cleanly on SIGTERM. Because the rollout completes on the new pod's readiness, a large shutdown delay no longer slows down or fails deploys.

Services with a persistent disk

A persistent disk is single-writer (ReadWriteOnce) — it can only be attached to one running pod at a time. Services with a disk therefore deploy with the Recreate strategy: the old pod is fully stopped (releasing the disk) before the new pod starts. This means a brief gap in availability during each deploy, which is unavoidable for a single-writer volume. Services without a disk keep the default zero-downtime rolling strategy.