ข้ามไปยังเนื้อหา
KoishiAI
EN
← กลับไปหน้าสารบัญ
บทที่ 12 / 12 · 24 เมษายน 2569

แก้ Loop จัดการ Error และรับมือ Incident

หาสาเหตุรากของ loop ด้วย 5 Whys, anti-loop pattern, profiling, error taxonomy, retry, circuit breaker, graceful shutdown และการรับมือ incident บน production

คู่มือชุดนี้ลิขสิทธิ์ All Rights Reserved — อ่านได้ฟรี แต่คัดลอก/เผยแพร่ซ้ำต้องขออนุญาต

บทที่ 12 | แก้ Loop จัดการ Error และรับมือ Incident กลุ่มเป้าหมาย: Developer ทุกระดับที่ต้องการให้ระบบล้มแล้วฟื้นได้ และไม่ล้มซ้ำด้วยสาเหตุเดิม

การแก้ปัญหา Loop แบบลึก — Root Cause Analysis

บทที่ 4 สอน Protocol หยุด Loop บทนี้ไปลึกกว่านั้น โดยสอนวิธีวิเคราะห์ต้นเหตุ (Root Cause) อย่างเป็นระบบ และออกแบบโค้ดล่วงหน้าให้เกิด Loop น้อยที่สุด

Framework 5 Whys สำหรับ Loop Debugging

เทคนิค “5 Whys” จาก Toyota Production System ใช้ได้ผลดีมากกับการ debug ด้วย Claude ไม่จำเป็นต้องถาม “ทำไม” ครบ 5 ครั้งทุกครั้ง แค่ถามจนถึง root cause จริงๆ

ตัวอย่าง: แก้บักด้วย 5 Whys จริง

# สถานการณ์: Payment ล้มเหลวบ้างประปราย
 
> Why 1: ทำไม payment ถึง fail?
  → Stripe API return error "card_declined"
 
> Why 2: ทำไม card ถึงถูก decline?
  → Stripe บอกว่า insufficient_funds แต่ user บอกว่าเงินพอ
 
> Why 3: ทำไม Stripe ถึงเห็น insufficient_funds ทั้งที่เงินพอ?
  → ดู request payload พบว่า amount ที่ส่งไปเป็น 1000
     แต่ควรเป็น 10.00 (หน่วยต่างกัน: บาท vs สตางค์)
 
> Why 4: ทำไม amount ถึงส่งผิดหน่วย?
  → Code ใน checkout.ts ไม่ได้ convert จาก บาท → สตางค์
     ก่อนส่งให้ Stripe (Stripe ใช้หน่วยที่เล็กที่สุดของสกุลเงิน)
 
> Why 5: ทำไม conversion ถึงขาดไป?
  → Developer อ่าน doc ผิด คิดว่า Stripe ใช้หน่วยหลัก
     และไม่มี unit test ที่ verify ค่า amount
 
# Root Cause: ขาด unit test + documentation ไม่ชัด
# Fix จริง: แก้ conversion + เพิ่ม test + เพิ่ม comment ใน CLAUDE.md

Prompt ให้ Claude ทำ 5 Whys

> ทำ 5 Whys Analysis สำหรับบักนี้:
  [อธิบายอาการบัก]
 
  ทำแบบนี้:
  1. Why 1: อธิบาย symptom ที่เห็น
  2. Why 2-5: ถามต่อเรื่อยๆ จาก answer ก่อนหน้า
  3. หยุดเมื่อถึง root cause จริง (ไม่ต้องครบ 5 ถ้าเจอก่อน)
  4. แยกระหว่าง "Fix Symptom" กับ "Fix Root Cause"
  5. เสนอ solution สำหรับ root cause
  6. เสนอวิธีป้องกันไม่ให้เกิดซ้ำ (systematic fix)

Debugging Playbook — คู่มือแก้บักแต่ละประเภท

แทนที่จะ describe ปัญหากว้างๆ ให้ระบุประเภทบักก่อน แล้วใช้ playbook ที่เหมาะสม:

Playbook A: Logic Bug — ผลลัพธ์ผิด แต่ไม่มี Error

ยากที่สุดในการ debug เพราะไม่มี error message ให้ follow Claude มักวน loop กับบักประเภทนี้

> Logic Bug Analysis:
  สิ่งที่เห็น: [input] → [actual output]
  สิ่งที่ต้องการ: [input] → [expected output]
 
  ให้ทำดังนี้:
  1. Trace execution path: อธิบายทีละ step ว่า code ทำอะไร
     ตั้งแต่รับ input จนถึงส่ง output
 
  2. หา divergence point: ตรงไหนที่ actual กับ expected เริ่มต่างกัน?
 
  3. เพิ่ม assertion checks ตลอดทาง:
     console.assert(value === expected, `Step N: got ${value}, want ${expected}`)
 
  4. รัน และดูว่า assertion ล้มเหลวที่ step ไหน
 
  อย่าแก้โค้ดจนกว่าจะ identify divergence point ได้
Playbook B: Performance Bug — ช้าผิดปกติ
> Performance Investigation:
  อาการ: [ส่วนไหนช้า] ช้าประมาณ [X วินาที/ms]
  Target: ต้องเร็วกว่า [Y วินาที/ms]
 
  ทำตามลำดับนี้:
 
  Phase 1 — Measure ก่อนแก้:
  เพิ่ม timing ใน @[file]:
  - console.time("total")
  - console.time("db-query")
  - console.time("data-transform")
  - console.time("response")
  แล้วรัน 3 ครั้ง บันทึกค่าเฉลี่ย
 
  Phase 2 — Identify bottleneck:
  step ไหนใช้เวลามากที่สุด?
 
  Phase 3 — Optimize เฉพาะ bottleneck:
  อย่า optimize ส่วนที่เร็วอยู่แล้ว
 
  Phase 4 — Measure อีกครั้ง:
  เปรียบเทียบก่อน/หลัง ต้อง [Y ms] ตาม target
Playbook C: Memory Leak — RAM ค่อยๆ เพิ่มจนระบบช้า
> Memory Leak Investigation:
  อาการ: memory เพิ่มขึ้นเรื่อยๆ เมื่อใช้งานนาน
 
  Step 1 — Confirm มี leak จริง:
  เพิ่ม memory monitoring:
  setInterval(() => {
    const mem = process.memoryUsage();
    console.log(`RSS: ${Math.round(mem.rss/1024/1024)}MB`,
                `Heap: ${Math.round(mem.heapUsed/1024/1024)}MB`);
  }, 5000);
 
  Step 2 — หา pattern:
  memory เพิ่มหลัง action ไหน?
  ทุก request? หลัง upload? หลัง WebSocket connect?
 
  Step 3 — วิเคราะห์ @[file] หา patterns เหล่านี้:
  - Event listeners ที่ไม่ได้ removeEventListener
  - setTimeout/setInterval ที่ไม่ได้ clearTimeout/clearInterval
  - Global variables ที่เก็บ array/object ไว้ตลอด
  - Cache ที่ไม่มี eviction policy
  - Closure ที่ capture object ใหญ่
 
  Step 4 — Fix และ verify ว่า memory คงที่หลังรัน 30 นาที
