Elixir untuk Technical Leader — Bab 8 dari 10

Deploy & Operations

Dari laptop ke production server. Kamu harus tau cara deploy, monitor, dan rollback — karena kamu yang pegang akun Fly.io.


Big Picture — Dari Code ke Server

LabaBersih ditulis di laptop kamu pakai Elixir. Tapi server di internet gak perlu install Elixir. Yang di-upload ke server adalah binary yang sudah di-compile — kayak file .exe di Windows.

Alurnya:

# Alur deploy LabaBersih:

Code Elixir (laptop)
    |
    v
mix release          # compile jadi binary standalone
    |
    v
Docker image         # bungkus binary + OS minimal ke dalam "kontainer"
    |
    v
fly deploy           # upload ke Fly.io server di Singapore
    |
    v
lababersih.id LIVE   # Nelly bisa akses
Analogi mix release = masak makanan di dapur. Docker = bungkus ke dalam lunch box. fly deploy = kirim ke restoran (server). Customer (Nelly) tinggal makan.

1. Mix Release — Compile Jadi Binary

Di development, kamu jalankan mix phx.server — ini butuh Elixir dan Erlang ter-install. Di production, kita gak mau install itu semua. Solusinya: Mix Release.

# Compile project jadi standalone binary
$ mix release

# Hasilnya ada di folder:
_build/prod/rel/lababersih/

# Jalankan tanpa Elixir ter-install:
$ _build/prod/rel/lababersih/bin/server

Yang terjadi saat mix release:

  1. Semua code Elixir di-compile jadi bytecode BEAM
  2. Semua dependency (Phoenix, Ecto, Guardian, Oban, dll) ikut di-bundle
  3. Erlang/OTP runtime ikut di-bundle
  4. Jadi 1 folder yang self-contained — tinggal copy ke server mana aja
Yang perlu kamu tau Kamu gak perlu jalankan mix release manual. Dockerfile LabaBersih sudah otomatis menjalankannya. Tapi kamu perlu tau konsepnya — bahwa yang jalan di server bukan "code Elixir", tapi binary yang sudah di-compile.

2. Dockerfile — Resep Kontainer

Docker = cara standar industri untuk "bungkus" aplikasi + semua dependensinya jadi 1 paket (disebut image). Image ini bisa jalan di mana aja yang support Docker — Fly.io, AWS, Google Cloud, laptop kamu.

Phoenix otomatis generate Dockerfile saat kamu bikin project baru. LabaBersih punya Dockerfile sendiri. Ini versi simplifikasinya:

# === Stage 1: BUILD ===
# Pakai image yang sudah ada Elixir + Erlang
FROM hexpm/elixir:1.19.5-erlang-28.4.1-debian-trixie AS builder

# Install tools untuk compile
RUN apt-get update && apt-get install -y build-essential git

# Copy source code
COPY mix.exs mix.lock ./
RUN mix deps.get --only prod    # download dependency

COPY lib lib
COPY config config
COPY assets assets
COPY priv priv

RUN mix compile                 # compile semua code
RUN mix assets.deploy           # compile CSS/JS
RUN mix release                 # bikin binary standalone


# === Stage 2: RUN ===
# Image KECIL — cuma OS minimal, TANPA Elixir/Erlang source
FROM debian:trixie-slim AS final

# Copy HANYA binary hasil compile dari stage 1
COPY --from=builder /app/_build/prod/rel/lababersih ./

# Jalankan!
CMD ["/app/bin/server"]

Perhatikan: ada 2 stage (multi-stage build).

StageIsiUkuran
BuilderElixir, Erlang, npm, tools compile~1.5 GB
FinalCuma OS minimal + binary hasil compile~120 MB

Stage builder dibuang setelah selesai. Yang di-upload ke server cuma stage final yang kecil. Gak ada source code di server production — cuma binary.

Zero vendor lock-in Dockerfile ini standar. Kalau besok kamu mau pindah dari Fly.io ke AWS atau Google Cloud — tinggal pindahkan Docker image yang sama. Gak ada yang spesifik Fly.io di dalamnya.

