Module 7: Alternative Platforms (Render, Railway, Fly.io)

5. Platform Comparison: Render vs Railway vs Fly.io

Description

In this capsule you'll put the three platforms side by side with concrete data. You've deployed your AI app on Render (capsule 02), Railway (capsule 03) and Fly.io (capsule 04). Now it's time to compare in a structured way: real pricing, free tier limits, features, limitations for AI workloads, database support, auto-scaling, deploy times, and developer experience. The tables in this capsule are the ones you consult when you need to choose a platform for a project.

Why it matters: Generic online comparisons say "all three are good." That doesn't help you. You need to know: which has the longer timeout for AI? Which supports WebSockets for streaming? Which is cheaper for an MVP running 24/7? Which scales to multi-region without complex configuration? This capsule answers with numbers, not opinions.


General Feature Comparison

Core Features

FeatureRenderRailwayFly.io
Deploy from Git✅ GitHub, GitLab✅ GitHub❌ CLI/API only
Deploy from CLI❌ No official CLIrailway upflyctl deploy
Deploy from Docker✅ Dockerfile✅ Dockerfile + Nixpacks✅ Dockerfile
Auto-deploy on push✅ Native✅ Native⚠️ Via GitHub Actions
Preview environments⚠️ Manual (PR previews in beta)✅ Native, automatic⚠️ Manual with the Machines API
Custom domains✅ Free (Starter+)✅ Hobby+✅ Free
Automatic SSL✅ Let's Encrypt✅ Let's Encrypt✅ Let's Encrypt
Health checks✅ Configurable✅ Configurable✅ Configurable
Logs✅ Dashboard + API✅ Dashboard + CLI✅ Dashboard + CLI
Metrics✅ CPU, RAM, requests✅ CPU, RAM, network✅ CPU, RAM, network
Teams/collaboration✅ Team plan✅ Pro plan✅ Organizations

Infrastructure

FeatureRenderRailwayFly.io
Available regions4 (Oregon, Ohio, Frankfurt, Singapore)1+ (auto-selected)30+ regions
Multi-region❌ One region per service❌ One region per service✅ Native
Horizontal auto-scaling✅ Standard+ (manual)✅ Pro (automatic)✅ Native (auto_start/stop)
Vertical auto-scaling❌ Fixed plan⚠️ Dynamic within limits❌ Fixed VM
Container typeDocker containerDocker/Nixpacks containerFirecracker micro-VM
SSH to containerflyctl ssh console
Private networking✅ Between project services✅ Between project services✅ WireGuard + private IPv6

Databases and Add-ons

Add-onRenderRailwayFly.io
PostgreSQL✅ Managed✅ Managed (plugin)✅ Managed (Fly Postgres)
Redis✅ Managed✅ Managed (plugin)✅ Via Upstash (managed)
MySQL✅ Managed (plugin)❌ (deploy your own)
MongoDB✅ Managed (plugin)❌ (deploy your own)
Object Storage❌ (use S3)❌ (use S3)✅ Tigris (S3-compatible)
Cron Jobs✅ Native✅ Native⚠️ Via the Machines API
Background Workers✅ Native✅ Native✅ Native
Persistent Disk✅ Render Disk ($0.25/GB)✅ Volumes✅ Volumes ($0.15/GB)

Pricing Comparison

Free Tiers

DimensionRender FreeRailway TrialFly.io Free
Cost$0$0 (+ $5 credit)$0
Web services1 service, 15 min sleepUntil $5 is used up3 shared VMs
RAM512 MBVariable (by usage)256 MB per VM
CPU0.1 vCPUVariableshared-cpu-1x
PostgreSQL256 MB, 97-day retentionIncluded in creditNot included free
Redis25 MB, 97-day retentionIncluded in creditNot included free
Custom domains
DurationIndefinite (with sleep)Until credit is used upIndefinite
Credit cardNot requiredNot requiredRequired (verification)

Paid Plans — Comparison for a Typical AI App