Playbook D: Concurrency Bug — ผิดเฉพาะ high traffic
> Concurrency Analysis:
  อาการ: ปกติดี แต่พอมี concurrent users จะมีปัญหา
 
  Step 1 — Reproduce locally:
  สร้าง load test script ที่ส่ง concurrent requests:
  for (let i = 0; i < 50; i++) {
    promises.push(fetch("/api/[endpoint]"));
  }
  await Promise.all(promises);
 
  Step 2 — วิเคราะห์ shared state:
  หา variables ใน @[file] ที่:
  - เป็น module-level (ไม่ใช่ request-level)
  - ถูก read และ write ใน handler เดียวกัน
  - ไม่มี locking/synchronization
 
  Step 3 — เสนอ fix:
  - Database-level locking: SELECT FOR UPDATE
  - Optimistic locking: version field + retry
  - Queue: serialize concurrent operations
  - Idempotency key: ป้องกัน duplicate processing
 
  อธิบาย tradeoffs ของแต่ละ option ก่อนเลือก

Anti-Loop Patterns — ออกแบบให้ Loop เกิดน้อยลง

วิธีที่ดีที่สุดในการหลีกเลี่ยง Loop คือออกแบบโค้ดและ prompt ให้ดีตั้งแต่ต้น:

Pattern 1: Contract-First Development

กำหนด Interface และ Contract ชัดเจนก่อน implement ทำให้ Claude มี specification ที่ชัดเจน ไม่ต้องเดา:

# แทนที่จะบอก "สร้าง payment service"
# ให้เขียน contract ก่อน แล้วให้ Claude implement
 
> นี่คือ Contract ที่ต้องการ:
 
  // Input
  interface ProcessPaymentInput {
    userId: string;
    amount: number;        // หน่วย: บาท (เช่น 99.50)
    currency: "THB" | "USD";
    description: string;
    idempotencyKey: string; // ป้องกัน duplicate charge
  }
 
  // Success Output
  interface ProcessPaymentSuccess {
    success: true;
    transactionId: string;
    amount: number;         // ยืนยัน amount ที่ charge จริง
    timestamp: Date;
  }
 
  // Error Output
  interface ProcessPaymentError {
    success: false;
    errorCode: "CARD_DECLINED" | "INSUFFICIENT_FUNDS" |
               "INVALID_CARD" | "PROCESSING_ERROR";
    message: string;       // สำหรับ log (ไม่แสดง user)
    userMessage: string;   // สำหรับแสดง user (ภาษาไทย)
    retryable: boolean;    // บอก client ว่า retry ได้ไหม
  }
 
  implement processPayment(input: ProcessPaymentInput)
  : Promise<ProcessPaymentSuccess | ProcessPaymentError>
  ใช้ Stripe เป็น payment processor
  convert amount จาก บาท → สตางค์ก่อนส่ง Stripe

Pattern 2: Error Budget Strategy

กำหนดล่วงหน้าว่า error ประเภทไหน Claude ควร retry เองได้ และประเภทไหนต้องหยุดแล้วถาม:

# เพิ่มใน CLAUDE.md
## 🔄 Error Handling Strategy
 
### Claude retry เองได้ (ไม่ต้องถาม):
- TypeScript type error → แก้ type ให้ถูกต้อง
- Import path ผิด → แก้ path
- Missing await → เพิ่ม await
- Unused variable → ลบออก
 
### Claude ต้องถามก่อน retry:
- Logic error (ผลลัพธ์ไม่ตรงที่คาด) → อธิบายความเข้าใจก่อน
- Database schema mismatch → แสดง schema ที่เห็น แล้วถาม
- External API error → แสดง error code + ถาม intent
 
### Claude ต้องหยุดและรายงาน:
- Security-related issue → อย่าแก้เองเด็ดขาด
- แก้เกิน 2 รอบแล้วยังไม่ได้ → สรุปสิ่งที่ลอง + ขอข้อมูลเพิ่ม
- ต้องแก้ไฟล์นอก scope → ขออนุมัติก่อน

Pattern 3: Checkpoint System

แบ่งงานเป็น checkpoint เล็กๆ และ verify แต่ละ checkpoint ก่อนไปต่อ ป้องกัน snowball effect ที่บักสะสม:

> สร้าง User Registration System ด้วย Checkpoint:
 
  Checkpoint 1: Database schema
  - สร้าง Prisma schema สำหรับ User
  - รัน migration
  - ✓ verify: npx prisma db pull แล้วดู schema
  STOP → รอ approve ก่อนไป Checkpoint 2
 
  Checkpoint 2: Validation layer
  - สร้าง Zod schema สำหรับ registration input
  - เขียน unit test ครอบคลุม valid/invalid cases
  - ✓ verify: npm test ต้องผ่านทั้งหมด
  STOP → รอ approve ก่อนไป Checkpoint 3
 
  Checkpoint 3: Service layer
  - สร้าง registerUser() function
  - hash password, check duplicate email
  - ✓ verify: integration test กับ test database
  STOP → รอ approve ก่อนไป Checkpoint 4
 
  Checkpoint 4: API Route
  - สร้าง POST /api/auth/register
  - ✓ verify: curl test ทุก case
 
  ถ้า checkpoint ไหนล้มเหลว → หยุด ไม่ไป checkpoint ถัดไป

การใช้ Claude Debug Claude

เทคนิคที่ทรงพลังมาก: ให้ Claude ตัวใหม่วิเคราะห์ปัญหาโดยไม่รู้ว่า Claude ตัวไหนเขียนโค้ดนั้น

# Session 1: Claude A สร้าง code และเจอบัก
# Claude A แก้ไม่ได้ใน 2 รอบ
 
# เปิด Session ใหม่ (Claude B)
> [Fresh session - ไม่มี context เดิม]
 
  ผมได้รับ code นี้มาและมันมีบัก:
  [วาง code ทั้งหมด]
 
  อาการ: [อธิบาย]
  Error: [copy error]
 
  วิเคราะห์ code นี้จากมุมมองภายนอก:
  1. สิ่งที่ code นี้พยายามทำคืออะไร?
  2. เห็น design issue อะไรไหม?
  3. บัคน่าจะอยู่ที่ไหน?
  4. ถ้าคุณเขียน code นี้ใหม่จาก scratch
     จะเปลี่ยน approach อะไร?
 