3. Fly.io — Kenapa Dipilih

Fly.io = hosting platform yang native untuk Phoenix/Elixir. Chris McCord (pembuat Phoenix) kerja di Fly.io. Ini bukan kebetulan — mereka optimize khusus untuk BEAM apps.

Kenapa Fly.io untuk LabaBersih?

FaktorFly.ioCatatan
Region Singaporesin (Southeast Asia)Terdekat ke user Indonesia. Latency rendah.
Phoenix-nativeFirst-class supportfly launch otomatis detect Phoenix project
PostgreSQL managed1 command setupDatabase, backup, connection pooling otomatis
Harga~$10-15/bulanLebih murah dari Supabase+Vercel ($45/bulan)
Auto-scalingScale to zeroGak dipake = gak bayar (auto_stop)
SSL/HTTPSOtomatisGak perlu setup sertifikat
Custom domainMudahlababersih.id pointing ke Fly.io

Deploy pertama kali

# Install Fly CLI (sekali aja)
$ curl -L https://fly.io/install.sh | sh

# Login ke Fly.io
$ fly auth login

# Launch project (pertama kali — auto-detect Phoenix)
$ fly launch
# ? Choose an app name: lababersih-id
# ? Choose region: sin (Singapore)
# ? Create PostgreSQL database? Yes

# Deploy!
$ fly deploy

Selesai. fly deploy melakukan semua: build Docker image, upload ke Fly.io, jalankan health check, switch traffic.


4. fly.toml — File Konfigurasi

Setiap project Fly.io punya file fly.toml di root project. Ini "kontrak" antara kamu dan Fly.io — seberapa besar server, di mana, pakai port berapa.

Ini file fly.toml LabaBersih yang sesungguhnya:

# fly.toml — konfigurasi LabaBersih di Fly.io

app = 'lababersih-id'        # nama app di Fly.io
primary_region = 'sin'         # Singapore — terdekat ke Indonesia

[http_service]
  internal_port = 4000         # port yang Phoenix dengarkan
  force_https = true            # selalu HTTPS (keamanan)
  auto_stop_machines = 'stop'   # matikan kalau gak ada traffic
  auto_start_machines = true    # nyalakan lagi kalau ada request
  min_machines_running = 0      # boleh 0 saat idle (hemat biaya)
  processes = ['app']           # nama proses

[[vm]]
  memory = '1gb'               # RAM 1 GB
  cpus = 1                      # 1 CPU

Penjelasan per section:

SectionFungsiYang perlu kamu tau
appNama appURL default: lababersih-id.fly.dev
primary_regionLokasi serversin = Singapore. Pilihan lain: nrt (Tokyo), hkg (Hong Kong)
[http_service]Konfigurasi webPort 4000 = default Phoenix. HTTPS dipaksa.
auto_stopHemat biayaServer mati otomatis kalau gak ada traffic. Nyala lagi ~2-3 detik.
[[vm]]Ukuran server1 CPU + 1 GB RAM cukup untuk 6.300 order/hari
Kapan perlu ubah fly.toml? Jarang. Paling kalau mau naikkan RAM (1gb ke 2gb) atau tambah server di region lain. Kebanyakan perubahan lewat fly secrets (environment variables), bukan di fly.toml.

5. Database di Fly.io

Fly.io menyediakan PostgreSQL managed — database yang sama dengan yang dipakai di development. Setup-nya 1 command:

# Buat database (pertama kali, sudah dilakukan)
$ fly postgres create --name lababersih-db --region sin

# Attach ke app (otomatis set DATABASE_URL)
$ fly postgres attach lababersih-db

Setelah attach, Fly.io otomatis set environment variable DATABASE_URL di app kamu. Phoenix baca ini di config/runtime.exs.

Fitur database Fly.io:

FiturStatusCatatan
Automatic backupsAdaPoint-in-time recovery. Bisa restore ke menit tertentu.
Connection poolingBuilt-inPgBouncer otomatis. Pool size 10 (default LabaBersih).
Region co-locationOtomatisDB di Singapore, app di Singapore. Latency minimal.
Storage10 GB (default)Bisa naikkan. LabaBersih ~5 juta operasi/bulan cukup.
MonitoringDashboardQuery stats, connection count, storage usage.

