Deployment Hosting DevOps

Deployment & Hosting Strategies — จาก Code สู่ Production 🚀

DevOps & Vibe Coding 2026 ~30 min read
Deployment & Hosting Strategies

Deployment & Hosting Strategies 🚀

DevOps Series #21 — by practical-algo.com


🐕 Code เขียนเสร็จแล้ว... แล้วจะเอาขึ้นที่ไหน?

ตัวอย่าง code:

Developer ที่เริ่มต้น:

"เว็บเสร็จแล้ว! ทำยังไงให้คนอื่นเข้าได้?"

  • 🤔 ซื้อ server เอง?
  • 🤔 ใช้ Vercel/Netlify?
  • 🤔 เช่า VPS?
  • 🤔 ไป AWS/GCP?
  • 🤔 Domain ยังไง? HTTPS ยังไง?

❌ เลือกผิด = จ่ายแพง, ช้า, พังบ่อย

✅ เลือกถูก = ประหยัด, เร็ว, scale ได้

โพสต์นี้จะพาไปรู้จักทุกทางเลือก

ตั้งแต่ free tier ไปจนถึง enterprise-grade


📊 Hosting Options — เปรียบเทียบทุกแบบ

ตัวอย่าง code:

Hosting Options — เปรียบเทียบทุกแบบ
แบบราคาเริ่มต้นControlScaleดูแลเองเหมาะกับ
Static Host
(Vercel/Netlify)
$0ต่ำอัตโนมัติไม่ต้องStatic/SPA, JAMstack
PaaS
(Railway/Render/Fly.io)
$0-7/moต่ำ-กลางอัตโนมัติน้อยWeb apps, API, MVP
VPS
(DO/Linode/Hetzner)
$4-6/moสูงmanualปานกลางcustom setup
Cloud
(AWS/GCP/Azure)
$0-?????สูงมากอัตโนมัติเยอะEnterprise
Bare Metal$50+/moสูงสุดmanualเยอะมากHigh perf, ML, Gaming
💡 กฎง่ายๆ:
  • Side project / portfolio → Vercel/Netlify (ฟรี)
  • Startup MVP → Railway/Render (ง่าย, ถูก)
  • ต้อง customize เยอะ → VPS (control ดี, ราคาดี)
  • Enterprise / scale → Cloud (AWS/GCP/Azure)
  • ML training / gaming → Bare Metal / GPU Cloud

1️⃣ Static Hosting — Vercel / Netlify / Cloudflare Pages

ทำไมถึงฟรี?

ตัวอย่าง code:

Traditional Hosting:

Request → Server → Process → Render HTML → Response

💸 Server ต้องทำงานตลอด = ต้องจ่ายตลอด

Static Hosting:

Build Time: Framework → HTML/CSS/JS (static files)
Runtime: Request → CDN Edge → ส่ง file กลับเลย

💰 แค่เก็บไฟล์ + ส่งผ่าน CDN = ถูกมาก (ฟรีได้)

Vercel vs Netlify vs Cloudflare Pages

ตารางนี้ช่วยให้เห็นเร็วมากว่าแต่ละแพลตฟอร์มเด่นคนละมุม: Vercel เหมาะกับ Next.js, Netlify ใช้ง่ายสำหรับทีมเล็ก, ส่วน Cloudflare Pages เด่นเรื่อง edge และต้นทุน bandwidth.

รันคำสั่งเหล่านี้เพื่อ deploy:

Vercel vs Netlify vs Cloudflare Pages
VercelNetlifyCF Pages
จุดเด่นNext.js best-in-classง่ายที่สุดเร็วที่สุด
Free BW100 GB/mo100 GB/moUnlimited
Free Builds6000 min/mo300 min/mo500 builds/mo
Serverless✅ Edge+Node✅ Functions✅ Workers
Edge Runtime✅ v8✅ Deno✅ v8
Git IntegrationGitHub/GitLab/BitbucketGitHub/GitLab/BitbucketGitHub/GitLab
Analytics✅ (paid)✅ (paid)✅ (free basic)
Pro Price$20/mo/seat$19/mo/seat$5/mo (paid)
เหมาะกับNext.js projectsมือใหม่/Static sitesspeed + low cost

Deploy บน Vercel — ง่ายแค่ 3 ขั้นตอน

รันคำสั่งเหล่านี้เพื่อ deploy:

# 1. Install CLI
npm i -g vercel

# 2. Deploy (ครั้งแรก)
cd my-next-app
vercel
# → ตอบคำถาม → ได้ preview URL ทันที

# 3. Deploy production
vercel --prod
# → ได้ URL: my-next-app.vercel.app

# หรือ... แค่ push to GitHub
# Vercel auto-deploy ทุก push ให้เลย 🎉