# Claude B มักเห็นปัญหาที่ Claude A มองข้ามไป
# เพราะไม่มี cognitive bias จากการเขียนโค้ดนั้นเอง

💡 เมื่อไหร่ควรใช้ Claude Debug Claude
ใช้เมื่อ: Claude วน loop แก้ไม่ได้เกิน 2 รอบ
ใช้เมื่อ: โค้ดซับซ้อนมากจนอธิบายยาก
ใช้เมื่อ: ต้องการ second opinion ก่อน merge
ไม่ต้องใช้: บักง่ายๆ หรือแก้ได้ในรอบแรก

Production Quality — ตั้งแต่เริ่มต้นจนถึง Live

Production code ไม่ได้หมายความแค่ “รันได้” แต่หมายถึงโค้ดที่ reliable, maintainable, observable และ recoverable ส่วนนี้จะไล่ทุกขั้นตอนตั้งแต่ design จนถึงผู้ใช้งานจริง

ขั้นตอนที่ 1 — Requirements & Design

งานส่วนใหญ่ล้มเหลวที่ขั้นตอนนี้ ไม่ใช่ที่ implementation ให้ Claude ช่วย clarify requirements ก่อนเสมอ

# Prompt สำหรับ clarify requirements
> ก่อน implement ขอ clarify requirements:
 
  Feature ที่ต้องการ: [อธิบาย]
 
  ช่วยถามคำถามที่จำเป็นก่อน implement:
  1. Happy path: ขั้นตอนปกติเป็นอย่างไร?
  2. Edge cases: กรณีพิเศษที่ต้อง handle?
  3. Error cases: เกิดอะไรขึ้นถ้า X ล้มเหลว?
  4. Performance: ต้องรองรับ concurrent users กี่คน?
  5. Security: ใครเข้าถึงได้? Data sensitivity ระดับไหน?
  6. Rollback: ถ้า feature นี้พัง rollback ยังไง?
 
  หลังจาก clarify แล้ว สรุป acceptance criteria
  ที่ใช้ verify ว่า feature เสร็จและถูกต้อง

Design Document ที่ Claude ช่วยสร้าง

> สร้าง Design Document สำหรับ [Feature] ประกอบด้วย:
 
  ## Summary
  อธิบาย feature ใน 2-3 ประโยค
 
  ## Architecture
  - Data flow diagram (text format)
  - Components ที่เกี่ยวข้อง
  - External dependencies
 
  ## API Contract
  - Endpoints ใหม่ (input/output types)
  - Error responses
 
  ## Database Changes
  - Tables/columns ที่เพิ่ม/แก้
  - Migration strategy
  - Rollback plan
 
  ## Testing Strategy
  - Unit tests ที่ต้องเขียน
  - Integration tests
  - E2E scenarios
 
  ## Risks & Mitigations
  - ความเสี่ยงที่เห็น
  - วิธีลด risk
 
  ## Acceptance Criteria
  ✓ [criterion 1]
  ✓ [criterion 2]

ขั้นตอนที่ 2 — Implementation with Quality Gates

แต่ละ phase ของ implementation มี Quality Gate ที่ต้องผ่านก่อนไปต่อ Claude ช่วย verify ได้ทุก gate

Phaseงานที่ทำQuality GateClaude ช่วยได้
Data LayerSchema, migrations, indexesMigration รันได้, rollback ได้เขียน migration + test
Business LogicCore functions, validationUnit tests ผ่าน 100%เขียน tests + implement
API LayerRoutes, middleware, authIntegration tests ผ่านเขียน tests + routes
UI LayerComponents, forms, statesE2E tests ผ่าน key flowsเขียน Playwright tests
PerformanceQuery optimization, cachingLoad test ผ่าน targetวิเคราะห์ bottleneck
SecurityAuth check, input validationSecurity checklist ผ่านรัน OWASP checklist

ขั้นตอนที่ 3 — Testing Strategy แบบสมบูรณ์

Testing คือส่วนที่ Vibe Coder มักข้ามมากที่สุด แต่เป็นส่วนที่ทำให้ production code แตกต่างจาก prototype

Unit Testing ด้วย Vitest + Claude
# ให้ Claude เขียน comprehensive unit tests
> เขียน unit tests สำหรับ @src/lib/pricing.ts
  ครอบคลุม ALL cases:
 
  1. Happy paths (input ถูกต้อง → output ที่คาด)
  2. Edge cases:
     - จำนวนที่ boundary: 0, negative, MAX_SAFE_INTEGER
     - null/undefined inputs
     - empty arrays/objects
  3. Error cases:
     - invalid input type
     - business rule violations
  4. Precision cases:
     - floating point (0.1 + 0.2 ≠ 0.3)
     - currency rounding
 
  ใช้ Vitest, organize เป็น describe blocks
  ชื่อ test ต้อง readable: "should return X when Y"
 
# ตัวอย่าง output ที่ดี
describe("calculateDiscount", () => {
  describe("percentage discount", () => {
    it("should apply 10% discount to 1000", () => {
      expect(calculateDiscount(1000, { type: "percent", value: 10 }))
        .toBe(900);
    });
    it("should handle 0% discount", () => {...});
    it("should cap at 100% discount", () => {...});
  });
  describe("fixed discount", () => {...});
  describe("edge cases", () => {...});
});
Integration Testing ด้วย Supertest
> เขียน integration tests สำหรับ POST /api/orders
  ใช้ Supertest + test database
 
  Test cases:
  1. ✅ Success: create order ถูกต้อง → 201 + order object
  2. ❌ Unauthorized: ไม่มี token → 401
  3. ❌ Validation: ข้อมูลไม่ครบ → 400 + error details
  4. ❌ Business Rule: สินค้าหมด stock → 422 + user message
  5. ⚡ Idempotency: ส่ง request เดิม 2 ครั้ง → สร้าง order เดียว
  6. 🔒 Authorization: user ดู order ของคนอื่น → 403
 
  Setup:
  - เริ่ม test database ที่สะอาดก่อนแต่ละ test
  - ล้าง database หลังแต่ละ test
  - mock Stripe API (ไม่ call real API ใน test)
 