Akses database langsung:

# Buka psql console ke database production
$ fly postgres connect -a lababersih-db

# Cek jumlah order
lababersih=# SELECT count(*) FROM orders;

# Cek ukuran database
lababersih=# SELECT pg_size_pretty(pg_database_size('lababersih'));
Hati-hati! fly postgres connect = akses langsung ke database production. JANGAN jalankan DELETE atau DROP tanpa yakin. Query SELECT aman.

6. Environment Variables — Rahasia App

Informasi sensitif (password, API key, secret) gak boleh ditulis di code. Mereka disimpan sebagai environment variables di Fly.io.

3 Secret wajib LabaBersih:

VariableFungsiCara generate
SECRET_KEY_BASEEnkripsi cookies & session Phoenixmix phx.gen.secret
DATABASE_URLKoneksi ke PostgreSQLOtomatis saat fly postgres attach
GUARDIAN_SECRET_KEYSign JWT token untuk authmix phx.gen.secret

Cara set di Fly.io:

# Set 1 secret
$ fly secrets set SECRET_KEY_BASE=abc123supersecretlongstring

# Set beberapa sekaligus
$ fly secrets set \
    GUARDIAN_SECRET_KEY=anotherlongstring \
    PHX_HOST=lababersih.id

# Lihat daftar secrets (value GAKK ditampilkan, cuma nama)
$ fly secrets list
NAME                  DIGEST          CREATED AT
DATABASE_URL          abc123...       2026-03-30
GUARDIAN_SECRET_KEY   def456...       2026-03-30
SECRET_KEY_BASE       ghi789...       2026-03-30

# Hapus secret
$ fly secrets unset NAMA_SECRET
Kenapa aman? Secrets di Fly.io disimpan terenkripsi. Bahkan kamu sendiri gak bisa lihat value-nya setelah di-set — cuma bisa ganti. Secrets diinject ke app saat start sebagai environment variable.

Di mana secrets dipakai di code?

Di file config/runtime.exs. Ini file yang dibaca saat app start (bukan saat compile):

# config/runtime.exs — dibaca saat app start di production

if config_env() == :prod do
  # Ambil DATABASE_URL dari environment
  database_url =
    System.get_env("DATABASE_URL") ||
      raise "DATABASE_URL is missing"

  config :lababersih, Lababersih.Repo,
    url: database_url,
    pool_size: 10

  # Ambil SECRET_KEY_BASE dari environment
  secret_key_base =
    System.get_env("SECRET_KEY_BASE") ||
      raise "SECRET_KEY_BASE is missing"

  config :lababersih, LababersihWeb.Endpoint,
    secret_key_base: secret_key_base

  # Ambil GUARDIAN_SECRET_KEY dari environment
  guardian_secret =
    System.get_env("GUARDIAN_SECRET_KEY") ||
      raise "GUARDIAN_SECRET_KEY is missing"

  config :lababersih, Lababersih.Auth.Guardian,
    secret_key: guardian_secret
end

Perhatikan pattern System.get_env("...") || raise "..." — kalau secret gak ada, app gak mau start dan kasih pesan jelas. Lebih baik gagal keras daripada jalan dengan config salah.

Secret yang akan ditambah nanti:

VariableKapanFungsi
RESEND_API_KEYPart EKirim email (reset password, invite)
SENTRY_DSNPart HError tracking
TIKTOK_SHOP_APP_KEYPart GTikTok Shop API
TIKTOK_SHOP_APP_SECRETPart GTikTok Shop API
MENGANTAR_API_KEYPart GMengantar API

7. Deploy Workflow

Setiap kali Claude selesai bikin fitur dan kamu mau push ke production:

# 1. Pastikan tests pass
$ mix test
268 tests, 0 failures

# 2. Commit perubahan
$ git add .
$ git commit -m "feat: laporan keuangan UI"

# 3. Deploy ke Fly.io
$ fly deploy

Apa yang terjadi saat fly deploy:

# Proses fly deploy (otomatis):

