สัปดาห์ที่ 14 · Advanced

Deploy + Maintain

งานบนเครื่องของคุณ ≠ งานที่คนอื่นใช้ได้ · สัปดาห์นี้ครอบคลุม 5 deployment targets — Cloud · Desktop · 📱 Mobile · 🤖 IoT/Edge · Hybrid · เลือก target ผิด = user ไม่ใช้ · เลือกถูก = ของ "อยู่กับ user ตลอด"

⚠️ ก่อน deploy — ตรวจ Tech vs Target match "Tkinter → Cloud Run" · "Streamlit → 10,000 user" · "CLI → grandma" — 3 mismatch ที่นักศึกษาเจอบ่อยที่สุด · เปิด UX/UI Section 0 — เลือก UI Technology ก่อนเริ่ม deploy · ถ้าเลือก tech ผิดมาตั้งแต่แรก → deploy ไม่ได้ ไม่ว่าจะพยายามแค่ไหน
📐 ตรวจ UX ก่อน deploy ของบน production = ทุกคนเห็น · เปิด UX/UI Checklist เช็คให้ครบก่อนกด deploy

เป้าหมายสัปดาห์นี้

🔒 ทำไม "เลือก deployment target" คือทักษะที่ AI ทำให้คุณไม่ได้ AI "deploy ได้" · แต่ AI ไม่รู้ว่า user ของคุณใช้อะไร · เพื่อนคุณเปิด เครื่อง laptop วันละ 1 ชั่วโมง แต่อยู่กับ มือถือ ทั้งวัน · TA ในห้อง lab อยู่หน้า desktop · พ่อแม่ในร้าน "ไม่กล้าโหลดอะไรเพิ่ม" · ตัวเลือก target ตัดสินว่าของคุณจะถูกใช้หรือไม่ · งานนี้เป็นงาน "คิดถึง user" · AI ทำไม่ได้

🗺 Deployment Decision — เลือก target จาก user

ก่อนเลือก tech · ตอบคำถามนี้ก่อน: "user ของฉันใช้อะไรอยู่?"