# ตัวอย่าง
describe("POST /api/orders", () => {
  beforeEach(async () => {
    await db.cleanDatabase();
    await db.seed.basicProducts();
  });
 
  it("should create order and return 201", async () => {
    const res = await request(app)
      .post("/api/orders")
      .set("Authorization", `Bearer ${testToken}`)
      .send({ items: [{ productId: "p1", quantity: 2 }] });
 
    expect(res.status).toBe(201);
    expect(res.body.id).toBeDefined();
    expect(res.body.total).toBe(200);
  });
});
E2E Testing ด้วย Playwright
> เขียน E2E tests สำหรับ checkout flow
  ใช้ Playwright + staging environment
 
  Critical flows ที่ต้อง test:
  1. Happy path: เลือกสินค้า → checkout → payment → confirmation
  2. Failed payment: กรอก card ผิด → error message → retry
  3. Out of stock: สินค้าหมดระหว่าง checkout → error + redirect
  4. Session timeout: ค้างนาน → session หมด → redirect to login
 
# ตัวอย่าง Playwright test
test("complete checkout flow", async ({ page }) => {
  await page.goto("/products");
 
  // เลือกสินค้า
  await page.click("[data-testid=product-1]");
  await page.click("[data-testid=add-to-cart]");
 
  // ไป checkout
  await page.click("[data-testid=cart-icon]");
  await page.click("[data-testid=checkout-btn]");
 
  // กรอก payment
  await page.fill("[data-testid=card-number]", "4242424242424242");
  await page.fill("[data-testid=card-expiry]", "12/25");
  await page.fill("[data-testid=card-cvc]", "123");
  await page.click("[data-testid=pay-btn]");
 
  // verify confirmation
  await expect(page.locator("[data-testid=order-confirmed]"))
    .toBeVisible({ timeout: 10000 });
});

ขั้นตอนที่ 4 — Security Checklist

Security เป็นสิ่งที่ Vibe Coder มักลืมมากที่สุด ใช้ checklist นี้ทุกครั้งก่อน deploy:

# ให้ Claude รัน Security Audit
> รัน Security Audit สำหรับ code ที่เพิ่งเขียน
  ตรวจสอบ OWASP Top 10 ที่เกี่ยวข้อง:
 
  □ Injection:
    - SQL: ใช้ parameterized queries ทั้งหมด?
    - NoSQL: sanitize MongoDB operators?
    - Command: exec() หรือ shell command ใช้ input โดยตรงไหม?
 
  □ Authentication:
    - ทุก route ที่ sensitive มี auth check?
    - JWT validation ถูกต้อง (verify signature, expiry)?
    - Rate limiting บน login endpoint?
 
  □ Authorization (IDOR):
    - User ดูแก้ข้อมูลตัวเองเท่านั้น?
    - ตรวจสอบ ownership ก่อน return data?
 
  □ Sensitive Data:
    - Password hashed ด้วย bcrypt (cost >= 10)?
    - ไม่ return sensitive fields (password, token)?
    - Log ไม่มี PII หรือ credentials?
 
  □ Input Validation:
    - Validate และ sanitize ทุก input?
    - File upload: check type, size, scan content?
    - URL parameters: validate format?
 
  □ Error Handling:
    - Error messages ไม่ leak internal info?
    - Stack traces ไม่ถูกส่งไป client?
 
  สำหรับแต่ละรายการ: ✅ ผ่าน / ❌ พบปัญหา (อธิบาย)

ขั้นตอนที่ 5 — Performance Testing และ Benchmarking

ก่อน deploy ต้องรู้ว่าโค้ดรองรับ load ได้มากแค่ไหน และ bottleneck อยู่ที่ไหน

Load Testing ด้วย k6
# ให้ Claude เขียน k6 load test script
> เขียน k6 load test สำหรับ API ที่สำคัญ
 
  Target: /api/products/search
  Expected: p95 latency < 500ms ที่ 100 concurrent users
 
// k6 script ที่ Claude จะสร้าง
import http from "k6/http";
import { check, sleep } from "k6";
 
export const options = {
  stages: [
    { duration: "30s", target: 10 },   // warm up
    { duration: "1m",  target: 100 },  // ramp to target
    { duration: "3m",  target: 100 },  // steady state
    { duration: "30s", target: 0 },    // ramp down
  ],
  thresholds: {
    http_req_duration: ["p(95)<500"],  // 95% ต้อง < 500ms
    http_req_failed: ["rate<0.01"],    // error rate < 1%
  },
};
 
export default function() {
  const params = {
    headers: { Authorization: `Bearer ${__ENV.TEST_TOKEN}` },
  };
 
  const searchTerms = ["shirt", "pants", "shoes", "hat"];
  const term = searchTerms[Math.floor(Math.random() * searchTerms.length)];
 
  const res = http.get(`${__ENV.BASE_URL}/api/products/search?q=${term}`, params);
 
  check(res, {
    "status 200": (r) => r.status === 200,
    "has products": (r) => JSON.parse(r.body).products.length >= 0,
    "response time OK": (r) => r.timings.duration < 500,
  });
 
  sleep(1);
}
 
# รัน: k6 run -e BASE_URL=https://staging.myapp.com \
#          -e TEST_TOKEN=xxx script.js
Database Query Performance ด้วย EXPLAIN ANALYZE
> วิเคราะห์ performance ของ query นี้:
  [แปะ Prisma query]
 
  สร้าง raw SQL EXPLAIN ANALYZE version
  เพื่อดู execution plan:
  1. Seq Scan หรือ Index Scan?
  2. estimated vs actual rows ต่างกันมากไหม?
  3. สิ้นเปลือง memory ที่ step ไหน?
 
  จากนั้นเสนอ:
  - Index ที่ควรเพิ่ม
  - Query rewrite ถ้าจำเป็น
  - Caching strategy ถ้าเหมาะสม
 
# ตัวอย่าง EXPLAIN ANALYZE output ที่ Claude วิเคราะห์
EXPLAIN ANALYZE
SELECT u.*, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created_at > NOW() - INTERVAL "30 days"
GROUP BY u.id;
 
# Claude จะเห็น Seq Scan บน users และเสนอ:
# CREATE INDEX idx_users_created_at ON users(created_at DESC);

ขั้นตอนที่ 6 — Observability: Logging, Metrics, Tracing

โค้ดที่ดีต้องสังเกตได้ เมื่อเกิดปัญหาใน production ต้องหาสาเหตุได้ภายในนาที ไม่ใช่ชั่วโมง

Structured Logging
> เพิ่ม structured logging ใน @src/lib/logger.ts
  Requirements:
  - ใช้ pino (เร็วกว่า winston 10x)
  - Log format: JSON (เพื่อ parse ได้)
  - Log levels: error, warn, info, debug
  - ทุก log ต้องมี: timestamp, level, service,
    requestId, userId (ถ้ามี), message, data
  - ห้าม log: passwords, tokens, credit card
  - Production: log ระดับ info ขึ้นไปเท่านั้น
 