1. Upload source code ke Fly.io builder
   |
2. Build Docker image (sesuai Dockerfile)
   ├── Install dependencies (mix deps.get)
   ├── Compile code (mix compile)
   ├── Build assets (mix assets.deploy)
   └── Create release (mix release)
   |
3. Push image ke Fly.io registry
   |
4. Start mesin baru dengan image baru
   |
5. Health check — cek app respond HTTP 200
   |
6. Switch traffic ke mesin baru
   |
7. Matikan mesin lama
   |
Deploy complete!

Total waktu: 3-5 menit. Selama deploy, app lama tetap jalan — zero downtime.

Health check:

Fly.io cek apakah app baru sudah ready sebelum switch traffic. Kalau health check gagal (app crash, gak respond), Fly.io gak switch — app lama tetap jalan. Deploy ditandai "failed" tapi user gak terkena dampak.

Safe by default Deploy yang gagal = gak terjadi apa-apa. App lama tetap jalan. Kamu bisa fix, lalu deploy lagi. User gak tau ada deploy yang gagal.

Database migration otomatis:

Kalau ada migration baru (tabel baru, kolom baru), migration dijalankan otomatis saat app start — sebelum menerima traffic. Ini diatur di file rel/overlays/bin/migrate.


8. Monitoring — Tau Apa yang Terjadi

Sebagai leader, kamu perlu tau cara cek: apakah app jalan? Ada error? Performance oke?

8a. Fly.io Dashboard (Web)

Buka fly.io/apps/lababersih-id di browser:

8b. fly status (Terminal)

$ fly status

App
  Name     = lababersih-id
  Status   = deployed
  Version  = 42

Machines
  ID        STATE   REGION  CREATED
  e784e2    started sin     2026-03-30T15:01:20Z

Ini cara tercepat cek: apakah app jalan?

8c. fly logs (Real-time)

# Lihat log production real-time
$ fly logs

# Output contoh:
2026-04-02 10:30:15 [info] GET /app/order
2026-04-02 10:30:15 [info] Sent 200 in 45ms
2026-04-02 10:30:18 [info] GET /app/produk
2026-04-02 10:30:18 [info] Sent 200 in 32ms
2026-04-02 10:31:01 [error] ** (Ecto.NoResultsError) no results for Order query
2026-04-02 10:31:01 [error]   Lababersih.Orders.get_order!/1

Ini alat utama debugging. Kalau ada user lapor error, buka fly logs dan cari pesan errornya.

8d. Phoenix LiveDashboard

Phoenix punya monitoring dashboard built-in di /dev/dashboard (hanya di development). Di production, bisa diaktifkan tapi butuh auth khusus.

Yang bisa dilihat:

TabIsiBerguna kapan
HomeMemory usage, atom count, process countCek apakah ada memory leak
OSCPU usage, memory, diskServer kepenuhi gak?
Ecto StatsQuery paling lambat, query paling seringOptimasi database
ProcessesSemua BEAM process yang jalanDebugging (advanced)
ObanBackground jobs statusCek daily journal batch jalan gak

8e. Sentry (Future — Part H)

Sentry = layanan tracking error otomatis. Setiap kali ada error di production, Sentry kirim notifikasi (email/Slack) dengan detail lengkap: error apa, user mana, stack trace.

# Nanti di mix.exs:
{:sentry, "~> 10.0"}

# Nanti di config/prod.exs:
config :sentry,
  dsn: System.get_env("SENTRY_DSN"),
  environment_name: :prod
Monitoring summary untuk leader
  • App jalan? → fly status
  • Ada error? → fly logs
  • Server penuh? → Fly.io dashboard (Monitoring tab)
  • Query lambat? → LiveDashboard (Ecto Stats)
  • Error notification? → Sentry (nanti)

9. Troubleshooting — Kalau Ada Masalah

Alat utama: fly ssh console

Ini fitur paling keren — kamu bisa buka IEx (Elixir console) langsung di server production:

# SSH ke server production
$ fly ssh console

# Jalankan IEx (Elixir interactive shell)
$ /app/bin/lababersih remote

