DevOps & Cloud

Railway: Platform App Hosting Modern

TOKEN

Panduan lengkap Railway.app — deploy aplikasi dari Git repo, managed databases, environment variables, auto-scaling, templates, Dockerfiles, dan best practices

1. Pengenalan Railway

Railway adalah Platform as a Service (PaaS) modern yang memungkinkan developer meng-deploy aplikasi, databases, dan infrastruktur lengkap dengan cara yang sangat sederhana. Dikenal karena developer experience (DX) yang luar biasa — Railway menghilangkan kompleksitas DevOps dan membiarkan developer fokus pada kode.

Railway mendukung hampir semua bahasa dan framework — Node.js, Python, Go, Rust, Java, Ruby, PHP, Elixir, dan lainnya. Platform ini mendeteksi bahasa secara otomatis dari repository dan melakukan build yang sesuai. Yang membuat Railway berbeda dari PaaS lainnya adalah kemampuannya untuk men-deploy tidak hanya aplikasi tetapi juga databases dan infrastructure services dalam satu project yang terintegrasi.

Mengapa Railway?

Keunggulan Penjelasan
Zero Config DeployPush ke Git, Railway auto-detect bahasa dan build
Integrated DatabasesPostgreSQL, MySQL, Redis, MongoDB — satu klik untuk deploy
Private NetworkingServices berkomunikasi via private network tanpa exposed ports
Instant RollbackRollback ke deployment sebelumnya dalam satu klik
TemplatesDeploy stack lengkap (app + DB + cache) dari template siap pakai
CLI PowerfulRailway CLI untuk deploy, logs, variables, dan manage dari terminal
Monorepo SupportDeploy multiple services dari satu monorepo
ScalingHorizontal dan vertical scaling dengan mudah
ObservabilityLogs, metrics, dan monitoring built-in
Diagram: Railway Platform Architecture
┌──────────────────────────────────────────────────────────────┐
│                    RAILWAY PROJECT                            │
│                                                               │
│  ┌──────────────────────────────────────────────────────┐    │
│  │              Private Network (10.x.x.x)              │    │
│  │                                                       │    │
│  │  ┌────────────┐  ┌────────────┐  ┌────────────┐     │    │
│  │  │  App       │  │  Worker    │  │  Scheduler │     │    │
│  │  │  Service   │  │  Service   │  │  Service   │     │    │
│  │  │            │  │            │  │            │     │    │
│  │  │  Node.js   │  │  Python    │  │  Cron      │     │    │
│  │  │  Express   │  │  Celery    │  │  Jobs      │     │    │
│  │  └─────┬──────┘  └─────┬──────┘  └────────────┘     │    │
│  │        │               │                              │    │
│  │  ┌─────┴───────────────┴──────────────────────────┐  │    │
│  │  │           Private Network Communication         │  │    │
│  │  └─────┬───────────────┬───────────────┬──────────┘  │    │
│  │        │               │               │             │    │
│  │  ┌─────▼──────┐ ┌─────▼──────┐ ┌─────▼──────┐      │    │
│  │  │ PostgreSQL │ │   Redis    │ │  MySQL     │      │    │
│  │  │ (Managed)  │ │  (Cache)   │ │ (Managed)  │      │    │
│  │  └────────────┘ └────────────┘ └────────────┘      │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                               │
│  Features:                                                    │
│  - Git push → auto deploy                                   │
│  - Automatic SSL/HTTPS                                       │
│  - Custom domains                                            │
│  - Environment variables per service                         │
│  - Horizontal/vertical scaling                               │
│  - Build logs & runtime logs                                 │
└──────────────────────────────────────────────────────────────┘

Perbandingan Railway dengan Alternatif