Vercel Project Config (vercel.json)

ตัวอย่าง code:

{
  "framework": "nextjs",
  "buildCommand": "npm run build",
  "outputDirectory": ".next",
  "regions": ["sin1"],
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "no-store" }
      ]
    },
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Frame-Options", "value": "DENY" },
        { "key": "X-Content-Type-Options", "value": "nosniff" }
      ]
    }
  ],
  "rewrites": [
    { "source": "/api/:path*", "destination": "/api/:path*" }
  ],
  "redirects": [
    { "source": "/old-page", "destination": "/new-page", "permanent": true }
  ]
}

2️⃣ PaaS — Railway / Render / Fly.io

เมื่อต้องการ Backend + Database

รันคำสั่งเหล่านี้เพื่อ deploy:

Static Host: HTML/CSS/JS only ❌ ไม่มี backend

PaaS: Full app + DB + Background jobs ✅

PaaS จัดการให้:

  • 🖥️ Server provisioning
  • 📦 Container orchestration
  • 🗄️ Database management
  • 🔐 SSL certificates
  • 📊 Logs & monitoring
  • 🔄 Auto-deploy from Git
  • 📈 Auto-scaling (some)
คุณแค่: push code → มันทำที่เหลือให้หมด

เปรียบเทียบ PaaS ยอดนิยม

ถ้าคุณกำลังเริ่ม MVP ตารางนี้คือจุดตัดสินใจหลัก: ดู free tier, region, และความสะดวกเรื่อง DB/cron ก่อนเลือก เพื่อไม่ต้องย้ายแพลตฟอร์มเร็วเกินไป.

ตัวอย่าง code:

Railway vs Render vs Fly.io
RailwayRenderFly.io
Free Tier$5 credit/month750 hrs/mo (spin down)3 shared VMs free
Starter$5/mo$7/mo$0 + usage
DB included✅ Postgres/MySQL/Redis✅ Postgres/Redis✅ via Supabase
RegionsUS/EU/APUS/EU/SG35 regions
Cron Jobs✅ (paid)✅ (machines)
Private Net✅ WireGuard
เหมาะกับStartup/Prototypeมือใหม่/Simple appGlobal low-latency

Deploy ด้วย Railway

รันคำสั่งเหล่านี้เพื่อ deploy:

# Install CLI
npm i -g @railway/cli

# Login
railway login

# Init project
railway init

# Add Postgres
railway add --database postgres

# Deploy
railway up

# ได้ URL: my-app.up.railway.app 🎉

Fly.io — Deploy ใกล้ user ที่สุด

รันคำสั่งเหล่านี้เพื่อ deploy:

# Install
curl -L https://fly.io/install.sh | sh

# Login
fly auth login

# Launch (สร้าง fly.toml อัตโนมัติ)
fly launch

# Deploy
fly deploy

# Scale ไปหลาย region
fly regions add sin nrt
fly scale count 2

# ดู status
fly status

ตัวอย่าง code:

# fly.toml
app = "my-api"
primary_region = "sin"

[build]
  dockerfile = "Dockerfile"

[env]
  NODE_ENV = "production"
  PORT = "3000"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 256

3️⃣ VPS — Virtual Private Server

ทำไมยังมีคนใช้ VPS?

ตัวอย่าง code:

PaaS ง่ายแต่...

  • 💸 แพงขึ้นเรื่อยๆ เมื่อ scale
  • 🔒 Limited customization
  • 📦 Vendor lock-in
  • 🐌 Cold starts (บาง service)

VPS ให้:

  • 💰 ราคาคงที่ ไม่ว่า traffic เท่าไร
  • 🔧 Full root access — ทำอะไรก็ได้
  • 📦 Run อะไรก็ได้ (Docker, custom stack)
  • 📚 เรียนรู้ Linux/DevOps จริงๆ

Trade-off: ต้องดูแล server เอง

(security updates, backup, monitoring)

VPS Providers เทียบราคา (2025)

ส่วนนี้เหมาะกับคนที่อยากคุมระบบเองและ optimize ค่าใช้จ่ายระยะยาว โดยเฉพาะเมื่อ traffic เริ่มนิ่งและต้องการ performance ที่คาดเดาได้.

ตัวอย่าง code:

VPS Providers เทียบราคา (2025)
ProviderRAMvCPUSSDราคา/เดือนจุดเด่น
Hetzner2 GB240 GB€3.79ถูกที่สุด
DigitalOcean1 GB125 GB$6เริ่มง่าย
Linode2 GB150 GB$5community
Vultr1 GB125 GB$5หลาย region
Oracle Cloud1 GB150 GBFREE!Always Free
Contabo4 GB250 GB€4.99specs/ราคา
🔥 Hetzner ถูกที่สุด, Oracle มี Always Free tier