# Sekarang kamu di IEx production! Bisa query langsung:
iex> Lababersih.Repo.aggregate(Lababersih.Orders.Order, :count)
4643

iex> Lababersih.Accounts.get_user_by_email("nelly@lababersih.com")
%User{name: "Nelly", ...}
HATI-HATI IEx remote = akses penuh ke production. Bisa baca data, tapi juga bisa ubah/hapus data. Gunakan untuk debugging dan query saja. JANGAN jalankan fungsi yang mengubah data kecuali benar-benar perlu.

Masalah umum dan solusinya:

MasalahGejalaSolusi
Deploy gagal Error saat fly deploy Baca error message. Biasanya: compile error (fix code), health check timeout (app gak start). Cek fly logs.
App crash loop App start lalu mati terus fly logs — cari error. Biasanya: secret missing, database gak connect, migration gagal.
Database connection refused "could not connect to server" Cek fly postgres list. Restart DB: fly machine restart -a lababersih-db
Migration gagal App start tapi data gak ada fly ssh console/app/bin/migrate untuk run manual
Out of memory App lambat lalu mati Naikkan RAM di fly.toml: memory = '2gb', lalu fly deploy
Secret missing "SECRET_KEY_BASE is missing" di log fly secrets set SECRET_KEY_BASE=...
HTTPS error / mixed content Browser warning "not secure" Pastikan force_https = true di fly.toml. Cek DNS pointing.
Slow response TTFB > 300ms Cek LiveDashboard Ecto Stats. Missing index? N+1 query? Cek fly logs response time.

10. Rollback — Kalau Deploy Rusak

Deploy baru ternyata ada bug? Rollback ke versi sebelumnya dalam hitungan detik.

# Lihat daftar semua release (versi deploy)
$ fly releases

VERSION   STATUS    CREATED
v42       current   2026-04-02T10:30:00Z
v41       -         2026-04-01T15:00:00Z
v40       -         2026-03-31T12:00:00Z

# Rollback ke versi sebelumnya
$ fly deploy --image registry.fly.io/lababersih-id:deployment-v41

# Atau cara cepat: redeploy dari git commit sebelumnya
$ git checkout v41-commit-hash
$ fly deploy

Workflow rollback darurat:

  1. User lapor error / kamu lihat di fly logs
  2. fly releases — cari versi yang terakhir stabil
  3. fly deploy --image ... — rollback ke versi itu
  4. Fix bug di code, test, deploy lagi
Safety net Fly.io simpan semua versi image. Kamu bisa rollback ke versi berapa aja. Dan ingat: deploy yang gagal health check gak akan live — app lama tetap jalan.
Catatan tentang database migration Rollback app mudah. Tapi rollback migration database lebih susah. Kalau versi baru sudah jalankan migration (tambah kolom, buat tabel), rollback app ke versi lama bisa error karena schema beda. Karena itu: selalu bikin migration yang backward-compatible (tambah kolom nullable, jangan hapus kolom).

11. Data Migration — Pindah Provider

LabaBersih v1 di Supabase, v2 di Fly.io. Keduanya pakai PostgreSQL — jadi data bisa dipindahkan langsung.

# Export data dari Supabase (v1)
$ pg_dump --data-only --no-owner -F c \
    "postgresql://user:pass@supabase-host/db" \
    -f v1_backup.dump

# Import data ke Fly.io (v2)
$ pg_restore --no-owner --no-privileges \
    -d "postgresql://user:pass@fly-host/db" \
    v1_backup.dump

Kenapa ini possible?

Cutover plan LabaBersih
  1. Sabtu malam: freeze v1 (maintenance mode)
  2. pg_dump dari Supabase (~15 menit)
  3. Transform data kalau perlu (script Elixir)
  4. pg_restore ke Fly.io (~15 menit)
  5. Verify: count rows, spot check, trial balance
  6. Switch DNS lababersih.id ke Fly.io
  7. Nelly test — OK? Selesai. Gagal? Rollback ke v1.
  8. Total downtime: 2-4 jam (Sabtu malam)

12. Alternatif Hosting

