The Hosting Decision Nobody Wants to Make
Heroku killed its free tier. AWS is a career. Vercel is great for frontends but awkward for long-running APIs.
For a Node.js API or full-stack app, three platforms stand out in 2025: Railway, Render, and Fly.io.
Railway
Best for: Fast deploys, full-stack apps, teams who want zero config.
npm install -g @railway/cli
railway login
railway init
railway up
That's a real deploy. Railway detects Node.js, builds it, runs it.
What it handles automatically:
- Detects runtime from
package.json - Sets up SSL
- Provisions PostgreSQL or Redis with one click
- Environment variables in the dashboard
- GitHub integration for auto-deploys
Pricing: $5/month per service (roughly). Usage-based, scales to zero when idle.
Limits: Not ideal for very high traffic without custom scaling.
Render
Best for: Teams that need predictable pricing and built-in cron jobs.
# render.yaml
services:
- type: web
name: my-api
env: node
buildCommand: npm ci && npm run build
startCommand: node dist/server.js
envVars:
- key: DATABASE_URL
fromDatabase:
name: my-postgres
property: connectionString
databases:
- name: my-postgres
databaseName: myapp
user: myapp
Deploy:
# Connect GitHub repo in Render dashboard
# Every push to main auto-deploys
Standout features:
- Native cron jobs (no external scheduler needed)
- Background workers as separate service type
- Preview environments on PR
- Managed PostgreSQL with daily backups
Pricing: $7/month for starter web service. Predictable (not usage-based).
Limits: Free tier spins down after 15 minutes of inactivity (cold start).
Fly.io
Best for: Low latency globally, Docker-based workloads, more control.
npm install -g flyctl
fly launch
fly deploy
fly launch detects Node.js, generates a Dockerfile, creates an app.
Dockerfile it generates:
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
RUN npm run build
CMD ["node", "dist/server.js"]
Standout features:
- Deploy in 30+ regions worldwide
- Machines scale to zero by default
- Persistent volumes for stateful apps
- WireGuard-based private networking between services
-
fly ssh consolefor direct machine access
Pricing: Pay for compute time. Free tier includes 3 shared-CPU VMs.
Limits: More configuration needed. Steeper learning curve.
Head-to-Head
| Feature | Railway | Render | Fly.io |
|---|---|---|---|
| Zero-config deploy | Best | Good | OK |
| Global edge | No | No | Yes |
| Managed Postgres | Yes | Yes | Managed (Neon integration) |
| Cron jobs | Add-on | Native | Via workers |
| Preview envs | Yes | Yes | Manual |
| Scale to zero | Yes | Yes (free) | Yes |
| Custom domains | Yes | Yes | Yes |
| Pricing model | Usage | Fixed | Usage |
| Complexity | Low | Low | Medium |
What to Choose
Choose Railway if:
- You want the fastest path from code to deployed
- Team collaboration is important
- You're building a full-stack app (frontend + API + DB)
Choose Render if:
- You want predictable monthly bills
- You need native cron jobs
- You want background workers as first-class citizens
Choose Fly.io if:
- Global low latency matters (multi-region)
- You're comfortable with Docker
- You need more infrastructure control
Common Configuration
# Health check endpoint (all platforms respect this)
app.get('/healthz', (req, res) => res.json({ status: 'ok' }));
# Port from environment (required by all platforms)
const port = process.env.PORT ?? 3000;
app.listen(port);
All three platforms inject PORT as an environment variable. Always use process.env.PORT, never hardcode.
For a new SaaS, start with Railway or Render. You can always migrate to Fly.io when you need global distribution.
Deploy scripts and platform configs for Railway, Render, and Fly.io included: Whoff Agents Ship Fast Skill Pack.
Top comments (0)