Scenario: FastAPI + OpenAI API, 1 vCPU, 1 GB RAM, running 24/7:

ComponentRender StarterRailway HobbyFly.io (shared)
Monthly base$7/month (fixed plan)$5/month (+ credit)$0 (free tier VMs)
ComputeIncluded in plan~$20/month (vCPU) + ~$10/month (RAM)$1.94/month (VM) + ~$6/month (extra RAM)
PostgreSQL$7/month (Starter)Included in usage$1.94/month (Postgres VM)
Redis$7/month (Starter)Included in usage$0 (Upstash free tier)
EgressIncluded$0.10/GB after 100 GB$0.02/GB after 100 GB
Estimated total~$21/month~$25-30/month~$10-15/month

Pricing at larger scale

Scenario: 2 vCPU, 4 GB RAM, PostgreSQL, Redis, running 24/7:

ComponentRender ProRailway ProFly.io Dedicated
Compute$85/month~$60/month~$37/month
PostgreSQL$20/month (Standard)Included~$15/month
Redis$20/month (Standard)Included~$5/month
Estimated total~$125/month~$80-90/month~$57/month

Pricing: Billing model

AspectRenderRailwayFly.io
ModelFixed plan per servicePay-per-use (CPU×time + RAM×time)Pay-per-use (VM×time + RAM)
Predictability✅ High — you know the exact cost⚠️ Medium — depends on usage⚠️ Medium — depends on active VMs
OverageNone — capped at the planCharged by usageCharged by usage
BillingMonthlyMonthlyMonthly

Comparison: Limitations for AI Workloads

Request Timeouts

PlatformHTTP TimeoutAI impact
Render30 seconds⚠️ Limiting for long inference. Streaming mandatory for responses > 30s
Railway5 minutes✅ Enough for most AI workloads
Fly.ioConfigurable (default 60s)✅ Adjustable as needed

Memory Limits

PlatformFreeMinimum paidMaximum
Render512 MB512 MB (Starter)8 GB (Pro Plus)
RailwayVariable (~512 MB)Configurable32 GB (Pro)
Fly.io256 MB256 MB (shared)16 GB+ (dedicated)

WebSocket and Streaming

FeatureRenderRailwayFly.io
WebSocket⚠️ Starter+ (not on Free)✅ Supported✅ Supported
Server-Sent Events (SSE)✅ Supported✅ Supported✅ Supported
LLM token streaming⚠️ SSE works, WS limited✅ Full support✅ Full support

Cold Start

PlatformWith sleep enabledWithout sleep
Render Free15,000-45,000msN/A (always sleeps)
Render StarterN/A (always running)0ms
Railway (sleep)2,000-8,000ms0ms
Fly.io (auto-stop)300-2,000ms0ms
Fly.io (min=1)N/A (always running)0ms

Container Size and Build

AspectRenderRailwayFly.io
Max image sizeNo documented limitNo documented limit10 GB
Build timeout30 minutes30 minutesNot documented (long)
Build cache✅ Docker layer cache✅ Nixpacks cache (aggressive)✅ Docker layer cache
Build speedMediumFast (Nixpacks)Medium

Comparison: Developer Experience

Setup Time (first time)

StepRenderRailwayFly.io
Create account1 min (GitHub OAuth)1 min (GitHub OAuth)2 min (email + card)
First deploy3-5 min (dashboard)2-3 min (CLI)5-7 min (CLI + config)
Custom domain5 min3 min5 min
Total setup~10 min~6 min~12 min

Daily workflow

ActionRenderRailwayFly.io
Deploygit push (auto)git push or railway upflyctl deploy
View logsDashboard → Logsrailway logs or Dashboardflyctl logs or Dashboard
Add a variableDashboard → Envrailway variables setflyctl secrets set
Add a databaseDashboard → New → PostgreSQLrailway addflyctl postgres create
ScaleDashboard → SettingsDashboard → Settingsflyctl scale count N
SSH to the containerflyctl ssh console
Connect to DB locally❌ (copy URL manually)railway connect postgresflyctl postgres connect