Fitur Railway Render Fly.io Heroku
Database Managed✅ PostgreSQL, MySQL, Redis, MongoDB✅ PostgreSQL, Redis✅ PostgreSQL✅ PostgreSQL, Redis
Auto-detect Build✅ Ya✅ Ya❌ Dockerfile✅ Ya (buildpacks)
Private Networking✅ Built-in✅ Internal URLs✅ WireGuard❌ Private Spaces ($$)
Pricing ModelPay per usageFree tier + paidPay per usageMonthly dyno pricing
DX Rating🟢 Excellent🟢 Good🟡 Intermediate🟡 Good

2. Memulai dengan Railway

Install Railway CLI

Bash
# Install Railway CLI (macOS/Linux/Windows via npm)
npm install -g @railway/cli

# Atau gunakan npx
npx @railway/cli --version

# Install via Homebrew (macOS)
brew install railway

# Install via script (Linux/macOS)
curl -fsSL https://railway.app/install.sh | sh

# Login ke Railway
railway login

# Atau login via token (untuk CI/CD)
railway login --token "my-railway-token"

# Verifikasi login
railway whoami

# Inisialisasi project baru
railway init

# Link ke project yang sudah ada
railway link

Buat Project Baru

Bash
# Buat project baru dari CLI
railway init

# Atau buat dari template
railway init --template "express-postgres"

# Deploy langsung
railway up

# Cek status
railway status

# Lihat logs
railway logs

# Buka di browser
railway open

3. Deploy dari Git Repository

Cara Deploy via Git

  1. Buat repository di GitHub/GitLab/Bitbucket
  2. Push kode Anda
  3. Buka Railway Dashboard → New Project → Deploy from GitHub
  4. Pilih repository
  5. Railway otomatis detect bahasa, build, dan deploy
  6. Dapatkan URL publik

Deploy Node.js App

JavaScript
// server.js — Simple Express app
const express = require('express');
const app = express();

const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => {
  res.json({
    message: 'Hello from Railway!',
    env: process.env.NODE_ENV || 'development',
    timestamp: new Date().toISOString(),
  });
});

app.get('/health', (req, res) => {
  res.json({ status: 'healthy' });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`Server running on port ${PORT}`);
});
JSON
{
  "name": "my-railway-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "pg": "^8.12.0"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}

Deploy Python App

Python
# app.py — Flask app
import os
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/')
def home():
    return jsonify({
        'message': 'Hello from Railway!',
        'python_version': os.sys.version,
        'env': os.environ.get('FLASK_ENV', 'development'),
    })

@app.route('/health')
def health():
    return jsonify({'status': 'healthy'})

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port)
Text
# requirements.txt
flask==3.0.0
gunicorn==21.2.0
psycopg2-binary==2.9.9

# Procfile (opsional — Railway detect dari start script)
# web: gunicorn app:app --bind 0.0.0.0:$PORT

Auto-detect Logic