# ตัวอย่าง logger ที่ดี
logger.info({
  event: "payment.processed",
  requestId: ctx.requestId,
  userId: user.id,
  orderId: order.id,
  amount: order.total,
  duration: timer.elapsed(),
  // ไม่มี card number!
}, "Payment processed successfully");
 
> เพิ่ม request ID middleware ที่ inject requestId
  ใน every request context เพื่อ trace across services
Health Check Endpoint
> สร้าง /api/health endpoint สำหรับ monitoring
  ต้องตรวจสอบ:
  □ Database: ping ได้? query ง่ายๆ รันได้?
  □ Redis (ถ้าใช้): ping ได้?
  □ External APIs: Stripe, SendGrid reachable?
  □ Disk space: เหลือ > 20%?
  □ Memory: heap usage < 80%?
 
  Response format:
  {
    "status": "healthy" | "degraded" | "unhealthy",
    "timestamp": "2025-01-15T10:00:00Z",
    "version": "1.4.2",
    "checks": {
      "database": { "status": "ok", "latency": 5 },
      "redis":    { "status": "ok", "latency": 1 },
      "stripe":   { "status": "ok", "latency": 120 }
    }
  }
 
  - 200: healthy หรือ degraded (บาง service ช้าแต่ยังทำงานได้)
  - 503: unhealthy (core service ล้มเหลว)
  - Timeout ของแต่ละ check: 2 วินาที

ขั้นตอนที่ 7 — Deployment Strategy

การ deploy ที่ดีต้องมีแผน rollback ชัดเจน และ minimize downtime

Zero-downtime Deployment Checklist
> สร้าง deployment checklist สำหรับ [feature]
  โดย Claude ช่วยระบุ:
 
  ## Pre-deployment
  □ Tests ทั้งหมดผ่าน (unit, integration, e2e)
  □ Database migration reviewed (backward compatible?)
  □ Environment variables ใหม่ set ใน production?
  □ Feature flags configured?
  □ Monitoring alerts set up?
 
  ## Migration Strategy
  (สำคัญ: migration ต้อง backward compatible อย่างน้อย 1 version)
  Step 1: Deploy migration (เพิ่ม column ใหม่, nullable)
  Step 2: Deploy app (ใช้ column ใหม่)
  Step 3: Backfill data เก่า (background job)
  Step 4: Make column NOT NULL (next release)
 
  ## Deployment Steps
  1. Deploy to staging → smoke test
  2. Deploy to production (canary: 5% traffic)
  3. Monitor 15 นาที (error rate, latency)
  4. Expand to 50% → monitor
  5. Full rollout → monitor 1 ชั่วโมง
 
  ## Rollback Plan
  Trigger: error rate > 1% หรือ p95 > 2s
  Time to rollback: < 5 นาที
  Command: [ระบุคำสั่ง rollback จริง]

QA Testing — การทดสอบก่อน Production

QA (Quality Assurance) คือกระบวนการตรวจสอบว่า feature ทำงานถูกต้องในทุกสถานการณ์ Claude ช่วยออกแบบและรัน QA ได้อย่างเป็นระบบ

QA Test Plan ด้วย Claude

> สร้าง QA Test Plan สำหรับ [Feature Name]
 
  ข้อมูล feature:
  [อธิบาย feature ที่สร้าง]
 
  สร้าง test plan ที่ครอบคลุม:
 
  ## Functional Testing
  - Happy path scenarios (ทุก user journey)
  - Negative scenarios (input ผิด, permission ไม่พอ)
  - Boundary testing (min/max values)
 
  ## Browser/Device Compatibility
  - Chrome, Firefox, Safari (latest)
  - Mobile: iOS Safari, Android Chrome
  - Responsive: 320px, 768px, 1280px, 1920px
 
  ## Accessibility Testing
  - Keyboard navigation ครบ?
  - Screen reader compatible?
  - Color contrast WCAG 2.1 AA?
  - Focus indicators visible?
 
  ## Data Integrity
  - ข้อมูลถูก save ถูกต้อง?
  - ข้อมูลแสดงถูกต้องหลัง refresh?
  - Concurrent users: race condition?
 
  ## Format: Test Case Table
  | ID | Scenario | Steps | Expected | Priority |

Automated QA Checklist สำหรับ Vibe Coding

ใช้ checklist นี้ทุกครั้งก่อน merge PR:

# .claude/commands/qa-check.md
# QA Pre-merge Checklist
 
# รัน automated checks ทั้งหมดและรายงานผล
 
1. รัน: npm run typecheck
   ✓ ต้องไม่มี TypeScript errors
 
2. รัน: npm run lint
   ✓ ต้องไม่มี ESLint errors (warnings OK)
 
3. รัน: npm test
   ✓ ต้องผ่าน 100% (0 failures)
   ✓ coverage ต้อง >= 70% สำหรับ new code
 
4. รัน: npm run build
   ✓ ต้อง build สำเร็จ ไม่มี errors
 
5. รัน Security check:
   npm audit --audit-level=high
   ✓ ต้องไม่มี high/critical vulnerabilities
 
6. ตรวจสอบ git diff --stat
   ✓ ไม่มี .env ถูก commit
   ✓ ไม่มี console.log ที่ไม่จำเป็น
   ✓ ไม่มี TODO ที่ should not be in prod
 
7. ทดสอบ manual บน localhost:
   - Happy path ที่สำคัญที่สุด
   - Error case ที่น่าจะเกิดบ่อย
 
รายงานผลเป็น: ✅ ผ่าน / ❌ ล้มเหลว (พร้อมรายละเอียด)

Visual Regression Testing

ตรวจสอบว่า UI ไม่เปลี่ยนโดยไม่ตั้งใจ หลังจาก refactor หรือ upgrade dependency:

# ติดตั้ง Playwright screenshot testing
npm install @playwright/test
 
> เขียน visual regression tests สำหรับหน้าสำคัญ:
  - Homepage
  - Product listing
  - Checkout flow (3 steps)
  - User profile
 
// visual.test.ts
import { test, expect } from "@playwright/test";
 
test("homepage visual", async ({ page }) => {
  await page.goto("/");
  await page.waitForLoadState("networkidle");
  await expect(page).toHaveScreenshot("homepage.png", {
    maxDiffPixels: 100,  // อนุญาต pixel ต่างได้ 100 pixels
  });
});
 
# ครั้งแรก: รันเพื่อสร้าง baseline
npx playwright test visual --update-snapshots
 
# ครั้งต่อไป: เปรียบเทียบกับ baseline
npx playwright test visual
# ถ้า UI เปลี่ยน → test fail → ต้อง approve หรือ fix

A/B Testing และ Feature Flags