CLI Power

CapabilityRenderRailwayFly.io
Official CLI❌ (REST API only)✅ Complete✅ Complete
Deploy from terminalrailway upflyctl deploy
Variables from terminalrailway variablesflyctl secrets
Logs from terminalrailway logsflyctl logs
DB connect from terminalrailway connectflyctl postgres connect

Comparison: When to Choose Each One

Quick-Reference Decision

Do you want absolute simplicity + predictable pricing?
    → Render

Do you want the best developer experience + fast prototypes?
    → Railway

Do you need multi-region or low global latency?
    → Fly.io

Do you have a team and need preview environments?
    → Railway

Minimal budget and you don't mind cold start?
    → Fly.io (most generous free tier on CPU)

AI app with token streaming?
    → Railway or Fly.io (better WebSocket support)

Enterprise, compliance, guaranteed SLA?
    → None of the three — use AWS

Concrete scenarios for AI

ScenarioBest optionWhy
MVP AI chatbot, 1 developerRailwayFastest deploy, excellent CLI
Inference API, team of 3RailwayPreview environments, add-ons
RAG app for a global companyFly.ioMulti-region, low latency
Demo for investorsRenderPredictable, easy to explain
Personal project, $0/monthFly.ioMost generous free tier (3 VMs)
App with long streamingFly.ioConfigurable timeout, native WS
Early-stage startup, $50/month budgetRailwayGood DX/price ratio
AI app + PostgreSQL + RedisRailwayIntegrated add-ons, automatic variables
Need to self-host an LLMNoneYou need a GPU → RunPod, Lambda Labs

Summary Table: The Big Picture

DimensionRenderRailwayFly.ioAWS (Lambda)
PhilosophySimplicityDeveloper ExperienceEdge ComputingFull control
Deploy time3-5 min2-3 min5-7 min30-60 min
Free tierLimited (sleep)$5 credit3 free VMs1M requests/month
Pricing modelFixed planPay-per-usePay-per-usePay-per-use
Cost $$ (AI app)~$21/month~$25-30/month~$10-15/month~$15-40/month
Multi-region✅ (with config)
Request timeout30s5 minConfigurable15 min
WebSocketStarter+⚠️ (API GW)
Cold start15-45s (free)2-8s0.3-2s1-10s
CLI✅✅✅✅✅ (aws cli)
DatabasesPG, RedisPG, Redis, MySQL, MongoPG, RedisRDS, ElastiCache
ComplexityLowLowMediumHigh
Vendor lock-inLowLowMediumHigh
GPU✅ (SageMaker)

Hands-On Exercises

Exercise 1: Personalized evaluation matrix

Create an evaluation table for YOUR specific use case. Define 5 criteria with weights and rate each platform from 1 to 5.

See solution
# platform_evaluation.py

criteria = {
    "Monthly cost": 25,
    "Developer experience": 20,
    "Deploy time": 15,
    "AI support (timeout, RAM)": 20,
    "Future scalability": 20,
}

scores = {
    "Render": {
        "Monthly cost": (3, "$21/month — predictable but not the cheapest"),
        "Developer experience": (3, "Simple dashboard, no CLI"),
        "Deploy time": (4, "Git push → auto deploy"),
        "AI support (timeout, RAM)": (2, "30s timeout is limiting"),
        "Future scalability": (3, "Horizontal scaling, but single region"),
    },
    "Railway": {
        "Monthly cost": (3, "$25-30/month — flexible but less predictable"),
        "Developer experience": (5, "Excellent CLI, preview envs, add-ons"),
        "Deploy time": (5, "railway up — the fastest"),
        "AI support (timeout, RAM)": (4, "5 min timeout, up to 32 GB RAM"),
        "Future scalability": (3, "Auto-scaling, but single region"),
    },
    "Fly.io": {
        "Monthly cost": (4, "$10-15/month — the cheapest"),
        "Developer experience": (3, "Powerful CLI but more initial setup"),
        "Deploy time": (3, "flyctl deploy — medium"),
        "AI support (timeout, RAM)": (4, "Configurable timeout, native WS"),
        "Future scalability": (5, "Native multi-region, edge"),
    },
}