flowchart TB user["👤 User
ใช้อะไร?"] user --> q1{ต้องใช้
ออฟไลน์?} q1 -->|Yes| q2{อุปกรณ์?} q1 -->|No| q3{อุปกรณ์?} q2 -->|PC| desk["💻 Desktop App
PyInstaller .exe"] q2 -->|Phone| pwa["📱 PWA
(installable web)"] q2 -->|Sensor / Motor| iot["🤖 IoT / Edge
Raspberry Pi · ESP32"] q3 -->|PC| cloud["☁️ Cloud Web
Streamlit · Flask"] q3 -->|Phone| mobile["📱 Mobile Web
+ LINE bot"] q3 -->|ทั้งคู่| hybrid["🔄 Hybrid
Cloud + LINE bot"] classDef question fill:#3b2962,stroke:#8b5cf6,color:#fff classDef desk fill:#1e3a5f,stroke:#3776ab,color:#fff classDef mob fill:#0d3f3a,stroke:#2dd4bf,color:#fff classDef iot fill:#5c2618,stroke:#ff7a18,color:#fff classDef cloud fill:#064e3b,stroke:#34d399,color:#fff class user,q1,q2,q3 question class desk desk class pwa,mobile,hybrid mob class iot iot class cloud cloud

🎯 5 Deployment Targets — สรุป

TargetเหมาะกับราคายากUser เห็นแบบ
☁️ Cloud Webapp สาธารณะ · dashboard · APIฟรี-$5/เดือน⭐⭐browser URL
💻 Desktop Apptool ออฟไลน์ · ใช้ส่วนตัว · sensitive dataฟรี⭐⭐.exe icon บน desktop
📱 Mobile (PWA / LINE / Web)user อยู่บนมือถือฟรี⭐⭐icon บน home screen / LINE chat
🤖 IoT / Edgeเซ็นเซอร์ · controller · ห่างจาก networkค่า hardware⭐⭐⭐⭐กล่องอยู่ในที่
🔄 Hybridมี user หลาย channelผสม⭐⭐⭐⭐หลายแบบพร้อมกัน

📊 ทางเลือก 1: Streamlit Cloud (ง่ายที่สุด)

Streamlit = library ที่ทำให้ Python กลายเป็น web app ใน 50 บรรทัด · เหมาะมากสำหรับนักศึกษา

# app.py
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt

st.title("📊 PM2.5 Dashboard")

df = pd.read_csv("data.csv")
st.dataframe(df.tail(10))

city = st.selectbox("เลือกเมือง", df["city"].unique())
data = df[df["city"] == city]

fig, ax = plt.subplots()
ax.plot(data["date"], data["pm25"])
ax.set_title(f"PM2.5 — {city}")
st.pyplot(fig)

รัน local: streamlit run app.py → เปิดที่ localhost:8501

Deploy ขึ้น Streamlit Cloud

  1. push code ขึ้น GitHub (public repo)
  2. ไปที่ share.streamlit.io
  3. Login ด้วย GitHub
  4. เลือก repo + ไฟล์ app.py → Deploy
  5. รอ 2-3 นาที → ได้ URL ของตัวเองเช่น username-app.streamlit.app

🐳 ทางเลือก 2: Cloud Run (สำหรับ API)

Cloud Run = Google service ที่รัน Docker container · scale ตาม traffic · pay-per-request

เตรียม Dockerfile

# Dockerfile
FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

CMD ["python", "main.py"]

Deploy steps

  1. ติดตั้ง gcloud CLI (Google Cloud SDK)
  2. gcloud auth login + gcloud config set project YOUR_PROJECT
  3. ใน folder project: gcloud run deploy
  4. ตอบคำถาม (region, port, allow unauthenticated)
  5. ได้ URL เช่น https://my-app-xxxxx.asia-southeast1.run.app
Free tier ของ Cloud Run 2 ล้าน requests/เดือน, 180,000 vCPU-seconds — เกือบทุก project นักศึกษาอยู่ในนี้

💻 ทางเลือก 3: Desktop App (.exe)

เปลี่ยน Python script เป็น .exe ที่ double-click รันได้ · ไม่ต้องลง Python

# ติดตั้ง
pip install pyinstaller

# build
pyinstaller --onefile --windowed app.py

# ผลลัพธ์ใน dist/app.exe
Flagทำอะไร
--onefileรวมทุกอย่างเป็น .exe เดียว
--windowedไม่เปิด terminal (เหมาะกับ GUI)
--icon=app.icoใส่ icon
--add-data "data.csv;."รวม data file

GUI Library


📱 ทางเลือก 4: Mobile — user อยู่บนมือถือ

เพื่อนคุณ "อยู่กับมือถือทั้งวัน" · ของที่ต้องเปิด laptop จะถูกใช้ "แค่ตอน demo" · ของที่อยู่บนมือถือจะใช้ "จริง" · นี่คือ 5 ทางที่ทำได้ โดยไม่ต้องเขียน Swift / Kotlin

📱 5 ทางลง Mobile

วิธีทำยังไงเหมาะกับความยาก
1. Mobile-responsive Web Streamlit / Flask + CSS media queries data dashboard, form
2. PWA (Progressive Web App) Web + manifest.json + service worker → "Install" บน home screen web app ที่ user อยากเปิดบ่อย ⭐⭐
3. LINE Bot LINE Messaging API (W12) — chat = UI notifications, simple workflows, แจ้งเตือน ⭐⭐
4. Telegram Bot python-telegram-bot library กลุ่ม international, automation ⭐⭐
5. Native (BeeWare/Kivy) Python → Android/iOS native bundle app ที่ต้อง access camera/sensor ⭐⭐⭐⭐
เคล็ดลับ — เริ่มที่ "responsive web" + "LINE bot" ก่อน 90% ของ Final Project นักศึกษาไม่ต้อง native · responsive Streamlit ทำงานบนมือถือ 80% เท่ากับ native · LINE bot ทำงานได้แม้ไม่มี internet UX

📲 วิธี 1: Mobile-Responsive Streamlit

# Streamlit auto-responsive อยู่แล้ว · เพิ่ม config สำหรับ phone:
# .streamlit/config.toml
[theme]
primaryColor = "#3776ab"
base = "light"

[browser]
gatherUsageStats = false

# app.py
import streamlit as st
st.set_page_config(
    page_title="My App",
    page_icon="🐰",
    layout="centered",     # ✅ centered = phone-friendly · wide = desktop-only
    initial_sidebar_state="collapsed",   # ✅ ซ่อน sidebar บนมือถือ
)

# ใช้ st.columns + responsive — ดูในมือถือเสมอตอนทดสอบ

📲 วิธี 2: PWA — Install บน Home Screen

เปลี่ยน web app ให้ user "ติดตั้ง" ได้บนมือถือ — เห็น icon เหมือน native app

<!-- index.html (ถ้าใช้ Flask) -->
<link rel="manifest" href="/static/manifest.json">
<meta name="theme-color" content="#3776ab">
<link rel="apple-touch-icon" href="/static/icon-192.png">
// static/manifest.json
{
  "name": "Smart Lab Monitor",
  "short_name": "Lab Mon",
  "start_url": "/",
  "display": "standalone",       // ทำให้ดูเหมือน native app
  "background_color": "#0b1020",
  "theme_color": "#3776ab",
  "icons": [
    {"src": "/static/icon-192.png", "sizes": "192x192", "type": "image/png"},
    {"src": "/static/icon-512.png", "sizes": "512x512", "type": "image/png"}
  ]
}

หลังจาก deploy + เปิดบนมือถือ → Safari/Chrome → "Add to Home Screen" → ได้ icon บน phone

📲 วิธี 3: LINE Bot — UI คือ Chat

ทบทวนจาก W12 · นี่คือ "the Thai-friendly mobile app" · ทุกคนมี LINE อยู่แล้ว

import os # pip install line-bot-sdk (ใน Cursor) # ตัวอย่าง concept: # 1) Bot รับข้อความจาก user def handle_message(user_message: str, user_id: str) -> str: """LINE Webhook เรียก function นี้""" if user_message.lower() == "pm": return "🌫 PM2.5 ตอนนี้: 75 µg/m³ (ปานกลาง)" if user_message.lower() == "help": return "พิมพ์: pm = ดูค่า · alert = เปิดเตือน" return "❓ ไม่เข้าใจ · พิมพ์ help" # 2) Bot ส่ง notification เอง (push) def send_alert(user_id: str, pm_value: int): text = f"⚠️ PM2.5 = {pm_value} — สูง! ใส่ mask" # client.push_message(user_id, TextSendMessage(text=text)) # ทดสอบ logic print(handle_message("pm", "U001")) print(handle_message("xyz", "U001")) print(handle_message("HELP", "U001"))
📌 LINE Bot ใช้ได้บน mobile + desktop พร้อมกัน "App ที่ดีที่สุดของไทย ปี 2026 มักจะมาในรูป LINE bot" — ไม่ต้องลง · ไม่ต้องเปิด browser · user เห็น notification ทันที · เก็บ chat history เป็น log

📲 วิธี 5: BeeWare / Kivy (Advanced)

ถ้าจำเป็นต้อง "native มือถือจริง ๆ" (เช่น ต้อง access camera ในแบบเฉพาะ)

# pip install briefcase
briefcase new        # สร้าง project
briefcase create     # สร้าง bundle สำหรับ Android
briefcase build      # build .apk
briefcase run android   # ทดสอบ
# → output: .apk ที่ลงในมือถือได้

# Kivy ก็ทำได้คล้ายกัน — ใช้ buildozer
# แต่ทั้งคู่ learning curve สูง · ทำเฉพาะถ้าจำเป็น
⚠️ BeeWare/Kivy ไม่เหมาะกับ Final Project นักศึกษาปี 1 ใช้เวลาเรียน 2-3 สัปดาห์ · debug ยาก · iOS ต้องมี Mac + Apple Developer account ($99/ปี) · ส่วนใหญ่ PWA หรือ LINE bot ทำได้ดีกว่าและเร็วกว่า

🤖 ทางเลือก 5: IoT / Edge — Deploy ลงอุปกรณ์

สำหรับ engineering students — "deploy ลงเซ็นเซอร์ / motor / controller" · ไม่ใช่ทุก app อยู่บน cloud · บางอันต้องอยู่ "ในที่" — แท่นบนโรงงาน · ในห้อง lab · บน drone

🔌 4 ระดับของ IoT / Edge

ระดับอุปกรณ์Python ที่ใช้เหมาะกับ
1. Microcontroller ESP32, RP2040 (Pico) MicroPython — Python subset · จำกัด RAM/ROM เซ็นเซอร์เดี่ยว · LED · simple control · battery-powered
2. Single-Board Computer Raspberry Pi 4/5, Orange Pi Python เต็ม + Linux edge gateway · multi-sensor · camera · lightweight server
3. Edge AI Coral TPU, Jetson Nano Python + TensorFlow Lite vision · NLP บน edge · real-time inference
4. Industrial PLC FX5U, Siemens S7 ไม่ใช้ Python · ใช้ ladder logic + Modbus safety-critical · factory · จาก W12 (Modbus API)

🥧 Raspberry Pi — Full Linux + Python

Pi 5 ($80) = mini computer · ติดตั้ง Python · เซ็นเซอร์ผ่าน GPIO · run Flask · ทำได้ทุกอย่างที่ Cloud Run ทำได้

# 1. Flash Raspberry Pi OS
# 2. SSH เข้า
ssh pi@192.168.1.10

# 3. Setup Python project
git clone https://github.com/you/lab-monitor.git
cd lab-monitor
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# 4. รัน background ด้วย systemd service
sudo nano /etc/systemd/system/lab-monitor.service
# /etc/systemd/system/lab-monitor.service
[Unit]
Description=Lab Monitor
After=network.target

[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/lab-monitor
ExecStart=/home/pi/lab-monitor/.venv/bin/python main.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
# Enable + start
sudo systemctl daemon-reload
sudo systemctl enable lab-monitor
sudo systemctl start lab-monitor

# Check status
sudo systemctl status lab-monitor
sudo journalctl -u lab-monitor -f  # ดู log สด
📌 systemd = "auto-start" บน Linux Pi รีบูต → service กลับมาเอง · service พัง → restart อัตโนมัติ · log ใน journalctl · "production-grade" สำหรับ Pi

🔧 MicroPython บน ESP32 — Python บน Microcontroller

ESP32 ($5) รัน Python ได้ผ่าน MicroPython · เซ็นเซอร์ · WiFi · ไม่ต้องมี Linux

# main.py (รันอัตโนมัติเมื่อ ESP32 boot)
import network
import time
from machine import Pin, ADC
import urequests as requests   # MicroPython มี subset

# 1) WiFi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("MyWiFi", "password")
while not wlan.isconnected():
    time.sleep(0.5)
print("Connected:", wlan.ifconfig())

# 2) อ่านเซ็นเซอร์ temperature (LM35) ผ่าน ADC
sensor = ADC(Pin(34))
sensor.atten(ADC.ATTN_11DB)

def read_temp():
    voltage = sensor.read() * 3.3 / 4095
    return voltage * 100  # LM35: 10mV/°C

# 3) Loop: อ่าน + ส่งขึ้น cloud
while True:
    t = read_temp()
    print(f"Temp: {t:.1f}°C")
    try:
        requests.post("https://my-api.run.app/temp", json={"temp": t})
    except Exception as e:
        print("Send fail:", e)
    time.sleep(30)

💡 Upload: ใช้ ampy หรือ Thonny IDE · 1 ครั้งแล้วทำงานตลอด — battery + solar = ยืนได้เป็นเดือน

📡 MQTT — Protocol มาตรฐาน IoT

Sensor → broker → dashboard · ใช้แทน HTTP เมื่อมีเซ็นเซอร์ หลายตัว

# pip install paho-mqtt
import paho.mqtt.client as mqtt

# Publish (ESP32 ส่งค่า)
client = mqtt.Client()
client.connect("broker.hivemq.com", 1883)
client.publish("lab/temp/sensor1", "25.3")

# Subscribe (Cloud server รับค่า)
def on_message(client, userdata, msg):
    print(f"{msg.topic}: {msg.payload.decode()}")

sub = mqtt.Client()
sub.connect("broker.hivemq.com", 1883)
sub.subscribe("lab/temp/+")   # + = wildcard ทุก sensor
sub.on_message = on_message
sub.loop_forever()

🛡 IoT Production Checklist


🧠 Local LLM vs Cloud LLM

หลังจาก 14 สัปดาห์ที่ใช้ AI เป็นเครื่องมือ · ในงานจริงต้องตัดสินใจ: เรียก API หรือรัน LLM ในเครื่องเอง?

☁️ Cloud LLM

Claude API, OpenAI API, Gemini API

  • ✅ เก่งที่สุด (GPT-4, Claude Opus)
  • ✅ ไม่ต้องมี GPU
  • ✅ scale ได้ทันที
  • ❌ จ่ายตาม token (~$0.001-0.03/req)
  • ❌ ส่งข้อมูล "นอกองค์กร"
  • ❌ ต้อง internet
  • ❌ rate limit

🖥️ Local LLM (Ollama)

Llama 3, Qwen, Phi, Mistral

  • ✅ ฟรี · ไม่มี per-request cost
  • ✅ ข้อมูล "ไม่ออกจากเครื่อง"
  • ✅ ไม่ต้อง internet (หลัง download)
  • ✅ ไม่มี rate limit
  • ❌ ต้องการ RAM ≥ 16 GB + GPU 8GB+ ดี
  • ❌ ความสามารถน้อยกว่า GPT-4/Claude
  • ❌ ช้ากว่าเมื่อใช้แค่ CPU

ใช้ Ollama (Local LLM)

# ติดตั้ง Ollama (Win/Mac/Linux): ollama.com
# Download model
ollama pull llama3.2:3b      # 2 GB, ใช้ใน CPU ได้
ollama pull qwen2.5:7b       # 4 GB, ต้องการ GPU

# เรียกจาก Python
pip install ollama
import ollama

response = ollama.chat(model="llama3.2:3b", messages=[
    {"role": "user", "content": "อธิบาย if statement ในภาษาไทยให้คนเริ่มต้น"}
])
print(response["message"]["content"])

ใช้ Cloud LLM (Claude API)

import os
from anthropic import Anthropic

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

msg = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=[{"role": "user", "content": "อธิบาย if statement..."}]
)
print(msg.content[0].text)

เลือกอันไหน?

สถานการณ์เลือก
Final Project demoCloud LLM (เร็ว · เก่ง)
ระบบเก็บข้อมูลส่วนตัว (health, finance)Local LLM (privacy)
App ที่รันบน Raspberry Pi / EdgeLocal LLM (offline)
Batch processing 10,000 รายการLocal LLM (cost)
ต้องการความเข้าใจสูง / reasoningCloud LLM (Claude/GPT)
Auto-grading นักศึกษา 200 คนLocal LLM (cost + privacy)
Hybrid pattern ที่นิยม ใช้ Local LLM สำหรับงาน routine (sentiment, classification, embeddings) + ใช้ Cloud LLM สำหรับงานยาก (reasoning, planning, code)

📊 Monitoring + Crash Reporting — รู้ก่อน user บ่น

Deploy แล้ว "ไม่จบ" · ของพังกลางคืน · ของเร็วลง · ของกินเงิน · ต้องมี ตา ดู · ไม่ใช่ "รอ user มาบ่นใน LINE"

🩺 4 อย่างที่ต้อง Monitor

เรื่องทำไมเครื่องมือฟรี
1. Uptime — ของยังเปิดอยู่มั้ย? ของพังตอนตี 2 · ตื่นมา 8 โมง = user เจอครั้งแรก UptimeRobot · ฟรี 50 monitor
2. Errors — มี exception มั้ย? "ทำงานได้" ≠ "ไม่มี bug" · user 1 คนเจอ error 10 คน Sentry · ฟรี 5K errors/เดือน
3. Performance — ช้ามั้ย? app ช้า 3 วินาที = user ใช้ครั้งเดียวแล้วไม่กลับ Cloud Run dashboard · Streamlit Cloud metrics
4. Usage — ใครใช้ ใช้ตรงไหน? เพื่อปรับ feature ที่ใช้จริง Plausible · privacy-friendly

🛡 Sentry — Crash Reporter (Free 5K errors/month)

# pip install sentry-sdk
import sentry_sdk
import os
sentry_sdk.init(
    dsn=os.getenv("SENTRY_DSN"),
    traces_sample_rate=0.1,    # 10% สำหรับ performance
)

# หลังจากนี้ทุก exception ที่ไม่ catch จะถูกส่งไป Sentry
def my_function():
    try:
        risky_operation()
    except Exception as e:
        sentry_sdk.capture_exception(e)   # ส่งให้ Sentry
        raise   # ยัง propagate เหมือนเดิม

# Sentry dashboard:
# - กราฟ error rate
# - stack trace + user context
# - email/Slack alert เมื่อ spike

💓 UptimeRobot — Heartbeat / Health Check

UptimeRobot ping URL ของคุณทุก 5 นาที · ถ้าตอบ > 30 วินาที หรือ status ≠ 200 → email/SMS เตือน

# เพิ่ม endpoint /health ใน Flask
@app.route("/health")
def health():
    # ตรวจ subsystem ทุกตัวที่สำคัญ
    db_ok = check_database()
    api_ok = check_external_api()

    if db_ok and api_ok:
        return {"status": "ok", "db": "ok", "api": "ok"}, 200
    else:
        return {"status": "degraded", "db": db_ok, "api": api_ok}, 503

📝 Structured Logging — Log เป็น JSON

Log แบบ "ข้อความ" ค้นยาก · Log แบบ JSON = search ได้

import json, logging, sys
from datetime import datetime

class JSONFormatter(logging.Formatter):
    def format(self, record):
        return json.dumps({
            "time": datetime.utcnow().isoformat() + "Z",
            "level": record.levelname,
            "msg": record.getMessage(),
            "module": record.module,
            **getattr(record, "extra", {}),
        })

handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(JSONFormatter())
log = logging.getLogger()
log.addHandler(handler)
log.setLevel(logging.INFO)

log.info("user_action", extra={"extra": {"user_id": "U123", "action": "login"}})
# → {"time":"2026-05-15T...","level":"INFO","msg":"user_action","user_id":"U123","action":"login"}
# Cloud Run / Google Cloud Logging รู้จัก format นี้ · search ตาม field ได้

💰 Cost Management — ไม่ให้ "bill ช็อก"

ตำนานของ developer: "loop ผิด → AWS bill $5000 ใน 1 คืน" · เรื่องจริง · เกิดทุกปีกับนักศึกษา · ตั้งกฎ "safety net" ตั้งแต่วันแรก

🎯 Free Tier — รู้ขีดจำกัด

ServiceFree Tierเมื่อเกิน
Streamlit Cloud1 app · publicไม่มี paid tier · ต้องย้าย
Cloud Run2M req/เดือน · 180K vCPU-sec$0.40/M req หลังจากนั้น
Render WebFree instance · sleep หลัง 15 นาที$7/เดือน เพื่อ always-on
Anthropic Claude$5 credit แรก$0.25-$15 / M tokens (Haiku-Opus)
OpenAI$5 credit แรก$0.15-$10 / M tokens
IQAir API10K calls/เดือน$$ ต้องอัพเกรด
GitHub Actions2000 minutes/เดือน (private)$0.008/นาที
Sentry5K errors/เดือน$26/เดือน

🚨 Budget Alert — ตั้งก่อน Deploy ทุกครั้ง

Serviceวิธีตั้ง alert
Google CloudConsole → Billing → Budgets → "$5 alert at 50%, 90%, 100%"
Anthropicconsole.anthropic.com → Settings → Limits → Monthly spend cap
OpenAIplatform.openai.com → Billing → Usage limits
AWS / AzureBilling alerts ใน console (อย่าใช้ AWS ถ้าไม่ได้บังคับ — bill surprises เกิดบ่อย)
⚠️ 3 ครั้งที่ bill ช็อก — เรียนจากตัวอย่างจริง
  1. Recursive API call — function เรียกตัวเอง · 1 ล้าน calls ใน 1 ชั่วโมง
  2. Infinite loop on LLM — for loop ไม่ break · streaming + cost = $1000/ชม.
  3. Open public endpoint — bot scraper เจอ → ping ทุก 100ms · เกิน rate limit · เกิน bill
กฎ: ตั้ง budget alert ที่ $5 ก่อน deploy ทุก service · ใช้ Haiku/Gemini Flash ไม่ใช่ Opus · --max-instances=10 ใน Cloud Run · rate limit ใน Flask

🛑 Kill Switch — ปิดเร็วเมื่อเกิดเหตุ

# Cloud Run — ปิดทันที
gcloud run services update my-service --max-instances=0

# หรือลบทั้ง service
gcloud run services delete my-service

# Anthropic — disable key ที่ console
# https://console.anthropic.com → API Keys → Delete

# GitHub Actions — disable workflow
# Settings → Actions → "Disable Actions for this repository"
📌 ฝึก kill switch ก่อน deploy ก่อน push production ครั้งแรก · ฝึกใช้ kill switch 1 ครั้ง · รู้ปุ่ม · รู้คำสั่ง · เพราะตอนเกิดเหตุจริง มือสั่น

🌳 Git Workflow ขั้นพื้นฐาน

คำสั่งที่ใช้ทุกวัน

git status                          # ดูสถานะ
git add .                           # stage ทุกอย่าง
git commit -m "message"             # commit
git push                            # ส่งขึ้น GitHub
git pull                            # ดึงล่าสุด

git log --oneline                   # ดูประวัติย่อ
git diff                            # ดูที่เปลี่ยน

git branch feature-x                # สร้าง branch ใหม่
git checkout feature-x              # สลับไป branch
git checkout -b feature-x           # สร้าง + สลับ

# rollback
git reset --hard HEAD               # ทิ้งการเปลี่ยนทั้งหมด
git revert <hash>                  # ทำ commit ใหม่ที่ undo อันเก่า

Pull Request Workflow (สำหรับทีม)

  1. git checkout -b feature-grade-export
  2. แก้ code + commit หลายครั้ง
  3. git push -u origin feature-grade-export
  4. เปิด GitHub → สร้าง Pull Request ขอ merge เข้า main
  5. เพื่อน/อาจารย์ review · comment
  6. แก้ตาม feedback · push เพิ่ม
  7. กด Merge เมื่อทุกคนยอมรับ

🔁 CI/CD — GitHub Actions

"ทุก push → รัน test อัตโนมัติ" · ฟรีบน public repo

สร้าง .github/workflows/test.yml:

name: Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install -r requirements.txt
      - run: pytest

หลังจากนี้ทุก push จะเห็น ✅ หรือ ❌ บน GitHub

📈 Maintenance — ระบบที่อยู่ได้นาน

Checklist ก่อน "ปล่อย" ระบบให้คนอื่นใช้

Changelog template

# Changelog

## [Unreleased]
- ...

## [1.1.0] - 2026-05-20
### Added
- LINE notification เมื่อ PM2.5 > 100
- /status endpoint

### Changed
- เปลี่ยน DB จาก SQLite เป็น PostgreSQL

### Fixed
- Timezone bug ในการเก็บ timestamp

## [1.0.0] - 2026-05-15
- Initial release

🧪 Workshop — Deploy ไป 3 Targets

เอา project ของคุณ (เลือก 1 จาก W07/W10/W12) · deploy ใน 3 channel ที่ user เข้าถึงได้

  1. ☁️ Target 1: Cloud Web — Streamlit Cloud หรือ Render — เพื่อน open URL บน laptop ได้
  2. 📱 Target 2: Mobile เลือก 1 ใน 3:
    • 2a) Mobile-responsive Streamlit + PWA manifest → install บน home screen
    • 2b) LINE bot · webhook คุยกับ logic เดิม
    • 2c) Telegram bot (option ที่ 3)
  3. 💻 Target 3: เลือก 1
    • 3a) Desktop .exe (PyInstaller) สำหรับ Windows user
    • 3b) Raspberry Pi + systemd service (ถ้าคุณมี Pi)
    • 3c) ESP32 MicroPython (ถ้าทำ IoT)
  4. 📊 ตั้ง Monitoring — Sentry สำหรับ errors · UptimeRobot สำหรับ uptime · log ผ่าน Cloud Run console
  5. 💰 ตั้ง Budget Alert ทุก service — $5 alert ที่ 50%, 90%, 100% · ตั้งทุกตัวที่ใช้ (Claude, OpenAI, GCP, ...)
  6. 🔁 เพิ่ม CI/CD — GitHub Actions รัน pytest + deploy auto บน push main
  7. 📝 Changelog v1.0.0 — เริ่มที่ v1.0.0 · log แต่ละ deploy ใน CHANGELOG.md
  8. 🧪 "Fresh clone" test — ขอเพื่อน 1 คน clone repo บนเครื่องเขา · ทำตาม README · ต้องรันได้
  9. 📱 User test บน mobile จริง — ส่ง LINE/URL ให้เพื่อน 3 คน · เปิดบนมือถือ · 2 ใน 3 ต้อง "ใช้สำเร็จ"
  10. Bonus — เปรียบเทียบ Local vs Cloud LLM — Ollama llama3.2:3b vs Claude Haiku · เปรียบเทียบ output + speed + cost ใน task เดียวกัน

ข้อผิดที่พบบ่อย

Commit .env ขึ้น GitHub — secret หลุดทันที · rotate key + ใช้ git-secrets ป้องกัน
Deploy ครั้งแรก ทำ branch main ทำ staging branch ก่อนเสมอ · ผ่านแล้วค่อย merge main
ไม่ทดสอบหลัง deploy Cloud มี environment ต่างกับ local · ต้องทดสอบจาก URL จริง
Cloud Run cost surprise ลืม set max instance → traffic spike → bill หลายพันบาท · ตั้ง --max-instances=10

ส่งงานสัปดาห์นี้

Reference จาก slide เดิม

เนื้อหานี้เป็น Mainidea Foundation 14 (Cloud + Deployment) + 20 (Version + Change) ที่ไม่อยู่ใน slide เดิม — เป็นทักษะที่ขาดไม่ได้สำหรับ Final Project