VPS Setup — จากศูนย์ถึง Production

ไฟล์ configuration มีหน้าตาแบบนี้:

# === Step 1: เข้า server ===
ssh root@your-server-ip

# === Step 2: Security basics ===
# สร้าง user ใหม่ (อย่าใช้ root!)
adduser deploy
usermod -aG sudo deploy

# Setup SSH key
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh

# ปิด password login + root login
sudo nano /etc/ssh/sshd_config
# PermitRootLogin no
# PasswordAuthentication no
sudo systemctl restart sshd

# === Step 3: Firewall ===
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

# === Step 4: Install Docker ===
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker deploy

# === Step 5: Deploy with Docker Compose ===

ตัวอย่าง code:

# docker-compose.yml
version: "3.8"

services:
  app:
    image: my-app:latest
    build: .
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=securepassword
      - POSTGRES_DB=mydb

  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  pgdata:

รันคำสั่งเหล่านี้เพื่อ deploy:

# Deploy!
docker compose up -d

# Update (zero-downtime)
docker compose pull
docker compose up -d --no-deps --build app

4️⃣ Reverse Proxy — Nginx vs Caddy

ทำไมต้องมี Reverse Proxy?

ตัวอย่าง code:

WITHOUT Reverse Proxy

Internet → :3000 → App (exposed directly)

❌ No HTTPS

❌ No load balancing

❌ No static file caching

❌ Single point of failure

WITH Reverse Proxy

Nginx /

Internet → :443 → Caddy → :3000 → App 1
→ :3001 → App 2
(port 80 → :3002 → App 3
→ 443

redirect)

✅ HTTPS (auto)

✅ Load balancing

✅ Static file serving

✅ Rate limiting

✅ Compression (gzip/brotli)

✅ WebSocket support

Nginx vs Caddy

ทั้งสองตัวดีมาก แต่ต่างกันที่จุดโฟกัส: Nginx ยืดหยุ่นสูงสำหรับ production ขนาดใหญ่, Caddy ชนะเรื่อง simplicity และ auto-HTTPS สำหรับทีมที่ต้องการความเร็วในการส่งงาน.

ไฟล์ configuration มีหน้าตาแบบนี้:

Nginx vs Caddy
NginxCaddy
HTTPSต้อง setup certbotAUTO! 🎉
Configซับซ้อนแต่ยืดหยุ่นง่ายมาก
Performanceเร็วมากเร็วใกล้เคียง
Learning Curveสูงต่ำ
Load Balancing✅ advanced✅ basic
เหมาะกับProduction/high trafficเริ่มต้น/auto-SSL

Nginx Config — Full Production Setup

ตัวอย่าง code:

# /etc/nginx/sites-available/myapp

# Redirect HTTP → HTTPS
server {
    listen 80;
    server_name myapp.com www.myapp.com;
    return 301 https://$server_name$request_uri;
}