print("=== Platform Evaluation ===\n")
print(f"{'Criterion':<30} {'Weight':>4}  {'Render':>8} {'Railway':>8} {'Fly.io':>8}")
print("-" * 70)

totals = {"Render": 0, "Railway": 0, "Fly.io": 0}

for criterion, weight in criteria.items():
    print(f"{criterion:<30} {weight:>4}", end="")
    for platform in ["Render", "Railway", "Fly.io"]:
        score, _ = scores[platform][criterion]
        weighted = weight * score
        totals[platform] += weighted
        print(f"  {weighted:>6}", end="")
    print()

print("-" * 70)
print(f"{'TOTAL':<30} {sum(criteria.values()):>4}", end="")
for platform in ["Render", "Railway", "Fly.io"]:
    print(f"  {totals[platform]:>6}", end="")
print()

max_possible = sum(criteria.values()) * 5
print(f"\nMaximum possible: {max_possible}")
winner = max(totals, key=totals.get)
print(f"Winner: {winner} ({totals[winner]}/{max_possible})")

Exercise 2: Comparative latency benchmark

Run a benchmark that measures the health check and inference latency on all three platforms simultaneously.

See solution
# benchmark_platforms.py
import time
import requests
import statistics
from concurrent.futures import ThreadPoolExecutor

PLATFORMS = {
    "Render": "https://docusearch-ai.onrender.com",
    "Railway": "https://docusearch-ai-production.up.railway.app",
    "Fly.io": "https://docusearch-ai-fly.fly.dev",
}

NUM_REQUESTS = 10


def measure_endpoint(platform: str, url: str, endpoint: str, payload=None) -> list:
    latencies = []
    for _ in range(NUM_REQUESTS):
        start = time.time()
        try:
            if payload:
                resp = requests.post(f"{url}{endpoint}", json=payload, timeout=30)
            else:
                resp = requests.get(f"{url}{endpoint}", timeout=30)
            elapsed = (time.time() - start) * 1000
            if resp.status_code == 200:
                latencies.append(elapsed)
        except Exception:
            latencies.append(30000)
        time.sleep(0.5)
    return latencies


print("=== Health Check Latency ===\n")
print(f"{'Platform':<12} {'Avg':>8} {'Median':>8} {'P95':>8} {'Min':>8} {'Max':>8}")
print("-" * 56)

for platform, url in PLATFORMS.items():
    lats = measure_endpoint(platform, url, "/health")
    if lats:
        avg = statistics.mean(lats)
        med = statistics.median(lats)
        p95 = sorted(lats)[int(len(lats) * 0.95)]
        print(f"{platform:<12} {avg:>7.0f}ms {med:>7.0f}ms {p95:>7.0f}ms "
              f"{min(lats):>7.0f}ms {max(lats):>7.0f}ms")

print("\n=== Inference Latency ===\n")
print(f"{'Platform':<12} {'Avg':>8} {'Median':>8} {'P95':>8}")
print("-" * 40)

payload = {"question": "What is Python?", "max_tokens": 50}
for platform, url in PLATFORMS.items():
    lats = measure_endpoint(platform, url, "/ask", payload)
    if lats:
        avg = statistics.mean(lats)
        med = statistics.median(lats)
        p95 = sorted(lats)[int(len(lats) * 0.95)]
        print(f"{platform:<12} {avg:>7.0f}ms {med:>7.0f}ms {p95:>7.0f}ms")

Exercise 3: 6-month cost calculation

Calculate the total cost of each platform for your AI app over 6 months, including compute, databases, and LLM APIs.

See solution
# cost_projection.py
MONTHS = 6

app_config = {
    "daily_requests": 3000,
    "avg_openai_cost_per_request": 0.002,
    "needs_postgresql": True,
    "needs_redis": True,
    "ram_gb": 1,
}