Bahasa/Framework Detect Dari Build Command Start Command
Node.jspackage.jsonnpm installnpm start
Pythonrequirements.txt / pyproject.tomlpip installProcfile atau gunicorn
Gogo.modgo build./main
RustCargo.tomlcargo build --release./target/release/app
Javapom.xml / build.gradlemvn packagejava -jar target/*.jar
PHPcomposer.jsoncomposer installphp artisan serve
RubyGemfilebundle installruby app.rb

4. Deploy dengan Dockerfile

Untuk kontrol lebih penuh, Anda bisa menggunakan Dockerfile. Railway akan mendeteksi Dockerfile di root project dan menggunakannya untuk build.

Dockerfile
# Dockerfile untuk Railway
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine
WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --from=builder /app/dist ./dist

ENV NODE_ENV=production
EXPOSE ${PORT:-3000}

# Railway akan set PORT secara otomatis
CMD ["node", "dist/server.js"]

Multi-Service Dockerfile

YAML
# railway.toml — Konfigurasi Railway (opsional)
[build]
builder = "DOCKERFILE"
dockerfilePath = "Dockerfile"

[deploy]
startCommand = "node dist/server.js"
healthcheckPath = "/health"
healthcheckTimeout = 300
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 3

5. Managed Databases

Salah satu fitur terbaik Railway adalah managed databases yang terintegrasi. Anda bisa men-deploy database dalam satu klik dan langsung terkoneksi ke aplikasi via private networking. Railway menangani backup, scaling, dan maintenance.

Database yang Tersedia

Database Fitur Use Case
PostgreSQLRelational, ACID, extensionsAplikasi web umum, data terstruktur
MySQLRelational, wide adoptionLegacy apps, CMS (WordPress, dll)
RedisIn-memory, caching, pub/subSession, cache, queue, real-time
MongoDBDocument store, flexible schemaContent management, IoT, analytics

Deploy Database

Bash
# === DEPLOY DATABASE VIA CLI ===

# Deploy PostgreSQL
railway add --database postgres

# Deploy MySQL
railway add --database mysql

# Deploy Redis
railway add --database redis

# Deploy MongoDB
railway add --database mongodb

# Railway akan otomatis:
# 1. Provision database
# 2. Set environment variables:
#    - DATABASE_URL (untuk PostgreSQL)
#    - MYSQL_URL (untuk MySQL)
#    - REDIS_URL (untuk Redis)
#    - MONGO_URL (untuk MongoDB)
# 3. Buat private networking antara services

# Connect ke database via Railway CLI
railway connect postgres

# Lihat environment variables yang ter-set
railway variables

Menggunakan Database di Aplikasi

JavaScript
// Koneksi PostgreSQL di Node.js
const { Pool } = require('pg');

// Railway otomatis set DATABASE_URL
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  ssl: process.env.NODE_ENV === 'production'
    ? { rejectUnauthorized: false }
    : false,
});

// Contoh penggunaan
async function getUsers() {
  const result = await pool.query('SELECT * FROM users');
  return result.rows;
}

async function createUser(name, email) {
  const result = await pool.query(
    'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
    [name, email]
  );
  return result.rows[0];
}

// Koneksi Redis
const Redis = require('ioredis');
const redis = new Redis(process.env.REDIS_URL);

async function getCachedUser(id) {
  const cached = await redis.get(`user:${id}`);
  if (cached) return JSON.parse(cached);

  const user = await getUserFromDB(id);
  await redis.set(`user:${id}`, JSON.stringify(user), 'EX', 3600);
  return user;
}
💡 Tips

Railway otomatis meng-inject database connection strings sebagai environment variables. Jangan pernah hardcode credentials — selalu gunakan environment variables. Database di Railway memiliki automatic daily backups (Pro plan) dan bisa di-scale vertikal dari dashboard.

6. Environment Variables

Manage Variables

Bash
# === ENVIRONMENT VARIABLES VIA CLI ===

# Set variabel untuk service saat ini
railway variables set NODE_ENV=production
railway variables set API_KEY=my-secret-key
railway variables set CORS_ORIGIN=https://mydomain.com

# Set beberapa sekaligus
railway variables set \
  NODE_ENV=production \
  LOG_LEVEL=info \
  SESSION_SECRET=my-session-secret

# List semua variabel
railway variables

# Get nilai variabel spesifik
railway variables get NODE_ENV

# Delete variabel
railway variables delete API_KEY

# Set variabel untuk service tertentu (jika multi-service)
railway variables set REDIS_URL=redis://... --service my-redis-service

# Import dari .env file
railway variables set --from-dotenv .env.production

# Set variabel sebagai secret (tidak terlihat di dashboard)
railway variables set DATABASE_URL="postgres://..."

Variable Scoping

Scope Penjelasan
Service-levelVariable yang hanya tersedia untuk satu service
Project-levelVariable shared ke semua service dalam project
Environment-levelVariable untuk environment tertentu (production, staging)

Private Networking Variables

Bash
# Railway otomatis membuat variabel untuk setiap service:
# PRIVATE_URL — URL internal (tidak exposed ke internet)
# PUBLIC_URL  — URL publik (jika service punya public domain)

# Contoh environment variables otomatis:
# DATABASE_URL=postgres://postgres:password@postgres.railway.internal:5432/railway
# REDIS_URL=redis://default:password@redis.railway.internal:6379
# SERVICE_PRIVATE_URL=http://my-app.railway.internal:8080

# Menggunakan private URL di kode:
# PostgreSQL → process.env.DATABASE_URL
# Redis → process.env.REDIS_URL

# Variabel Railway yang tersedia otomatis:
# RAILWAY_STATIC_URL — Static URL
# RAILWAY_PUBLIC_DOMAIN — Custom domain (jika diset)
# RAILWAY_GIT_COMMIT_SHA — Commit hash
# RAILWAY_GIT_BRANCH — Branch name
# RAILWAY_ENVIRONMENT_NAME — Nama environment
# RAILWAY_PROJECT_NAME — Nama project
# RAILWAY_SERVICE_NAME — Nama service

7. Railway Templates

Railway Templates adalah konfigurasi siap pakai yang bisa di-deploy dalam satu klik. Template mencakup stack lengkap — aplikasi, databases, dan konfigurasi yang diperlukan.

Template Populer

Template Stack Use Case
Express + PostgreSQLNode.js, Express, PostgreSQLREST API
Next.js + PostgreSQLNext.js, Prisma, PostgreSQLFull-stack web app
Django + PostgreSQLPython, Django, PostgreSQLWeb application
Go + PostgreSQLGo, PostgreSQLHigh-performance API
Strapi CMSStrapi, PostgreSQL, S3Headless CMS
WordPressWordPress, MySQLBlog / CMS
Plausible AnalyticsPlausible, PostgreSQL, ClickhouseWeb analytics
Uptime KumaUptime KumaUptime monitoring
Bash
# Deploy template via CLI
railway init --template "express-postgres"

# Atau deploy template tertentu
railway init --template "strapi"

# Di Railway Dashboard:
# 1. Klik "New Project"
# 2. Pilih "Templates"
# 3. Cari template yang diinginkan
# 4. Klik "Deploy"
# 5. Railway akan deploy semua services

Membuat Template Sendiri

JSON
{
  "$schema": "https://railway.app/template.schema.json",
  "name": "My Full Stack App",
  "description": "Full stack app dengan Next.js dan PostgreSQL",
  "keywords": ["nextjs", "postgres", "prisma"],
  "services": {
    "web": {
      "source": {
        "repo": "github.com/myuser/my-app"
      },
      "variables": {
        "NODE_ENV": "production",
        "DATABASE_URL": "${{Postgres.DATABASE_URL}}"
      },
      "startCommand": "npm start",
      "healthcheckPath": "/api/health"
    },
    "postgres": {
      "source": {
        "image": "postgres:16"
      },
      "variables": {
        "POSTGRES_PASSWORD": "${{generate(32)}}",
        "POSTGRES_DB": "myapp"
      }
    }
  }
}

8. Scaling dan Resource

Vertical Scaling

Anda bisa mengubah resource (CPU dan RAM) untuk setiap service langsung dari dashboard Railway.

Plan CPU RAM Disk
Hobby1 vCPU512 MB - 8 GB1 GB - 50 GB
Pro1-8 vCPU256 MB - 32 GB1 GB - 500 GB
TeamCustomCustomCustom

Horizontal Scaling

Bash
# Railway mendukung horizontal scaling (replicas)
# Di Railway Dashboard:
# Service → Settings → Scaling → Replicas

# Set replicas via railway.toml
[deploy]
numReplicas = 3

# Atau di Railway Dashboard:
# Service → Settings → Horizontal Scaling → Instances: 3

# Railway akan:
# 1. Menjalankan 3 instances dari service Anda
# 2. Load balance traffic antar instances
# 3. Setiap instance mendapatkan environment variables yang sama

Restart Policy

TOML
# railway.toml — Restart Policy
[deploy]
# Restart jika crash
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 5

# Atau selalu restart
# restartPolicyType = "ALWAYS"

# Jangan restart (manual)
# restartPolicyType = "NEVER"

9. Custom Domains

Bash
# Tambah custom domain via Railway Dashboard:
# Service → Settings → Domains → Custom Domain
# Masukkan domain: myapp.example.com

# DNS Configuration:
# Type  | Name  | Value
# CNAME | myapp | my-service-production.up.railway.app

# Atau untuk apex domain (root domain):
# Type  | Name | Value
# A     | @    | (IP dari Railway — lihat dashboard)
# AAAA  | @    | (IPv6 dari Railway)

# Atau gunakan railway domain (otomatis)
# Format: my-service-production.up.railway.app

# Atau generate random domain
# Service → Settings → Domains → Generate Domain

# HTTPS otomatis dikonfigurasi oleh Railway
# Let's Encrypt certificate di-provision otomatis

10. Monorepo & Multi-service

Railway mendukung monorepo — beberapa services dalam satu repository. Setiap service bisa di-build dan deploy secara terpisah dengan konfigurasi yang berbeda.

Text
Struktur Monorepo:
├── apps/
│   ├── web/                    ← Frontend (Next.js)
│   │   ├── package.json
│   │   └── Dockerfile
│   ├── api/                    ← Backend (Express)
│   │   ├── package.json
│   │   └── Dockerfile
│   └── worker/                 ← Background Worker
│       ├── package.json
│       └── Dockerfile
├── packages/
│   └── shared/                 ← Shared library
├── railway.toml
└── package.json (root)

# Railway Configuration untuk monorepo:
# Di Railway Dashboard, set "Root Directory" untuk setiap service:
# Service "web"    → Root Directory: apps/web
# Service "api"    → Root Directory: apps/api
# Service "worker" → Root Directory: apps/worker
Bash
# Deploy monorepo services via CLI
# Link ke service tertentu
railway link --service web
railway up

# Switch ke service lain
railway link --service api
railway up

# Atau deploy dari subdirectory
cd apps/api && railway up

11. Best Practices

Best Practice Detail
Gunakan Private NetworkingAntar services gunakan PRIVATE_URL, bukan PUBLIC_URL — lebih cepat dan aman
Health ChecksSet healthcheckPath agar Railway tahu kapan service sehat
Environment SeparationGunakan Railway Environments (production, staging, preview) untuk isolasi
Database BackupsGunakan Pro plan untuk automatic daily backups. Export manual di Hobby plan
Graceful ShutdownHandle SIGTERM untuk cleanup sebelum container dihentikan
LoggingOutput logs ke stdout/stderr. Railway mengumpulkan dan menampilkan di dashboard
Pinning VersionsPin database versions (misal PostgreSQL 16) untuk menghindari breaking changes
Cost MonitoringPantau usage di dashboard. Set billing alerts untuk menghindari tagihan tak terduga
Dockerfile Multi-stageGunakan multi-stage build untuk image lebih kecil dan deploy lebih cepat
Restart PolicyGunakan ON_FAILURE untuk production, max 3-5 retries
💡 Tips

Railway menyediakan Hobby Plan dengan $5 credit per bulan — cukup untuk project personal kecil. Pro Plan ($20/bln) menambah fitur seperti automatic backups, team collaboration, dan priority support. Selalu pantau usage di dashboard untuk menghindari biaya tak terduga.

12. Quiz Pemahaman

📝 Quiz: Pemahaman Railway

1. Apa yang dilakukan Railway saat Anda push kode ke Git?

2. Bagaimana cara Railway berkomunikasi antar services?

3. Database apa saja yang tersedia di Railway?

4. Apa yang terjadi saat service di Railway crash?

5. Apa keuntungan menggunakan private URL dibanding public URL?

🔍 Zoom
100%
🎨 Tema