# Main HTTPS server
server {
    listen 443 ssl http2;
    server_name myapp.com www.myapp.com;

    # SSL (managed by certbot)
    ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript
               text/xml application/xml text/javascript image/svg+xml;

    # Static files (serve directly, bypass app)
    location /static/ {
        alias /var/www/myapp/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # API / App (proxy to Node.js)
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # Rate limiting for API
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Health check
    location /health {
        access_log off;
        proxy_pass http://localhost:3000/health;
    }
}

# Rate limit zone (ใส่ใน http block)
# limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

Caddy Config — ง่ายกว่าเยอะ!

ตัวอย่าง code:

# Caddyfile — แค่นี้จริงๆ!

myapp.com {
    # HTTPS จัดการให้อัตโนมัติ — ไม่ต้องทำอะไร!

    # Proxy to app
    reverse_proxy localhost:3000

    # Static files
    handle_path /static/* {
        root * /var/www/myapp/static
        file_server {
            precompressed gzip br
        }
    }

    # Compression
    encode gzip zstd

    # Security headers
    header {
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
    }

    # Rate limiting
    rate_limit {
        zone api {
            key {remote_host}
            events 10
            window 1s
        }
    }

    # Logs
    log {
        output file /var/log/caddy/myapp.log
        format json
    }
}

# Multiple sites? แค่เพิ่ม block!
api.myapp.com {
    reverse_proxy localhost:4000
}

staging.myapp.com {
    reverse_proxy localhost:5000
}

ไฟล์ configuration มีหน้าตาแบบนี้:

# Nginx: ต้องทำ 5 ขั้นตอน
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d myapp.com -d www.myapp.com
sudo nginx -t
sudo systemctl reload nginx
# + ตั้ง cron renew certificate

# Caddy: ขั้นตอนเดียว
sudo apt install caddy
sudo nano /etc/caddy/Caddyfile  # ใส่ config ข้างบน
sudo systemctl reload caddy
# HTTPS จัดการให้อัตโนมัติ ✅

5️⃣ SSL/TLS — HTTPS ที่ทุกเว็บต้องมี

SSL/TLS คืออะไร?

ตัวอย่าง code:

HTTP (ไม่มี SSL):

Browser ──── plain text ── → Server

🔓 ใครก็ดักข้อมูลได้ (password, credit card)

HTTPS (มี SSL/TLS):

Browser ──── encrypted 🔒 ── → Server

🔐 เข้ารหัสทุกอย่าง ดักไม่ได้

TLS Handshake (simplified):

1. Client → Server: "สวัสดี, รองรับ cipher เหล่านี้"
2. Server → Client: "เลือก cipher นี้, นี่คือ cert"
3. Client: ตรวจ cert → สร้าง session key
4. ทั้งคู่: ใช้ session key เข้ารหัสข้อมูล ◄─ →

⚡ TLS 1.3: handshake เร็วขึ้น (1-RTT vs 2-RTT)

วิธีได้ SSL Certificate

หัวใจคือทำให้ HTTPS กลายเป็น default ตั้งแต่วันแรก เพราะมีผลทั้งความปลอดภัย, SEO, และความน่าเชื่อถือของระบบโดยตรง.

รันคำสั่งเหล่านี้เพื่อ deploy:

วิธีได้ SSL Certificate
วิธีราคาความยากใช้เมื่อไร
Let's Encryptฟรีง่ายทุกเว็บ (default)
Caddy auto-SSLฟรีง่ายที่สุดใช้ Caddy
Cloudflare SSLฟรีง่ายใช้ CF DNS
Vercel/Netlifyฟรีอัตโนมัติdeploy ที่นั่น
Commercial$10-500/yrmanualenterprise/EV cert

Let's Encrypt + Certbot

รันคำสั่งเหล่านี้เพื่อ deploy:

# Install certbot
sudo apt install certbot python3-certbot-nginx

# Get certificate (ถ้าใช้ Nginx)
sudo certbot --nginx -d myapp.com -d www.myapp.com
# → ตอบคำถาม → ได้ cert อัตโนมัติ!

# Auto-renew (certbot ตั้งให้แล้ว)
sudo certbot renew --dry-run

# Check cert status
sudo certbot certificates

# Manual renew
sudo certbot renew
sudo systemctl reload nginx

6️⃣ Domain Management — DNS

DNS ทำงานยังไง?

ตัวอย่าง code:

Browser: "myapp.com อยู่ไหน?"

Browser ── → DNS Resolver ── → Root Server

(ISP/Google (.com ?)

8.8.8.8)

┌────────▼───────┐

TLD Server

(.com →

ns1.cf.com)

┌────────▼───────┐

◄─────────── Auth Server

IP: 1.2.3.4 (Cloudflare)

myapp.com →

1.2.3.4

Browser → 1.2.3.4 → Your Server → Response 🎉

DNS Record Types

ตาราง DNS นี้ควร bookmark ไว้ใช้งานจริง เพราะปัญหา production จำนวนมากมักเริ่มจากการตั้งค่า A/CNAME/TXT ผิดเพียงจุดเดียว.

ตัวอย่าง code:

DNS Record Types
Typeใช้ทำอะไรตัวอย่าง
ADomain → IPv4myapp.com → 1.2.3.4
AAAADomain → IPv6myapp.com → 2001:db8::1
CNAMEAliaswww → myapp.com
MXMail servermail.google.com
TXTSPF/DKIM verifyv=spf1 include:_spf...
NSNameserverns1.cloudflare.com
CAAAllow CA issue certissue letsencrypt.org

ตัวอย่าง DNS Setup — Cloudflare

ตัวอย่าง code:

Cloudflare DNS — myapp.com

Type Name Content TTL Proxy

A @ 1.2.3.4 Auto 🟠 On

A @ 5.6.7.8 Auto 🟠 On

AAAA @ 2001:db8::1 Auto 🟠 On

CNAME www myapp.com Auto 🟠 On

CNAME api api-prod.fly.dev Auto 🟠 On

CNAME blog myblog.vercel.app Auto ⚪ Off

MX @ mx1.google.com Auto N/A

MX @ mx2.google.com Auto N/A

TXT @ v=spf1 include:... Auto N/A

💡 Proxy 🟠 = Traffic ผ่าน Cloudflare (CDN + DDoS protection)

Proxy ⚪ = DNS only (ตรงไป server)

ซื้อ Domain ที่ไหน?

การเลือก registrar ไม่ใช่แค่เรื่องราคาเปิดโดเมนปีแรก แต่ต้องดูค่า renew, UX ตอนจัดการ DNS, และความโปร่งใสเรื่องค่าบริการระยะยาวด้วย.

ตัวอย่าง code:

ซื้อ Domain ที่ไหน?
Registrar.com ราคาจุดเด่น
Cloudflare~$9.77at-cost + free DNS
Namecheap~$9.98UI ดี, WhoisGuard ฟรี
Porkbun~$9.73ถูกที่สุด, UI ดี
Google Domains~$12ย้ายไป Squarespace
GoDaddy~$12-20แพง/upsell เยอะ

7️⃣ CDN — Content Delivery Network

CDN ทำงานยังไง?

ตัวอย่าง code:

WITHOUT CDN:

User in Tokyo ─────── 200ms ──── → Server in US
User in London ────── 150ms ──── → Server in US
User in Bangkok ───── 180ms ──── → Server in US

WITH CDN:

┌──── Edge Tokyo ◄── cached

User in Tokyo ──5ms─┤

  • ── Origin US (if not cached)

┌──── Edge London ◄── cached

User in London ─5ms─┤

  • ── Origin US (if not cached)

┌──── Edge Singapore ◄── cached

User in Bangkok ─10ms┤

  • ── Origin US (if not cached)

⚡ Result: 200ms → 5-10ms (20-40x faster!)

CDN Providers

สำหรับเว็บทั่วไป Cloudflare free plan มักพอแล้ว แต่ถ้าอยู่ใน ecosystem AWS หนัก ๆ การใช้ CloudFront จะบริหารรวมกับระบบเดิมได้ง่ายกว่า.

ตัวอย่าง code:

CDN Providers
ProviderFree TierEdge Nodesจุดเด่น
Cloudflare✅ ฟรี330+ citiesDDoS/WAF/Workers
AWS CloudFront1 TB/mo free600+ edgesAWS ecosystem
Bunny CDN14-day trial123 PoPsถูกมาก
Fastly$50 trial90+ PoPsreal-time purge

Cloudflare Setup (5 นาที)

ตัวอย่าง code:

1. สมัคร cloudflare.com (ฟรี)

2. Add site → ใส่ domain

3. เปลี่ยน nameserver ที่ registrar ไปเป็น:

- ns1.cloudflare.com

- ns2.cloudflare.com

4. รอ propagate (ไม่เกิน 24 ชม, ปกติ < 1 ชม)

5. เปิด features:

  • SSL: Full (Strict)
  • Always Use HTTPS: On
  • Auto Minify: CSS/JS/HTML
  • Brotli: On
  • Cache: Standard
  • Security Level: Medium

ได้ทันที:

✅ CDN (330+ edge nodes)

✅ DDoS protection

✅ Free SSL

✅ DNS management

✅ Page Rules

✅ Web Analytics

Cache Headers — ควบคุมสิ่งที่ cache

ตัวอย่าง code:

# Nginx — Cache Control headers

# Static assets (images, CSS, JS) — cache นาน
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
    expires 365d;
    add_header Cache-Control "public, immutable";
}

# HTML — ไม่ cache (ให้ได้ content ใหม่เสมอ)
location ~* \.html$ {
    add_header Cache-Control "no-cache, must-revalidate";
}

# API — ไม่ cache เด็ดขาด
location /api/ {
    add_header Cache-Control "no-store, no-cache";
}

ตัวอย่าง code:

Cache-Control Cheatsheet:

  • public, max-age=31536000, immutable → Static assets (1 ปี)
  • public, max-age=3600 → Semi-static (1 ชม)
  • private, max-age=0, must-revalidate → User-specific data
  • no-cache → ต้อง validate ก่อน serve
  • no-store → ห้าม cache เลย (sensitive)
  • stale-while-revalidate=60 → Serve stale + fetch new

8️⃣ Deployment Strategies — วิธี Deploy ที่ไม่พัง

Overview

รันคำสั่งเหล่านี้เพื่อ deploy:

❌ Bad Deploy:

1. FTP upload ไฟล์ใหม่ทับของเก่า

2. เว็บพัง 5 นาที

3. แก้ไม่ได้ → restore backup อีก 10 นาที

4. User โกรธ

✅ Good Deploy:

1. Deploy version ใหม่ข้างๆ version เก่า

2. ค่อยๆ ส่ง traffic ไป version ใหม่

3. มีปัญหา? → rollback ทันที (< 1 นาที)

4. User ไม่รู้เลยว่ามี deploy

Zero-Downtime Deployment = standard ในปี 2025

Rolling Deployment

รันคำสั่งเหล่านี้เพื่อ deploy:

เหมือนเปลี่ยนยางรถ... ทีละล้อ

เริ่มต้น: [v1] [v1] [v1] [v1]  ← 4 instances, all v1

Step 1:  [v2] [v1] [v1] [v1]  ← update 1st instance
         ↑ ตรวจ health check → ✅ ผ่าน → ไปต่อ

Step 2:  [v2] [v2] [v1] [v1]  ← update 2nd instance
         ↑ ตรวจ health check → ✅ ผ่าน → ไปต่อ

Step 3:  [v2] [v2] [v2] [v1]  ← update 3rd instance

Step 4:  [v2] [v2] [v2] [v2]  ← done! 🎉

❌ ถ้า Step 2 fail?
Step 2:  [v2] [v2] [v1] [v1]  ← v2 #2 health check ❌
         → Stop! Rollback v2 #1 and #2 → [v1] [v1] [v1] [v1]

✅ Pros: ง่าย, ใช้ resource เท่าเดิม
❌ Cons: ระหว่าง deploy มี 2 versions วิ่งพร้อมกัน

Blue-Green Deployment

รันคำสั่งเหล่านี้เพื่อ deploy:

มี 2 environments: Blue (production) + Green (staging)

Phase 1: Blue = LIVE ✅

🔵 BLUE 🟢 GREEN

v1 (LIVE) ◄─── (idle)

  • App x3 LB
  • DB

Phase 2: Deploy v2 to Green

🔵 BLUE 🟢 GREEN

v1 (LIVE) ◄─── v2 (testing)

  • App x3 LB ├── App x3
  • DB └── DB

↑ ทดสอบ v2 ใน Green

Phase 3: Switch! (แค่เปลี่ยน LB)

🔵 BLUE 🟢 GREEN

v1 (standby) LB v2 (LIVE) ◄───

  • App x3 ───► ├── App x3
  • DB └── DB
🔄 Rollback? → Switch LB back to Blue (< 30 seconds!)

✅ Pros: Zero-downtime, instant rollback

❌ Cons: ต้องมี 2x resources (แพงกว่า)

Canary Deployment

ตัวอย่าง code:

เหมือนนกขมิ้นในเหมือง — ส่งตัวเล็กไปทดสอบก่อน

Step 1: ส่ง 5% traffic ไป v2

Load Balancer

95% ──── → [v1] [v1] [v1] [v1]
5% ──── → [v2] ← canary

Monitor: error rate, latency, CPU

Step 2: ถ้าไม่มีปัญหา → เพิ่มเป็น 25%
75% ──── → [v1] [v1] [v1]
25% ──── → [v2] [v2]
Step 3: เพิ่มเป็น 50% → 75% → 100%
100% ──── → [v2] [v2] [v2] [v2]

v1 instances terminated

❌ ถ้า Step 1 มีปัญหา (error spike)?

→ Rollback: ส่ง traffic 100% กลับ v1 ทันที
→ Impact: แค่ 5% ของ users ที่ได้รับผลกระทบ!

✅ Pros: ลด blast radius, data-driven decisions

❌ Cons: ซับซ้อน, ต้องมี monitoring ดี

เปรียบเทียบ Deployment Strategies

ตารางนี้ช่วยตัดสินใจเชิงความเสี่ยง: ถ้าต้องการปล่อยงานไวใช้ Rolling, ถ้าระบบ critical มากให้ขยับไป Blue-Green หรือ Canary.

รันคำสั่งเหล่านี้เพื่อ deploy:

เปรียบเทียบ Deployment Strategies
RollingBlue-GreenCanaryRecreate
DowntimeZeroZeroZeroมี ❌
Rollbackช้าทันทีเร็วช้า
ResourceN+12NN+1N
Riskปานกลางต่ำต่ำสุดสูง
Complexityต่ำปานกลางสูงต่ำสุด
Use caseทั่วไปต้อง fast rollbackcritical systemsdev/test
💡 ส่วนใหญ่ใช้ Rolling; งาน mission-critical ใช้ Blue-Green หรือ Canary

Kubernetes Rolling Update Config

ไฟล์ configuration มีหน้าตาแบบนี้:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # สร้าง pod ใหม่เพิ่มได้ 1 ตัว
      maxUnavailable: 0     # ห้ามมี pod ลดลง (zero-downtime)
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myapp:v2
          ports:
            - containerPort: 3000

          # Health checks — สำคัญมาก!
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5

          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 15
            periodSeconds: 10

          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "500m"

ไฟล์ configuration มีหน้าตาแบบนี้:

# Deploy
kubectl apply -f deployment.yaml

# ดู rollout status
kubectl rollout status deployment/myapp

# Rollback ถ้ามีปัญหา
kubectl rollout undo deployment/myapp

# ดู history
kubectl rollout history deployment/myapp

9️⃣ Full Production Setup — จากศูนย์ถึง Production

Architecture Overview

รันคำสั่งเหล่านี้เพื่อ deploy:

Production Stack

Cloudflare CDN + DNS + DDoS + WAF

(Free Plan)

┌──────▼───────┐

Caddy Reverse Proxy + Auto-SSL

(or Nginx)

┌──────▼───────────────────────────────────┐

Docker Compose

App Postgres Redis

:3000 :5432 :6379

Monitoring: Uptime Kuma + Grafana

Backup: Automated daily to S3/B2

CI/CD: GitHub Actions → SSH deploy

VPS: Hetzner CPX11 (2 vCPU, 2GB RAM) — €3.79/mo

Domain: Cloudflare Registrar — ~$10/yr

Total: ~$15/month for full production stack! 💰

GitHub Actions — Auto Deploy on Push

รันคำสั่งเหล่านี้เพื่อ deploy:

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install & Test
        run: |
          npm ci
          npm run lint
          npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to VPS
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: deploy
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /home/deploy/myapp
            git pull origin main
            docker compose pull
            docker compose up -d --build --no-deps app
            docker image prune -f

      - name: Health Check
        run: |
          sleep 10
          curl -f https://myapp.com/health || exit 1

      - name: Notify on Failure
        if: failure()
        run: |
          curl -X POST "${{ secrets.SLACK_WEBHOOK }}" \
            -H 'Content-type: application/json' \
            -d '{"text":"❌ Deploy failed! Check GitHub Actions."}'

Automated Backups

รันคำสั่งเหล่านี้เพื่อ deploy:

#!/bin/bash
# backup.sh — run daily via cron

set -euo pipefail

BACKUP_DIR="/home/deploy/backups"
DATE=$(date +%Y-%m-%d_%H%M)
RETENTION_DAYS=7

# Backup PostgreSQL
docker exec postgres pg_dump -U user mydb | gzip > "$BACKUP_DIR/db_${DATE}.sql.gz"

# Backup app data
tar czf "$BACKUP_DIR/data_${DATE}.tar.gz" /home/deploy/myapp/data/

# Upload to Backblaze B2 (cheap!)
rclone copy "$BACKUP_DIR/db_${DATE}.sql.gz" b2:my-backups/db/
rclone copy "$BACKUP_DIR/data_${DATE}.tar.gz" b2:my-backups/data/

# Cleanup old backups
find "$BACKUP_DIR" -name "*.gz" -mtime +$RETENTION_DAYS -delete

echo "✅ Backup completed: $DATE"

รันคำสั่งเหล่านี้เพื่อ deploy:

# Cron job (daily at 3 AM)
crontab -e
0 3 * * * /home/deploy/backup.sh >> /var/log/backup.log 2>&1

🔟 Monitoring — รู้ก่อนที่จะพัง

Uptime Monitoring

ตัวอย่าง code:

# Uptime Kuma — self-hosted uptime monitor
# (ฟรี, สวย, alert ได้)

docker run -d \
  --name uptime-kuma \
  --restart unless-stopped \
  -p 3001:3001 \
  -v uptime-kuma:/app/data \
  louislam/uptime-kuma:1

# → เข้า http://your-server:3001
# → เพิ่ม monitors:
#   - HTTPS: myapp.com (check every 60s)
#   - TCP: db server port 5432
#   - Docker container health
# → ตั้ง alert: Telegram, Slack, Discord, Email

Simple Health Check Endpoint

ไฟล์ configuration มีหน้าตาแบบนี้:

// Express.js health check
app.get('/health', async (req, res) => {
  const health = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    checks: {}
  };

  // Check database
  try {
    await db.query('SELECT 1');
    health.checks.database = 'ok';
  } catch (err) {
    health.status = 'degraded';
    health.checks.database = 'error';
  }

  // Check Redis
  try {
    await redis.ping();
    health.checks.redis = 'ok';
  } catch (err) {
    health.status = 'degraded';
    health.checks.redis = 'error';
  }

  // Check disk space
  const diskFree = getDiskFreePercent();
  health.checks.disk = diskFree > 10 ? 'ok' : 'warning';

  const statusCode = health.status === 'ok' ? 200 : 503;
  res.status(statusCode).json(health);
});

🛡️ Security Checklist — ก่อนจะ Go Live

ไฟล์ configuration มีหน้าตาแบบนี้:

Production Security Checklist ✅

🔐 SSL/TLS

  • [ ] HTTPS everywhere (redirect HTTP → HTTPS)
  • [ ] TLS 1.2+ only (disable TLS 1.0/1.1)
  • [ ] HSTS header enabled
  • [ ] Certificate auto-renewal working

🔒 Server

  • [ ] SSH key only (no password login)
  • [ ] Non-root user for app
  • [ ] Firewall enabled (only 22, 80, 443)
  • [ ] Unattended security updates
  • [ ] Fail2ban installed

🛡️ Application

  • [ ] Environment variables for secrets
  • [ ] CORS configured properly
  • [ ] Rate limiting on API
  • [ ] Input validation & sanitization
  • [ ] Security headers (X-Frame, CSP, etc.)
  • [ ] Dependencies updated (npm audit)

📊 Monitoring

  • [ ] Uptime monitoring active
  • [ ] Error tracking (Sentry)
  • [ ] Log rotation configured
  • [ ] Alerts configured (Telegram/Slack)

💾 Backup

  • [ ] Daily automated backups
  • [ ] Backups stored off-server
  • [ ] Restore tested recently
  • [ ] Backup monitoring (alert on failure)

🗺️ Decision Flowchart — เลือก Hosting ยังไง?

ตัวอย่าง code:

เริ่มต้น: มี project อะไร?

  • Static site / SPA / Next.js?
  • ใช้ Next.js → Vercel (free)
  • Static HTML → Cloudflare Pages (free, fastest)
  • อื่นๆ → Netlify (free, easiest)
  • Full-stack app + DB?
  • MVP / prototype?

└── Railway or Render (ง่ายที่สุด)

  • ต้อง customize?

└── VPS + Docker Compose

  • ต้อง scale globally?

└── Fly.io (multi-region)

  • Enterprise?
  • AWS/GCP/Azure + Kubernetes
  • API only?
  • Lightweight → Cloudflare Workers / Vercel Edge
  • Node/Python → Railway or Fly.io
  • Complex → VPS or Cloud
  • ML / GPU workloads?
  • Inference → Modal, Replicate, RunPod
  • Training → Lambda Labs, Vast.ai
  • Enterprise → AWS SageMaker, GCP Vertex

🔑 Key Takeaways

แนวคิดสำคัญของบทนี้คือ “เลือกให้เหมาะกับ stage ของโปรเจกต์” มากกว่าการไล่ใช้ของใหญ่ตั้งแต่วันแรก แล้วค่อยยกระดับ architecture ตามภาระงานจริง.

  1. เริ่มจากง่ายไปยาก — Vercel/Netlify → PaaS → VPS → Cloud
  2. HTTPS ฟรีทุกที่ — Let's Encrypt, Caddy auto-SSL, Cloudflare
  3. Cloudflare = must-have — CDN + DNS + DDoS ฟรี
  4. Caddy ง่ายกว่า Nginx — สำหรับ project ที่ไม่ต้อง fine-tune มาก
  5. Zero-downtime deploy เป็น standard — Rolling update เป็นค่า default
  6. Canary deploy สำหรับ critical systems — ลด blast radius
  7. Blue-Green สำหรับ instant rollback — แต่ต้องมี 2x resources
  8. VPS + Docker Compose + Caddy = sweet spot — $5-15/mo ได้ production-grade
  9. Automate everything — CI/CD, backups, monitoring, SSL renewal
  10. Monitor before you deploy — ถ้าไม่ monitor = ไม่รู้ว่าพัง

📌 This is #21 in our DevOps & Full-Stack series

📚 Series ทั้งหมด:

  1. Git Branching — แตก branch ยังไงให้เป็นระบบ
  2. CI/CD Pipeline — จาก commit ถึง production
  3. Docker vs VMs — Container คืออะไร ทำไมต้องใช้
  4. API Lifecycle — Request เดินทางยังไง
  5. Kubernetes — จัดการ container ระดับ production
  6. Networking — DNS, TCP, Load Balancer, Firewall
  7. Infrastructure as Code — Terraform & Ansible
  8. Monitoring & Observability — Logs, Metrics, Traces
  9. Linux & Shell Essentials — พื้นฐานที่ DevOps ต้องรู้
  10. DevSecOps & Security — Shift Left, OWASP, Secrets
  11. Testing Strategies — Pyramid, TDD, Load, Chaos
  12. GitOps & ArgoCD — Git-driven Deployments
  13. Cloud Architecture — AWS, GCP, Azure Fundamentals
  14. SRE — Site Reliability Engineering
  15. GitHub Actions Workflow — Advanced CI/CD
  16. Automated Testing — Unit, Integration, E2E
  17. Database Design & SQL — Normalization, Indexing, Query Optimization
  18. Authentication & Authorization — JWT, OAuth, RBAC
  19. Web Architecture & Design Patterns — Monolith vs Microservices
  20. Frontend Performance & Modern Frameworks
  21. Deployment & Hosting Strategies — Vercel to Bare Metal ← 📍 อยู่ตรงนี้