Fly.io bukan satu-satunya pilihan. Kalau suatu hari mau pindah (zero vendor lock-in karena Docker), ini perbandingannya:

ProviderElixir SupportHarga/bulanRegion AsiaProKontra
Fly.io Native (Phoenix-first) $10-15 Singapore Terbaik untuk Phoenix. Scale to zero. Chris McCord di sini. Docs kadang kurang. UI dashboard basic.
Gigalixir Native (Elixir-only) $10+ (free tier ada) US & EU only Dibuat khusus Elixir. Hot upgrade support. Gak ada region Asia. Latency tinggi dari Indonesia.
Render Docker $7+ Singapore UI bagus. Simple. PostgreSQL managed. Gak ada BEAM-specific feature. Cold start lebih lama.
Railway Docker $5+ US only Deploy dari GitHub otomatis. Developer-friendly. Gak ada region Asia. Pricing bisa unpredictable.
AWS (EC2/ECS) Docker/manual $15-50+ Singapore, Jakarta Enterprise-grade. Region Jakarta. Scalable. Kompleks banget. Butuh DevOps knowledge. Overkill untuk skala ini.
Google Cloud Run Docker $5-20 Jakarta Pay per request. Region Jakarta ada. WebSocket (LiveView) butuh config khusus. Stateless-focused.
DigitalOcean Docker/manual $6-12 Singapore Simple. Murah. App Platform support Docker. Gak ada BEAM-specific. PostgreSQL managed tambah biaya.
VPS (manual) Install sendiri $5-10 Banyak pilihan Paling murah. Full kontrol. Semua manual: SSL, backup, monitoring, update OS. Risky tanpa DevOps.
Rekomendasi Untuk LabaBersih sekarang: Fly.io (Phoenix-native, Singapore, murah).
Kalau butuh region Jakarta dan budget naik: pertimbangkan AWS atau Google Cloud Run.
Kalau mau pindah kapan aja: Docker image yang sama bisa jalan di semua provider di atas. Zero lock-in.

13. Performance Targets

Setiap fitur LabaBersih punya target response time. Ini bukan ngasal — berdasarkan standar UX research bahwa user mulai merasa "lambat" di atas 300ms.

Tipe HalamanTargetContohCara cek
List page < 200ms /app/order, /app/produk Lihat "Sent 200 in Xms" di fly logs
Detail page < 100ms /app/order/:id Sama — di logs
Create/Update < 300ms Buat order, update produk Sama
Heavy operation < 500ms Ship order (5 step atomic) Sama + LiveDashboard Ecto Stats
TTFB (general) < 300ms Semua halaman Browser DevTools → Network tab

Kenapa Phoenix bisa secepat ini?

  1. LiveView = WebSocket persistent — gak ada HTTP overhead per interaksi. Koneksi sudah terbuka.
  2. Server-side rendering — HTML sudah ready, browser gak tunggu JavaScript download + execute.
  3. Diff-only update — LiveView cuma kirim bagian yang berubah, bukan re-render seluruh halaman.
  4. BEAM concurrency — 1 CPU bisa handle ribuan koneksi bersamaan.
  5. Region Singapore — jarak fisik dekat ke Indonesia = latency rendah.

Kalau lambat, cek di mana?

# 1. Cek response time di logs
$ fly logs | grep "Sent"
# Sent 200 in 450ms  ← INI LAMBAT, target < 200ms

# 2. Buka LiveDashboard, cek Ecto Stats
# Cari query yang > 100ms → kemungkinan missing index

# 3. Pastikan query pakai index
# Di IEx remote:
iex> Ecto.Adapters.SQL.explain(Lababersih.Repo, :all,
       from o in Order, where: o.status == "dikirim")
# Cari: "Seq Scan" = LAMBAT (gak pakai index)
# Harus: "Index Scan" = CEPAT

Biaya Bulanan

Itemv1 (Supabase + Vercel)v2 (Fly.io)
Hosting (app)$20 (Vercel Pro)~$5-8 (Fly.io VM)
Database$25 (Supabase Pro)~$5-7 (Fly.io Postgres)
SSLIncludedIncluded
DomainTerpisahTerpisah (~$10/tahun)
Total$45/bulan~$10-15/bulan
Hemat ~$30/bulan ($360/tahun) dengan infrastruktur yang lebih baik