A/B Testing คือการทดสอบ feature สองแบบพร้อมกันกับผู้ใช้จริง เพื่อวัดว่าแบบไหนดีกว่า Feature Flags ช่วย control ว่าใครเห็น feature ไหน

Feature Flags — Control การ Release

Feature Flags ช่วยให้ deploy code ก่อน แล้วค่อย enable สำหรับผู้ใช้ทีหลัง ลด risk ของการ deploy

# ให้ Claude implement Feature Flag system
> สร้าง Feature Flag system สำหรับโปรเจค
  Requirements:
  - Store flags ใน database (เปลี่ยนได้ไม่ต้อง redeploy)
  - Target: ทุก user / user ที่ระบุ / percentage
  - Admin UI: เปิด/ปิด flag ได้ทันที
  - Cache: 1 นาที (ไม่ hit DB ทุก request)
 
  Schema:
  model FeatureFlag {
    id          String   @id @default(cuid())
    key         String   @unique  // "new-checkout"
    enabled     Boolean  @default(false)
    rolloutPct  Int      @default(0)   // 0-100%
    userIds     String[] // specific users
    description String
    createdAt   DateTime @default(now())
    updatedAt   DateTime @updatedAt
  }
 
  Usage ใน code:
  if (await featureFlag.isEnabled("new-checkout", user.id)) {
    // show new checkout
  } else {
    // show old checkout
  }

A/B Test Framework

A/B Test วัดว่า variant ไหนให้ conversion rate ที่ดีกว่า

> สร้าง A/B Test framework ที่:
  1. Assign user ไปยัง variant อย่าง consistent
     (user เดิม → variant เดิมเสมอ)
  2. Track events ที่สำคัญ (conversion goal)
  3. Calculate statistical significance
  4. Dashboard แสดงผลลัพธ์
 
  ตัวอย่าง A/B Test: CTA Button
  Variant A (control): "เพิ่มลงตะกร้า" (สีน้ำเงิน)
  Variant B (treatment): "ซื้อเลย" (สีแดง)
  Goal: Click rate
  Duration: 2 สัปดาห์ หรือ n=1000/variant
 
// ab-test.ts
export async function getVariant(
  testId: string,
  userId: string
): Promise<"control" | "treatment"> {
  // deterministic hash เพื่อให้ consistent
  const hash = crypto
    .createHash("sha256")
    .update(`${testId}:${userId}`)
    .digest("hex");
  const num = parseInt(hash.substring(0, 8), 16);
  return num % 2 === 0 ? "control" : "treatment";
}
 
export async function trackEvent(
  testId: string,
  userId: string,
  event: "impression" | "conversion"
) {
  const variant = await getVariant(testId, userId);
  await db.abTestEvent.create({
    data: { testId, userId, variant, event }
  });
}

วิเคราะห์ผล A/B Test ด้วย Claude

# หลังเก็บ data ได้ 2 สัปดาห์
> วิเคราะห์ผล A/B Test "cta-button-color"
  Data:
  Control:   1,024 impressions, 87 conversions (8.5%)
  Treatment: 1,031 impressions, 112 conversions (10.9%)
 
  ช่วย:
  1. คำนวณ statistical significance (p-value)
     ใช้ Chi-square test หรือ Fisher exact test
  2. คำนวณ confidence interval ของความต่าง
  3. บอกว่าผลมี significance ไหม (p < 0.05)?
  4. ถ้า significant: recommend ทำอะไร?
  5. ถ้าไม่ significant: ต้องการ sample size เท่าไหร่?

Benchmark และ Profiling

Benchmark คือการวัดประสิทธิภาพอย่างเป็นระบบ Profiling คือการหาว่าโค้ดส่วนไหนช้า เป็นทักษะสำคัญที่ทำให้ production code ทำงานได้เร็วและประหยัด resource

Micro-benchmark ด้วย Vitest

> เขียน benchmark เพื่อเปรียบเทียบ algorithm A กับ B:
 
  Algorithm A: ใช้ Array.filter().map()
  Algorithm B: ใช้ single Array.reduce()
 
  Test scenarios:
  - Array ขนาด 100, 1,000, 10,000, 100,000 elements
  - รันแต่ละ scenario 1000 ครั้ง
  - รายงาน: mean, median, p99, memory usage
 
// benchmark.test.ts
import { bench, describe } from "vitest";
 
describe("search algorithms", () => {
  const data = Array.from({ length: 10000 },
    (_, i) => ({ id: i, value: Math.random() })
  );
 
  bench("filter + map", () => {
    data.filter(x => x.value > 0.5).map(x => x.id);
  });
 
  bench("reduce", () => {
    data.reduce((acc, x) => {
      if (x.value > 0.5) acc.push(x.id);
      return acc;
    }, [] as number[]);
  });
});
 
# รัน: npx vitest bench

Node.js Profiling ด้วย —prof

> ช่วยตั้งค่า profiling สำหรับ Node.js app
  เพื่อหา CPU bottleneck
 
  # รัน app พร้อม profiler
  node --prof dist/server.js
 
  # ส่ง traffic (load test)
  k6 run profile-test.js
 
  # หยุด app แล้ว process profile
  node --prof-process isolate-*.log > profile.txt
 
  # ให้ Claude วิเคราะห์
> นี่คือ Node.js CPU profile:
  [วาง top functions จาก profile.txt]
 
  วิเคราะห์:
  1. Function ไหนใช้ CPU มากที่สุด?
  2. เป็น bottleneck จริงหรือ false positive?
  3. วิธี optimize ที่เหมาะสม?
 
  # Alternative: ใช้ clinic.js (ง่ายกว่า)
  npm install -g clinic
  clinic doctor -- node dist/server.js
  # เปิด browser อัตโนมัติ แสดง flame graph

Database Query Profiling

> สร้าง database profiling setup:
  1. เปิด query logging ใน Prisma:
  const prisma = new PrismaClient({
    log: [
      { level: "query", emit: "event" },
      { level: "error", emit: "stdout" },
    ],
  });
 
  prisma.$on("query", (e) => {
    if (e.duration > 100) {  // log queries > 100ms
      logger.warn({
        query: e.query,
        params: e.params,
        duration: e.duration,
      }, "Slow query detected");
    }
  });
 
  2. เพิ่ม pg_stat_statements ใน PostgreSQL
     เพื่อ track query statistics:
  CREATE EXTENSION pg_stat_statements;
 
  -- ดู slow queries
  SELECT query, calls, mean_exec_time, total_exec_time
  FROM pg_stat_statements
  WHERE mean_exec_time > 100
  ORDER BY total_exec_time DESC
  LIMIT 10;

Error Handling และ Recovery Strategy