def render_cost(config: dict) -> dict:
    monthly = {
        "compute": 7,       # Starter plan
        "postgresql": 7,    # Starter plan
        "redis": 7,         # Starter plan
        "openai_api": config["daily_requests"] * 30 * config["avg_openai_cost_per_request"],
    }
    monthly["total"] = sum(monthly.values())
    return {k: round(v, 2) for k, v in monthly.items()}


def railway_cost(config: dict) -> dict:
    hours_per_month = 730
    vcpu_cost = 0.02778 * hours_per_month
    ram_cost = config["ram_gb"] * 0.01388 * hours_per_month
    hobby_base = 5
    hobby_credit = 5
    compute_net = max(0, vcpu_cost + ram_cost - hobby_credit)

    monthly = {
        "base": hobby_base,
        "compute": round(compute_net, 2),
        "postgresql": 0,    # Included in usage
        "redis": 0,         # Included in usage
        "openai_api": config["daily_requests"] * 30 * config["avg_openai_cost_per_request"],
    }
    monthly["total"] = sum(monthly.values())
    return {k: round(v, 2) for k, v in monthly.items()}


def flyio_cost(config: dict) -> dict:
    monthly = {
        "compute_vm": 1.94,                      # shared-cpu-1x (free if <3 VMs)
        "ram_extra": max(0, (config["ram_gb"] - 0.256)) * 6,
        "postgresql": 1.94,                       # Fly Postgres VM
        "redis": 0,                               # Upstash free tier
        "volume": 0.15,                           # 1 GB
        "openai_api": config["daily_requests"] * 30 * config["avg_openai_cost_per_request"],
    }
    monthly["total"] = sum(monthly.values())
    return {k: round(v, 2) for k, v in monthly.items()}


print(f"=== {MONTHS}-Month Cost Projection ===\n")

for name, calc_fn in [("Render", render_cost), ("Railway", railway_cost), ("Fly.io", flyio_cost)]:
    monthly = calc_fn(app_config)
    print(f"--- {name} ---")
    for k, v in monthly.items():
        if k != "total":
            print(f"  {k:<20} ${v:.2f}/month")
    print(f"  {'TOTAL monthly':<20} ${monthly['total']:.2f}/month")
    print(f"  {'TOTAL ' + str(MONTHS) + ' months':<20} ${monthly['total'] * MONTHS:.2f}")
    print()
## Typical output

--- Render ---
  compute              $7.00/month
  postgresql           $7.00/month
  redis                $7.00/month
  openai_api           $180.00/month
  TOTAL monthly        $201.00/month
  TOTAL 6 months       $1206.00

--- Railway ---
  base                 $5.00/month
  compute              $25.41/month
  openai_api           $180.00/month
  TOTAL monthly        $210.41/month
  TOTAL 6 months       $1262.46

--- Fly.io ---
  compute_vm           $1.94/month
  ram_extra            $4.46/month
  postgresql           $1.94/month
  volume               $0.15/month
  openai_api           $180.00/month
  TOTAL monthly        $188.49/month
  TOTAL 6 months       $1130.94

Note: The OpenAI API cost dominates in every case.
The difference between platforms (~$20/month) is marginal
compared to $180/month of API cost.

Exercise 4: Document limitations for your specific case

For each platform, document the 3 most impactful limitations for YOUR specific AI app and the workarounds you'd use.

See solution
# Limitations for DocuSearch AI (RAG + GPT-4o-mini)

## Render
1. **30s timeout:** My /ask endpoint usually takes ~2-3s, but complex
   queries with a lot of RAG context can take 10-15s. If I add
   streaming, I could easily hit 30s.
   → Workaround: Implement mandatory SSE streaming for /ask

2. **No CLI:** For quick hotfixes, I need to go to the dashboard.
   Deploy is via git push, which is fine, but managing variables
   and viewing logs requires the browser.
   → Workaround: Use the Render API with curl/scripts

3. **PostgreSQL Free: 97 days.** If I use the free tier for development,
   I lose data every ~3 months.
   → Workaround: Starter ($7/month) or export data periodically