Deploy Checklist

Sebelum setiap deploy, pastikan:

Pre-deploy checklist
  1. Tests pass?mix test harus 0 failures
  2. Compile clean?mix compile --warnings-as-errors harus tanpa warning
  3. Migration backward-compatible? — Tambah kolom nullable, jangan hapus kolom
  4. Secrets sudah di-set?fly secrets list cek semua ada
  5. Commit sudah di-push?git status clean
  6. Team diberi tau? — Minimal bilang "mau deploy"
Post-deploy checklist
  1. App running?fly status
  2. Health check pass? — Buka lababersih.id di browser
  3. No errors?fly logs tunggu 1-2 menit
  4. Critical path work? — Login, buka order, cek produk
  5. Migration jalan? — Data baru muncul (kalau ada tabel/kolom baru)

Cheat Sheet — Command yang Perlu Kamu Hafal

Mau apa?Command
Cek app jalanfly status
Lihat errorfly logs
Deployfly deploy
Rollbackfly releases lalu fly deploy --image ...
Set secretfly secrets set KEY=value
List secretsfly secrets list
SSH ke serverfly ssh console
IEx di productionfly ssh console/app/bin/lababersih remote
Akses DBfly postgres connect -a lababersih-db
Restart appfly machine restart
Scale upEdit fly.tomlfly deploy
Cek biayafly billing atau dashboard web

Zero Vendor Lock-in — Buktinya

Klaim: "LabaBersih bisa pindah hosting kapan aja tanpa rewrite." Ini buktinya:

LayerTeknologiPortable?
Code Elixir/Phoenix Ya — bahasa + framework, gak terikat hosting
Database PostgreSQL Ya — standar industri, jalan di mana aja. pg_dump/pg_restore.
Container Docker Ya — image yang sama bisa jalan di AWS, GCP, DigitalOcean, dll.
Config Environment variables Ya — standar 12-factor app. Semua hosting support env vars.
Background jobs Oban (PostgreSQL-based) Ya — pakai database yang sama, gak butuh Redis/external queue.
Fly.io-specific Hanya fly.toml 1 file config, mudah di-replace dengan config hosting lain.
Kesimpulan Satu-satunya yang Fly.io-specific adalah file fly.toml (20 baris). Semua sisanya — code, database, Docker, secrets — standar industri. Mau pindah ke AWS besok? Copy Docker image, set env vars, selesai.

Ringkasan Bab 8

KonsepSatu Kalimat
Mix ReleaseCompile Elixir jadi standalone binary — server gak perlu install Elixir.
DockerfileResep kontainer: 2-stage build, image final cuma ~120 MB.
Fly.ioHosting Phoenix-native di Singapore, $10-15/bulan, 1 command deploy.
fly.tomlConfig file 20 baris: nama app, region, RAM, port.
DatabasePostgreSQL managed di Fly.io: backup otomatis, connection pooling.
Env varsSecrets (password, API key) disimpan terenkripsi di Fly.io, bukan di code.
Deployfly deploy = build Docker + health check + switch traffic. Zero downtime.
Monitorfly status (up?), fly logs (errors?), LiveDashboard (performance).
Troubleshootfly ssh console + /app/bin/lababersih remote = IEx di production.
Rollbackfly releasesfly deploy --image previous. Detik, bukan jam.
Data migrationpg_dump + pg_restore. Same PostgreSQL, same bcrypt. Password compatible.
Lock-inZero. Docker + PostgreSQL + env vars = standar industri.
PerformanceList < 200ms, detail < 100ms, create < 300ms, TTFB < 300ms.
Untuk kamu sebagai leader Kamu gak perlu jadi DevOps expert. Yang perlu kamu tau: cara cek app (fly status), cara lihat error (fly logs), cara rollback (fly deploy --image), dan berapa biayanya ($10-15/bulan). Claude yang handle sisanya — tapi kamu yang pegang akun.