Production system ต้องรับมือกับ failure ได้อย่างสง่างาม ไม่ใช่แค่ “อย่าให้เกิด error” แต่ต้องรู้ว่าจะทำอะไรเมื่อเกิดขึ้น

Error Taxonomy — จัดประเภท Error อย่างถูกต้อง

ประเภท Errorตัวอย่างวิธี HandleRetry?
TransientNetwork timeout, DB connection blipRetry with backoffได้
ValidationEmail format ผิด, field ขาดReturn 400 พร้อม detailไม่ได้
Business RuleCoupon หมดอายุ, สินค้าหมด stockReturn 422 พร้อม user messageไม่ได้
AuthToken หมดอายุ, ไม่มีสิทธิ์Return 401/403บางครั้ง
DependencyStripe down, SendGrid failFallback หรือ queueได้
SystemOOM, disk full, bug ใน codeAlert ทีม, log ละเอียดบางครั้ง

Retry Pattern ด้วย Exponential Backoff

> สร้าง retry utility ที่ใช้ได้ทั่วโปรเจค
 
// retry.ts
export async function withRetry<T>(
  fn: () => Promise<T>,
  options: {
    maxAttempts?: number;   // default: 3
    initialDelay?: number;  // default: 1000ms
    maxDelay?: number;      // default: 30000ms
    backoffFactor?: number; // default: 2 (exponential)
    retryIf?: (error: Error) => boolean;
    onRetry?: (attempt: number, error: Error) => void;
  } = {}
): Promise<T> {
  const {
    maxAttempts = 3,
    initialDelay = 1000,
    maxDelay = 30000,
    backoffFactor = 2,
    retryIf = () => true,
    onRetry = () => {},
  } = options;
 
  let lastError: Error;
 
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error as Error;
 
      if (attempt === maxAttempts || !retryIf(lastError)) {
        throw lastError;
      }
 
      const delay = Math.min(
        initialDelay * Math.pow(backoffFactor, attempt - 1),
        maxDelay
      );
      const jitter = delay * 0.1 * Math.random(); // ±10% jitter
 
      onRetry(attempt, lastError);
      await new Promise(resolve => setTimeout(resolve, delay + jitter));
    }
  }
 
  throw lastError!;
}
 
// Usage
const result = await withRetry(
  () => stripe.paymentIntents.create(params),
  {
    maxAttempts: 3,
    retryIf: (err) => err.message.includes("network"),
    onRetry: (attempt, err) => logger.warn({ attempt, err }, "Retrying payment"),
  }
);

Circuit Breaker Pattern

ป้องกันไม่ให้ระบบถาม external service ที่กำลัง fail ซ้ำๆ ช่วยให้ fail fast และ recover ได้เร็ว

> implement Circuit Breaker สำหรับ external API calls
  States:
  - CLOSED: ทำงานปกติ
  - OPEN: หยุดส่ง request (fail fast)
  - HALF_OPEN: ลอง request 1 อัน ถ้าสำเร็จ → CLOSED
 
  Config:
  - failureThreshold: 5 failures → OPEN
  - successThreshold: 2 successes → CLOSED (from HALF_OPEN)
  - timeout: 30 วินาที ก่อน HALF_OPEN
 
// ใช้ opossum library
npm install opossum
 
import CircuitBreaker from "opossum";
 
const stripeBreaker = new CircuitBreaker(
  (params) => stripe.paymentIntents.create(params),
  {
    timeout: 5000,          // 5s timeout per request
    errorThresholdPercentage: 50,  // 50% errors → OPEN
    resetTimeout: 30000,    // 30s ก่อน HALF_OPEN
    volumeThreshold: 10,    // ต้องมี 10+ requests ก่อน open
  }
);
 
stripeBreaker.on("open",     () => logger.error("Circuit OPEN: Stripe"));
stripeBreaker.on("halfOpen", () => logger.warn("Circuit HALF_OPEN: Testing Stripe"));
stripeBreaker.on("close",    () => logger.info("Circuit CLOSED: Stripe recovered"));
 
// Usage (transparent to caller)
const intent = await stripeBreaker.fire(params);

Graceful Shutdown

เมื่อ server ต้อง restart ต้องทำให้ request ที่กำลังประมวลผลเสร็จก่อน ไม่ทิ้งงานกลางคัน

> implement Graceful Shutdown สำหรับ Express server
  Requirements:
  - รับ SIGTERM signal
  - หยุดรับ request ใหม่
  - รอ request ที่กำลังทำอยู่ให้เสร็จ (timeout: 30s)
  - ปิด database connection
  - Exit ด้วย code 0
 
// shutdown.ts
let isShuttingDown = false;
 
export function gracefulShutdown(server: Server) {
  process.on("SIGTERM", async () => {
    logger.info("SIGTERM received, starting graceful shutdown");
    isShuttingDown = true;
 
    server.close(async () => {
      try {
        await prisma.$disconnect();
        await redis.quit();
        logger.info("Graceful shutdown complete");
        process.exit(0);
      } catch (err) {
        logger.error(err, "Error during shutdown");
        process.exit(1);
      }
    });
 
    // Force shutdown หลัง 30s
    setTimeout(() => {
      logger.error("Forced shutdown after timeout");
      process.exit(1);
    }, 30000);
  });
}
 
// middleware: reject new requests during shutdown
app.use((req, res, next) => {
  if (isShuttingDown) {
    res.set("Connection", "close");
    return res.status(503).json({ error: "Server shutting down" });
  }
  next();
});

Production Incident Management

เมื่อเกิดปัญหาใน production วิธีที่ตอบสนองมีผลอย่างมากต่อ downtime ที่เกิดขึ้น Claude ช่วยทั้งในการ debug และ communicate ได้

Incident Response Playbook

1Detect — รู้ว่ามีปัญหา
Alert จาก monitoring ที่ตั้งไว้ หรือ user report มาก Claude Code ช่วย query log ได้ทันที
# ตรวจสอบสถานะเร็ว
> ช่วย query log ของ 15 นาทีที่ผ่านมา:
  รัน: grep "ERROR" /var/log/app/app.log | tail -50
  หรือ query Cloudwatch:
  aws logs filter-log-events --log-group-name /app/production
    --start-time $(date -d "15 minutes ago" +%s000)
    --filter-pattern "ERROR"
 
  สรุปให้ว่า:
  1. Error ประเภทไหนเกิดมากที่สุด?
  2. เริ่มตั้งแต่เวลาไหน?
  3. endpoint ไหนได้รับผลกระทบ?