## Railway
1. **Unpredictable pricing:** With 3K requests/day, the cost varies by
   CPU usage. A traffic spike = an unexpected bill.
   → Workaround: Configure resource limits and billing alerts

2. **Single region:** My users are in Latin America. Railway doesn't
   let me choose a nearby region (São Paulo not directly available).
   → Workaround: Accept the extra latency or use Fly.io for those users

3. **Trial $5 lasts a short time:** For testing, the $5 runs out in ~5-7 days
   with the app running. I need Hobby ($5/month) from day 1.
   → Workaround: Immediate upgrade to Hobby

## Fly.io
1. **Region-locked volumes:** If I scale to multi-region, each region needs
   its own volume. I can't share cache across regions.
   → Workaround: Use Redis (Upstash) for shared cache, volumes only
     for local data

2. **More initial setup:** flyctl launch + fly.toml + secrets + deploy is
   more steps than railway up.
   → Workaround: Script the setup in a Makefile

3. **Variable shared CPU:** On shared, CPU performance fluctuates.
   Embedding generation can be slow during peak hours.
   → Workaround: Pre-generate embeddings offline, use dedicated CPU ($31/month)
     if performance is critical

Troubleshooting

Problem 1: "Which is the cheapest for my case?"

Solution: It depends on the usage pattern. For a 24/7 app with 1 GB RAM:

  • If you want predictability: Render ($21/month with PG + Redis)
  • If you want the absolute minimum: Fly.io (~$10/month)
  • If you want a DX/cost balance: Railway (~$25/month)

In every case, the LLM API cost (OpenAI) dominates the bill. The difference between platforms is marginal.

Problem 2: "My app needs streaming and Render's timeout isn't enough"

Solution: Use SSE (Server-Sent Events) on Render — SSE timeouts are different from normal HTTP requests. Alternative: switch to Railway (5 min timeout) or Fly.io (configurable).

Problem 3: "I need PostgreSQL with pgvector for embeddings"

Solution:

  • Render: pgvector available on Standard+ plan ($20/month)
  • Railway: pgvector available with the PostgreSQL plugin
  • Fly.io: Fly Postgres supports pgvector (you need to configure the extension)
  • Alternative: Use a dedicated vector service (Pinecone, Qdrant Cloud)

Problem 4: "Is there vendor lock-in?"

Solution: Minimal in all three. Your app is a Docker container — it works on any platform that runs containers. What "ties" you are:

  • Render: render.yaml (easy to replace)
  • Railway: railway.toml (minimal)
  • Fly.io: fly.toml + volumes + multi-region config (more lock-in)

Migration between platforms is trivial: change the config file + redirect DNS.


Summary

  • Render = Simplicity + predictable pricing. Ideal for demos and MVPs where you don't want surprises. Limited by the 30s timeout.
  • Railway = Best DX + fast prototypes. Ideal for developers who live in the terminal. Less predictable pricing.
  • Fly.io = Edge + multi-region + lower cost. Ideal for global apps or a tight budget. More initial setup.
  • For AI workloads: Render's timeout (30s) is the most impactful limitation. Railway (5 min) and Fly.io (configurable) are more permissive.
  • The LLM API cost dominates. The difference between platforms (~$10-20/month) is irrelevant next to the OpenAI cost ($100-500/month).
  • None has a GPU. For local inference of large models, you need specialized services.
  • Vendor lock-in is low in all three: your app is a portable Docker container.
  • There's no universal "best" — there's a best for YOUR case, YOUR constraints, YOUR stage.

Additional Resources

  1. Render Pricing — Render's updated pricing
  2. Railway Pricing — Railway's pricing calculator
  3. Fly.io Pricing — Fly.io's detailed pricing
  4. PaaS Comparison 2026 — Dev.to — Community comparisons
  5. Cloud Cost Handbook — Vantage — General reference for cloud costs
  6. OpenAI Pricing — To contextualize the real cost of your AI system