2Triage — ประเมิน severity
บอก Claude ข้อมูลที่มี Claude ช่วย assess impact และ priority
> Incident Assessment:
  ข้อมูลที่มี:
  - Error rate: [X%] (ปกติ < 0.1%)
  - Affected users: [N] คน
  - Affected features: [list]
  - Duration: [X minutes]
 
  ประเมิน:
  1. Severity: P1 (ระบบล่ม) / P2 (feature สำคัญพัง) / P3 (ผลกระทบน้อย)
  2. ผู้ที่ต้องแจ้ง: team lead, CTO, users?
  3. Timeline สำหรับ fix: ชั่วโมง / วัน
  4. Quick mitigation ที่ทำได้ทันที?
3Mitigate — ลดผลกระทบก่อน
ทำ workaround เพื่อลด downtime ก่อน แล้วค่อยหา root cause
# วิธี mitigate ที่ทำได้เร็ว
> เราพบว่า payment feature พัง
  ยังไม่รู้สาเหตุ
  เสนอ mitigation options ที่ทำได้ใน 5 นาที:
  - Feature flag: ปิด payment ชั่วคราว
  - Maintenance mode: redirect ไปหน้าแจ้ง
  - Rollback: ย้อนกลับ version ก่อนหน้า
  - Scale up: เพิ่ม server ถ้า load issue
  ระบุ command จริงสำหรับแต่ละ option
4Root Cause Analysis
เมื่อ mitigate แล้ว ค่อยหา root cause อย่างเป็นระบบ
5Post-mortem
หลังแก้แล้ว ทำ post-mortem เพื่อป้องกันไม่ให้เกิดซ้ำ
> เขียน Post-mortem document สำหรับ incident นี้:
  ข้อมูล:
  - เริ่ม: [เวลา]
  - แก้ได้: [เวลา]
  - Duration: [X minutes]
  - Impact: [N users, N transactions affected]
 
  Template:
  ## Timeline
  [เวลา] อะไรเกิดขึ้น
 
  ## Root Cause
  อธิบาย root cause จริงๆ (ไม่ใช่ symptom)
 
  ## Contributing Factors
  สิ่งที่ทำให้ปัญหาแย่ลงหรือแก้ช้า
 
  ## What Went Well
  สิ่งที่ทำได้ดีในการ respond
 
  ## Action Items
  | Action | Owner | Due Date | Priority |
  |--------|-------|----------|----------|
  | เพิ่ม test ที่ catch bug นี้ | @john | 2025-01-20 | P1 |
  | เพิ่ม alert สำหรับ error pattern นี้ | @jane | 2025-01-18 | P1 |
 
  ## Prevention
  จะป้องกันไม่ให้เกิดซ้ำด้วยวิธีไหน?

สรุป: Production-Ready Checklist

รวม checklist ทั้งหมดไว้ใช้ก่อน deploy production จริง:

# .claude/commands/prod-ready.md
# Production Readiness Checklist
 
## Code Quality
□ TypeScript strict mode: ไม่มี any
□ Tests: unit + integration + e2e ผ่าน
□ Test coverage: >= 70% สำหรับ new code
□ Linting: ไม่มี errors
□ Build: สำเร็จ ไม่มี warnings สำคัญ
 
## Security
□ Authentication: ทุก protected route มี auth check
□ Authorization: ตรวจสอบ ownership ก่อน return data
□ Input validation: ทุก input ผ่าน validation
□ SQL: ไม่มี raw string concatenation
□ Secrets: ไม่มี hardcoded credentials
□ Dependencies: npm audit ไม่มี high/critical
 
## Performance
□ Database: indexes ครบสำหรับ queries ที่ใช้บ่อย
□ N+1: ไม่มี N+1 query ใน critical paths
□ Load test: ผ่าน target performance
□ Caching: ใช้ cache สำหรับ expensive operations
 
## Observability
□ Logging: structured logs ครบ
□ Error tracking: Sentry configured
□ Health check: /api/health ทำงาน
□ Alerts: monitoring alerts set up
 
## Reliability
□ Error handling: ทุก async มี try/catch
□ Retry logic: transient errors มี retry
□ Graceful shutdown: รองรับ SIGTERM
□ Circuit breaker: external APIs มี protection
 
## Deployment
□ Migration: backward compatible
□ Rollback: plan ชัดเจน ทดสอบแล้ว
□ Feature flags: configured
□ Runbook: อัปเดตแล้ว
 
□ ทุกข้อ: ✅ พร้อม deploy | ❌ ต้องแก้ก่อน

คำศัพท์ประจำบท

5 Whysเทคนิคหา Root Cause โดยถาม “ทำไม” ซ้ำๆ จนถึงต้นเหตุจริง
Root Causeสาเหตุที่แท้จริงของปัญหา ไม่ใช่ symptom ที่เห็น
Contract-Firstกำหนด Interface/API contract ก่อน implement เพื่อลด ambiguity
Circuit BreakerPattern ที่หยุดส่ง request ไป service ที่กำลัง fail เพื่อ fail fast
Exponential Backoffวิธี retry โดยรอนานขึ้นทุกครั้ง เพื่อไม่กด service ที่กำลัง recover
Graceful Shutdownการ shutdown ที่รอ request ปัจจุบันเสร็จก่อน ไม่ทิ้งงานกลางคัน
Feature FlagSwitch ที่เปิด/ปิด feature ได้โดยไม่ต้อง redeploy
A/B Testการทดสอบ 2 variants พร้อมกันกับ users จริง เพื่อวัดว่าแบบไหนดีกว่า
Statistical Significanceระดับความมั่นใจทางสถิติว่าผลต่างไม่ได้เกิดจากความบังเอิญ
p-valueค่าที่บอกว่าผลที่เห็นเกิดจากความบังเอิญน้อยแค่ไหน (< 0.05 = significant)
Benchmarkการวัดประสิทธิภาพอย่างเป็นระบบเพื่อเปรียบเทียบ
Profilingการหาว่าโค้ดส่วนไหนใช้ CPU/Memory มากที่สุด
Flame Graphกราฟแสดง call stack ที่ใช้ CPU จนหา bottleneck ได้
EXPLAIN ANALYZEคำสั่ง SQL ที่แสดง execution plan จริงของ query
Load Testการทดสอบระบบภายใต้ load จำนวนมาก เพื่อหา breaking point
Canary Deploymentการ deploy ไปยัง % เล็กๆ ของ users ก่อน แล้วค่อยขยาย
Post-mortemการวิเคราะห์หลัง incident เพื่อหาสาเหตุและป้องกันซ้ำ
MTTRMean Time To Recovery — เวลาเฉลี่ยในการแก้ incident
Error Budgetปริมาณ error/downtime ที่ยอมรับได้ใน SLA (เช่น 0.1%/เดือน)