Skip to content
KoishiAI
ไทย
← Back to contents
Chapter 5 / 6 · April 24, 2026

ใช้งานใน Production

จากทดลองสู่การใช้งานจริง — hooks, permissions, security

This guide is All Rights Reserved — free to read, copying/republication requires permission.

บทที่ 5 | ทำให้ Claude Code จบงานระดับ Production กลุ่มเป้าหมาย: Developer ทุกระดับที่ต้องการสร้าง Production-grade Software ด้วย Claude Code

การแก้ปัญหา 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%/เดือน)

บทที่ 5 | ทำให้ Claude Code จบงานได้ระดับ Production กลุ่มเป้าหมาย: นักพัฒนาทุกระดับที่ต้องการนำ code ขึ้น production อย่างมั่นใจ

จาก Vibe Coding ถึง Production — ช่องว่างที่ต้องข้าม

บทที่ 4 สอนให้สร้างของได้เร็ว แต่ “เร็ว” ไม่ใช่ “พร้อม” เสมอไป Production code ต้องผ่านกระบวนการที่ครบถ้วนก่อนให้ผู้ใช้จริงสัมผัส บทนี้จะพา walk through ตั้งแต่โค้ดที่เพิ่ง Vibe จนถึงระบบที่ deploy จริงและวัดผลได้

The Production Gap — สิ่งที่ Vibe Coding ยังขาด

Vibe Coding ได้Production ต้องการเพิ่ม
Function ทำงานได้Handle ทุก edge case ที่เป็นไปได้
Happy path ผ่านError path ที่ graceful และ informative
โค้ดอ่านได้โค้ดที่ maintainable โดยคนอื่น 6 เดือนต่อมา
รันได้ใน localรันได้ทุก environment อย่าง consistent
ทดสอบด้วยมือAutomated tests ที่รันทุก commit
Deploy ครั้งแรกได้Deploy ซ้ำได้อย่าง reliable ไม่ว่ากี่ครั้ง
ไม่รู้ว่าช้าหรือเร็วBenchmark และ Performance budget ชัดเจน
ไม่รู้ว่า User ชอบไหมA/B test วัดผลด้วย data จริง

Production Pipeline ทั้งหมด

นี่คือ pipeline ที่ทุก feature ต้องผ่านก่อนถึงมือ user จริง Claude Code ช่วยได้ในทุกขั้น:

ขั้นที่PhaseงานหลักClaude ช่วยอะไร
1Code QualityLint, Format, Type checkAuto-fix + review
2Unit TestingTest ทุก function ทุก edge caseเขียน + รัน test
3Integration TestingTest ที่ component ทำงานร่วมกันสร้าง test scenario
4Security Auditหาช่องโหว่ก่อน deployOWASP checklist
5PerformanceBenchmark + optimizeหา bottleneck
6QA TestingManual + automated E2Eสร้าง test plan
7Staging Deployทดสอบใน environment จริงDeployment script
8Monitoring SetupLog, metric, alertเขียน dashboard
9Production DeployRelease strategyBlue/green, canary
10A/B Testingวัดผล feature ใหม่สร้าง experiment

Phase 1: Code Quality — มาตรฐานก่อนทุกอย่าง

โค้ดที่ไม่ผ่าน Quality gate ไม่ควรไปต่อ ตั้งค่าให้ block อัตโนมัติ ป้องกันโค้ดแย่เข้า repository

ตั้งค่า Quality Gate อัตโนมัติ

ให้ Claude ช่วยตั้งค่า Linting, Formatting และ Type checking แบบ zero-config:

> ตั้งค่า code quality toolchain สำหรับ Next.js + TypeScript:
  1. ESLint: ใช้ config next/typescript + strict rules
  2. Prettier: single quote, no semi, 100 char line length
  3. TypeScript: strict mode, no implicit any
  4. Husky pre-commit hook: รัน lint + typecheck ก่อน commit
  5. lint-staged: รัน prettier เฉพาะไฟล์ที่เปลี่ยน (เร็วกว่า)
 
  ติดตั้งและ config ทุกอย่างในครั้งเดียว
  ให้ error ที่ชัดเจนเมื่อ commit ไม่ผ่าน
# package.json scripts ที่ควรมี
{
  "scripts": {
    "lint": "next lint --fix",
    "lint:check": "next lint",
    "typecheck": "tsc --noEmit",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "quality": "npm run typecheck && npm run lint:check && npm run format:check"
  },
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md,css}": ["prettier --write"]
  }
}
 
# .husky/pre-commit
#!/bin/sh
npx lint-staged
npm run typecheck

Claude Code Review ก่อน PR

ให้ Claude รีวิวโค้ดทุกครั้งก่อนสร้าง Pull Request โดยใช้ checklist ที่ครอบคลุม:

# .claude/commands/pr-review.md
# Pre-PR Code Review
 
รีวิวโค้ดทั้งหมดที่เปลี่ยนแปลงจาก main:
 
## 1. ความถูกต้องของ Logic
- Business rules ถูกต้องตาม @docs/domain/business-rules.md?
- Edge cases ครบ? (empty array, null, undefined, negative numbers)
- Boundary conditions? (0, max int, empty string)
 
## 2. Error Handling
- ทุก async operation มี try/catch?
- Error messages สื่อความหมาย?
- Error log ไปที่ Sentry ด้วย enough context?
- User เห็น friendly error ไม่ใช่ stack trace?
 
## 3. Security
- Input validation ครบทุก endpoint?
- Authorization check ก่อนทุก data access?
- Sensitive data ไม่อยู่ใน log?
- SQL/NoSQL injection ป้องกันได้?
 
## 4. Performance
- N+1 queries?
- Missing database indexes?
- Unnecessary re-renders ใน React?
- Heavy computation ใน render path?
 
## 5. TypeScript
- ไม่มี any ที่ไม่จำเป็น?
- Types ครอบคลุม null/undefined?
- Generic types ใช้ถูกต้อง?
 
## Output Format
### ✅ APPROVED / ⚠️ APPROVED WITH NOTES / ❌ CHANGES REQUIRED
### Critical Issues (ต้องแก้ก่อน merge):
### Minor Issues (แก้ได้ทีหลัง):
### Suggestions (ไม่บังคับ):

Phase 2: Testing Strategy — ครบทุกชั้น

Testing Pyramid คือหลักการที่ดี: Unit tests เยอะ Integration tests ปานกลาง E2E tests น้อยแต่ครอบคลุม critical path การมี Claude ช่วยเขียน tests ทำให้ coverage สูงขึ้นได้โดยใช้เวลาน้อยลง

Testing Pyramid สำหรับ Vibe Coder

ชั้นจำนวนความเร็วค่าใช้จ่ายใช้สำหรับ
Unit Testsมาก (70%)เร็ว msถูกทุก function, ทุก utility
Integration Testsกลาง (20%)กลาง secกลางAPI endpoints, DB queries
E2E Testsน้อย (10%)ช้า นาทีแพงCritical user journeys เท่านั้น

Unit Testing — ให้ Claude เขียน Test ครอบคลุม

Unit test ที่ดีต้องครอบคลุม Happy path, Error path, Edge cases และ Boundary conditions:

> เขียน comprehensive unit tests สำหรับ
  @src/lib/pricing.ts ทุก function
 
  ใช้ Vitest + describe/it pattern
  ครอบคลุม:
  1. Happy path: input ปกติ output ถูกต้อง
  2. Edge cases: 0, negative, null, undefined, empty
  3. Boundary: ค่าต่ำสุด/สูงสุดที่ valid
  4. Error cases: input ผิด format ต้อง throw
  5. Business rules: ตาม @docs/domain/business-rules.md
 
  Format: describe("functionName") > it("should...")
  ไม่ใช้ magic numbers อธิบาย test case ด้วย

ตัวอย่าง Unit Test ที่ดี

// pricing.test.ts
import { describe, it, expect } from "vitest"
import { calculateDiscount, applyMemberDiscount } from "./pricing"
 
describe("calculateDiscount", () => {
  describe("Coupon discount", () => {
    it("should apply percentage coupon correctly", () => {
      expect(calculateDiscount(1000, { type: "percent", value: 10 })).toBe(900)
    })
 
    it("should apply fixed amount coupon correctly", () => {
      expect(calculateDiscount(1000, { type: "fixed", value: 150 })).toBe(850)
    })
 
    it("should not go below minimum price", () => {
      // coupon 100% discount แต่มี minimum price 100
      const result = calculateDiscount(500, { type: "percent", value: 100 }, { minPrice: 100 })
      expect(result).toBe(100)
    })
 
    it("should throw when coupon value is negative", () => {
      expect(() => calculateDiscount(1000, { type: "percent", value: -10 }))
        .toThrow("Coupon value must be positive")
    })
 
    it("should throw when original price is zero", () => {
      expect(() => calculateDiscount(0, { type: "percent", value: 10 }))
        .toThrow("Original price must be greater than 0")
    })
  })
 
  describe("Member discount stacking", () => {
    it("should apply member discount AFTER coupon", () => {
      // 1000 → coupon 10% → 900 → member 5% → 855
      const afterCoupon = calculateDiscount(1000, { type: "percent", value: 10 })
      expect(applyMemberDiscount(afterCoupon, "gold")).toBe(855)
    })
  })
})

Integration Testing — ทดสอบ API Endpoints

Integration test ตรวจสอบว่า component หลายตัวทำงานร่วมกันถูกต้อง รวมถึง database จริง:

> สร้าง integration tests สำหรับ POST /api/orders
 
  Setup:
  - ใช้ Vitest + supertest
  - Database: test database แยกจาก dev
  - Seed: สร้าง user และ products ก่อน test
  - Cleanup: ลบข้อมูลหลัง test ทุกอัน
 
  Test cases:
  1. สร้าง order สำเร็จ → 201 + order ID
  2. สร้าง order โดยไม่มี auth → 401
  3. สินค้า out of stock → 400 + error message
  4. สินค้าไม่มีอยู่จริง → 404
  5. Payment amount ไม่ตรง → 400
  6. Concurrent orders (race condition test)
 
  Verify ด้วย:
  - Response status code
  - Response body structure
  - Database state หลัง request
  - Side effects (email sent?, inventory updated?)
// orders.integration.test.ts
import { describe, it, expect, beforeEach, afterEach } from "vitest"
import request from "supertest"
import { app } from "../app"
import { db } from "../lib/db"
import { createTestUser, createTestProduct, clearTestData } from "./helpers"
 
describe("POST /api/orders", () => {
  let authToken: string
  let testProduct: { id: string; price: number; stock: number }
 
  beforeEach(async () => {
    const user = await createTestUser({ email: "test@test.com" })
    authToken = user.token
    testProduct = await createTestProduct({ price: 1000, stock: 10 })
  })
 
  afterEach(async () => {
    await clearTestData()
  })
 
  it("should create order successfully", async () => {
    const res = await request(app)
      .post("/api/orders")
      .set("Authorization", `Bearer ${authToken}`)
      .send({ productId: testProduct.id, quantity: 2 })
 
    expect(res.status).toBe(201)
    expect(res.body.order.total).toBe(2000)
 
    // verify inventory updated
    const product = await db.product.findUnique({ where: { id: testProduct.id } })
    expect(product?.stock).toBe(8) // 10 - 2
  })
 
  it("should return 400 when out of stock", async () => {
    const res = await request(app)
      .post("/api/orders")
      .set("Authorization", `Bearer ${authToken}`)
      .send({ productId: testProduct.id, quantity: 100 }) // เกิน stock
 
    expect(res.status).toBe(400)
    expect(res.body.error.code).toBe("E_OUT_OF_STOCK")
  })
})

E2E Testing — ทดสอบ Critical User Journey

E2E test ใช้ Playwright จำลอง user จริง เน้นเฉพาะ journey ที่ถ้าพังแล้วกระทบรายได้มากที่สุด:

> สร้าง E2E tests ด้วย Playwright สำหรับ
  Critical user journeys 3 อัน:
 
  Journey 1: Purchase Flow (สำคัญที่สุด)
  - เปิดหน้าแรก → เลือกสินค้า → Add to cart
  - → Checkout → กรอก shipping → เลือก payment
  - → ยืนยัน order → เห็น confirmation page
  - → ได้รับ email confirmation
 
  Journey 2: User Registration + First Purchase
  - กรอก email, password, verify email
  - → ซื้อสินค้าครั้งแรก → เห็น welcome discount
 
  Journey 3: Search + Filter + Purchase
  - ค้นหาสินค้า → filter by category, price
  - → เลือกสินค้า → ซื้อ
 
  Setup:
  - ใช้ test user account แยกต่างหาก
  - รัน against staging environment
  - Screenshot เมื่อ fail
  - Retry 2 ครั้งอัตโนมัติ
// tests/e2e/purchase-flow.spec.ts
import { test, expect } from "@playwright/test"
 
test.describe("Purchase Flow", () => {
  test.beforeEach(async ({ page }) => {
    // Login ด้วย test account
    await page.goto("/login")
    await page.fill("[name=email]", process.env.TEST_USER_EMAIL!)
    await page.fill("[name=password]", process.env.TEST_USER_PASSWORD!)
    await page.click("[type=submit]")
    await page.waitForURL("/dashboard")
  })
 
  test("complete purchase flow", async ({ page }) => {
    // เลือกสินค้า
    await page.goto("/products")
    await page.click("[data-testid=product-card]:first-child")
    await page.click("[data-testid=add-to-cart]")
 
    // Checkout
    await page.goto("/cart")
    await page.click("[data-testid=checkout-btn]")
 
    // กรอก shipping
    await page.fill("[name=address]", "123 Test Street")
    await page.fill("[name=city]", "Bangkok")
    await page.selectOption("[name=province]", "BKK")
    await page.click("[data-testid=next-btn]")
 
    // เลือก payment (test card)
    await page.fill("[name=card-number]", "4242424242424242")
    await page.fill("[name=expiry]", "12/28")
    await page.fill("[name=cvc]", "123")
    await page.click("[data-testid=pay-btn]")
 
    // verify confirmation
    await expect(page.getByText("Order Confirmed")).toBeVisible()
    await expect(page.getByTestId("order-id")).toContainText("ORD-")
  })
})
 
// playwright.config.ts
export default {
  retries: 2,
  screenshot: "only-on-failure",
  video: "retain-on-failure",
  use: { baseURL: process.env.STAGING_URL },
}

Test Coverage Report — วัดความครบถ้วน

# ดู coverage report
npx vitest run --coverage
 
# ให้ Claude วิเคราะห์ coverage gaps
> นี่คือ coverage report:
  File: src/lib/pricing.ts — 67% coverage
  Uncovered lines: 45-67, 89-102
 
  ดู @src/lib/pricing.ts บรรทัด 45-67 และ 89-102
  แล้วสร้าง test cases ที่ยังขาดอยู่
  โดยเฉพาะ error handling paths
 
# ตั้ง minimum coverage threshold
// vitest.config.ts
coverage: {
  thresholds: {
    lines: 80,
    functions: 80,
    branches: 70,
  }
}

Phase 3: Security Audit — ป้องกันก่อนถูกโจมตี

Security audit เป็นขั้นตอนที่ Vibe Coder มักข้ามเพราะคิดว่า Claude น่าจะเขียนโค้ดปลอดภัย แต่ความจริงคือ Claude อาจพลาด security issue ได้เหมือนกัน

Security Audit Checklist ด้วย Claude

# .claude/commands/security-audit.md
# Security Audit
 
ทำ security audit แบบ comprehensive สำหรับ PR นี้:
 
## OWASP Top 10 Checklist
 
### 1. Injection
- SQL Injection: ใช้ parameterized queries หรือ ORM?
- NoSQL Injection: validate input ก่อน query?
- Command Injection: ไม่รัน user input ใน shell?
 
### 2. Broken Authentication
- Session timeout ตั้งค่าไว้?
- Password ที่เก็บ hash ด้วย bcrypt/argon2?
- Brute force protection?
- JWT: expire time สมเหตุสมผล, signature verify ถูกต้อง?
 
### 3. Sensitive Data Exposure
- HTTPS ทุก endpoint?
- Sensitive data ใน log?
- Password/token ใน error message?
- API response ส่ง field ที่ไม่ควรส่งไหม?
 
### 4. Access Control
- ทุก endpoint มี auth check?
- User A เข้าถึงข้อมูล User B ได้ไหม? (IDOR)
- Admin-only routes มี role check?
 
### 5. XSS
- User input ที่ render เป็น HTML ถูก sanitize?
- dangerouslySetInnerHTML ใช้กับ user input?
- Content-Security-Policy header ตั้งไว้?
 
### 6. CSRF
- Form submit มี CSRF token?
- State-changing requests ใช้ POST ไม่ใช่ GET?
 
## รายงานผล
### 🔴 Critical (ต้องแก้ทันที):
### 🟠 High (ต้องแก้ก่อน production):
### 🟡 Medium (แก้ใน sprint นี้):
### 🟢 Low (แก้ได้ทีหลัง):

ตัวอย่างการหาและแก้ Security Issues

IDOR (Insecure Direct Object Reference)

❌ มีช่องโหว่ IDOR
// GET /api/orders/:id
const order = await db.order.findUnique({
where: { id: params.id }
})
// ไม่ check ว่า order เป็นของ user นี้!
// user A ดู order ของ user B ได้
✅ ป้องกัน IDOR
const order = await db.order.findFirst({
where: {
id: params.id,
userId: session.user.id // check ownership
}
})
if (!order) {
throw new NotFoundError()
// ไม่บอกว่ามีอยู่แต่ไม่มีสิทธิ์
}

Mass Assignment

❌ มีช่องโหว่
// User ส่ง body อะไรก็ได้
await db.user.update({
where: { id: userId },
data: req.body // อันตราย!
})
// user อาจส่ง { role: “admin” }
✅ Whitelist fields
const { name, email, bio } = req.body
// รับเฉพาะ field ที่อนุญาต
await db.user.update({
where: { id: userId },
data: { name, email, bio }
})
// role ไม่สามารถเปลี่ยนได้

Environment Variables Security

> ตรวจสอบ security ของ environment variables:
  1. มี .env.example ที่ไม่มี secret จริง?
  2. .env อยู่ใน .gitignore?
  3. ไม่มีการ console.log env vars?
  4. Validation ว่า required env ครบเมื่อ startup?
 
  สร้าง src/lib/env.ts ที่:
  - validate env vars ทุกตัวตอน app start
  - throw error ถ้า required var ขาด
  - type-safe env vars ด้วย zod
 
// src/lib/env.ts
import { z } from "zod"
 
const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  NEXTAUTH_SECRET: z.string().min(32),
  STRIPE_SECRET_KEY: z.string().startsWith("sk_"),
  NEXT_PUBLIC_APP_URL: z.string().url(),
})
 
export const env = envSchema.parse(process.env)
// throw at startup ถ้า env ไม่ถูกต้อง

Phase 4: Performance Benchmark — วัดก่อนปรับ

ไม่ควร optimize อะไรก็ตามโดยไม่มีตัวเลข “ช้า” และ “เร็ว” ต้องนิยามให้ชัดก่อน แล้วค่อย benchmark เปรียบเทียบ

Performance Budget — กำหนดเป้าหมาย

Performance Budget คือตัวเลขที่ตกลงกันว่า “ดีพอ” ก่อน optimize ต้องรู้ว่า target คืออะไร:

MetricPoorNeeds WorkGoodExcellent
Page Load (LCP)> 4s2.5-4s< 2.5s< 1s
API Response (P95)> 1000ms500-1000ms< 500ms< 100ms
Time to Interactive> 5s3.8-5s< 3.8s< 1s
First Byte (TTFB)> 1800ms900-1800ms< 900ms< 200ms
Core Web Vitals (CLS)> 0.250.1-0.25< 0.1< 0.05
# เพิ่มใน CLAUDE.md
## Performance Budget
- API response P95: < 500ms (เป้าหมาย < 200ms)
- Page load LCP: < 2.5s บน 4G mobile
- Database query: < 100ms ทุก query
- Memory usage: < 512MB per instance
 
## ถ้าทำให้ exceed budget ต้องขออนุมัติก่อน

Database Performance Benchmark

> สร้าง performance benchmark สำหรับ
  database queries ที่ใช้บ่อยที่สุด:
 
  1. รัน EXPLAIN ANALYZE สำหรับทุก query ที่สำคัญ
  2. วัด execution time กับ dataset ขนาด:
     - 1,000 rows (dev ปัจจุบัน)
     - 100,000 rows (3 เดือนข้างหน้า)
     - 1,000,000 rows (1 ปีข้างหน้า)
  3. ระบุ query ที่จะ slow ที่ scale ใหญ่
  4. เสนอ indexes ที่ต้องเพิ่ม
 
# สร้าง benchmark script
// benchmark/db-queries.ts
import { db } from "../src/lib/db"
import { performance } from "perf_hooks"
 
async function benchmark(name: string, fn: () => Promise<unknown>) {
  const runs = 100
  const times: number[] = []
 
  for (let i = 0; i < runs; i++) {
    const start = performance.now()
    await fn()
    times.push(performance.now() - start)
  }
 
  times.sort((a, b) => a - b)
  console.log(`${name}:`)
  console.log(`  P50: ${times[50].toFixed(2)}ms`)
  console.log(`  P95: ${times[95].toFixed(2)}ms`)
  console.log(`  P99: ${times[99].toFixed(2)}ms`)
}
 
await benchmark("getProductList", () =>
  db.product.findMany({ take: 20, include: { category: true } })
)
 
await benchmark("searchProducts", () =>
  db.product.findMany({ where: { name: { contains: "test" } }, take: 20 })
)

API Load Testing ด้วย k6

Load testing จำลอง user จำนวนมากใช้งานพร้อมกัน ช่วยหา bottleneck ก่อน traffic จริงมา:

> สร้าง load test script ด้วย k6 สำหรับ:
  Scenario 1: Normal load
  - 50 concurrent users, 5 นาที
  - ทำ: browse product, search, view detail
 
  Scenario 2: Peak load
  - Ramp up จาก 0 → 200 users ใน 2 นาที
  - คงที่ 200 users 5 นาที
  - Ramp down 2 นาที
 
  Scenario 3: Stress test
  - หา breaking point ว่า server ล่มที่กี่ users
 
  Success criteria:
  - Error rate < 1%
  - P95 response < 500ms
  - ไม่มี memory leak (memory ไม่เพิ่มขึ้นเรื่อยๆ)
// load-test.js (k6 script)
import http from "k6/http"
import { check, sleep } from "k6"
import { Rate } from "k6/metrics"
 
const errorRate = new Rate("errors")
 
export const options = {
  stages: [
    { duration: "2m", target: 50 },   // Ramp up
    { duration: "5m", target: 50 },   // Stay at 50
    { duration: "2m", target: 200 },  // Ramp to peak
    { duration: "5m", target: 200 },  // Stay at peak
    { duration: "2m", target: 0 },    // Ramp down
  ],
  thresholds: {
    http_req_duration: ["p(95)<500"],  // P95 < 500ms
    errors: ["rate<0.01"],             // Error < 1%
  },
}
 
const BASE_URL = "https://staging.myapp.com"
 
export default function() {
  // Browse products
  const res = http.get(`${BASE_URL}/api/products?page=1`)
  errorRate.add(res.status !== 200)
  check(res, { "products loaded": (r) => r.status === 200 })
  sleep(1)
 
  // Search
  const search = http.get(`${BASE_URL}/api/products?q=phone`)
  errorRate.add(search.status !== 200)
  sleep(0.5)
}
 
# รัน: k6 run load-test.js
# ดู result: k6 run --out json=result.json load-test.js

Frontend Performance — Core Web Vitals

> วิเคราะห์และปรับปรุง Core Web Vitals:
 
  1. รัน Lighthouse CI บน staging:
     npx lhci autorun
 
  2. วัด metrics ปัจจุบัน:
     - LCP (Largest Contentful Paint)
     - FID / INP (Interaction to Next Paint)
     - CLS (Cumulative Layout Shift)
 
  3. ให้ Claude วิเคราะห์ report:
> นี่คือ Lighthouse report:
  [paste JSON output]
  ระบุ top 5 improvements ที่ impact สูงที่สุด
  โดยเรียงตาม effort vs impact
 
  4. ปรับปรุงที่พบบ่อย:
     - Image optimization (next/image)
     - Font loading (display: swap)
     - Unused JavaScript (tree shaking)
     - Server-side rendering ที่เหมาะสม
# lighthouserc.js
module.exports = {
  ci: {
    collect: {
      url: ["https://staging.myapp.com", "/products", "/checkout"],
      numberOfRuns: 3,
    },
    assert: {
      assertions: {
        "categories:performance": ["error", { minScore: 0.8 }],
        "categories:accessibility": ["error", { minScore: 0.9 }],
        "first-contentful-paint": ["error", { maxNumericValue: 2000 }],
        "largest-contentful-paint": ["error", { maxNumericValue: 2500 }],
        "cumulative-layout-shift": ["error", { maxNumericValue: 0.1 }],
      },
    },
  },
}

Phase 5: QA Testing — ก่อนถึงมือ User

QA (Quality Assurance) คือขั้นตอนที่ทดสอบ feature ในมุมมองของ user จริง ไม่ใช่แค่ technical correctness Claude ช่วยสร้าง test plan ที่ครอบคลุมได้

สร้าง QA Test Plan ด้วย Claude

> สร้าง QA Test Plan สำหรับ Feature: User Profile Edit
 
  Feature requirements:
  - User แก้ไข name, email, bio, avatar ได้
  - Email ต้อง verify ใหม่เมื่อเปลี่ยน
  - Avatar resize อัตโนมัติ max 500x500px
  - Preview ก่อน save
 
  สร้าง test plan ที่ครอบคลุม:
  1. Functional tests: ทุก feature ทำงานได้
  2. Negative tests: input ผิดแล้วเกิดอะไร
  3. Boundary tests: ค่าขีดจำกัด
  4. UX tests: user experience flow
  5. Accessibility tests: keyboard, screen reader
  6. Cross-browser: Chrome, Firefox, Safari
  7. Mobile responsive: iPhone, Android
 
  Format: Test ID | Test Case | Steps | Expected | Priority

ตัวอย่าง QA Test Plan

Test IDTest CaseStepsExpectedPriority
QA-001แก้ชื่อสำเร็จ1.กรอกชื่อใหม่ 2.Saveชื่อเปลี่ยนทันทีHigh
QA-002ชื่อว่างเปล่า1.ลบชื่อออก 2.SaveError: Name requiredHigh
QA-003ชื่อยาวเกิน1.กรอก 200 ตัว 2.SaveError: Max 100 charsMedium
QA-004Email ใหม่1.เปลี่ยน email 2.SaveEmail verify ถูกส่งHigh
QA-005Avatar ขนาดใหญ่1.Upload 5MB PNGAuto resize < 500KBMedium
QA-006Avatar format ผิด1.Upload .pdfError: Invalid formatMedium
QA-007Preview ก่อน save1.เปลี่ยนรูป 2.ดู previewPreview ถูกต้องLow

Regression Testing — ป้องกัน Feature เก่าพัง

เมื่อ deploy feature ใหม่ ต้องมั่นใจว่า feature เก่ายังทำงานได้ Claude ช่วยสร้าง regression test suite ได้:

> สร้าง regression test suite สำหรับ release นี้
  ตรวจสอบว่า feature เก่ายังทำงานได้:
 
  Critical features ที่ต้อง test:
  - User login/logout
  - Product listing และ search
  - Add to cart
  - Checkout flow
  - Order history
  - Payment
 
  สร้าง Playwright script ที่รันทุก feature
  ใน 15 นาที (ต้องเร็วพอสำหรับ CI/CD)
  บน staging environment
 
# ตั้งให้รันอัตโนมัติก่อน production deploy
# ถ้า fail → block deployment

Accessibility Testing — ทุกคนใช้ได้

> ตรวจสอบ Accessibility ของ @src/components/
  ตาม WCAG 2.1 Level AA:
 
  1. Semantic HTML: ใช้ heading, button, nav ถูกต้อง?
  2. Keyboard navigation: Tab ผ่านทุก interactive element?
  3. Focus indicator: เห็นชัดเจนว่า focus อยู่ที่ไหน?
  4. Alt text: ทุกรูปมี meaningful alt?
  5. Color contrast: ผ่าน 4.5:1 ratio?
  6. Error messages: screen reader อ่านได้?
  7. Form labels: ทุก input มี label?
 
  สร้าง axe-core test สำหรับ pages สำคัญ
 
// accessibility.test.ts
import { test, expect } from "@playwright/test"
import AxeBuilder from "@axe-core/playwright"
 
test("checkout page passes accessibility", async ({ page }) => {
  await page.goto("/checkout")
  const results = await new AxeBuilder({ page }).analyze()
  expect(results.violations).toEqual([])
})

Phase 6: Deployment Strategy — ปล่อยอย่างปลอดภัย

Deploy แบบมั่นใจต้องมี strategy ที่ลด risk และ rollback ได้เร็วเมื่อมีปัญหา

Environment Strategy

Environmentใช้สำหรับDatabaseDeploy เมื่อ
Local DevDevelopment ส่วนตัวLocal SQLite/PGตลอดเวลา
StagingQA + Integration testStaging DB (copy prod)ทุก PR merge
PreviewReview per PRใช้ร่วมกับ Stagingทุก PR สร้าง
ProductionUser จริงProduction DBManual approve

Deployment Checklist ก่อน Production

# .claude/commands/deploy-check.md
# Pre-Production Deployment Checklist
 
ตรวจสอบทุกข้อก่อน approve production deploy:
 
## Code Quality
□ All tests pass (unit + integration + e2e)
□ No TypeScript errors
□ No ESLint errors
□ Code review approved
□ Security audit passed
 
## Database
□ Migration tested บน staging แล้ว
□ Migration reversible (มี rollback script)
□ Data backup ล่าสุดมีไหม
□ Index strategy reviewed
 
## Configuration
□ Environment variables ครบใน production
□ API keys ถูกต้อง (ไม่ใช่ test keys)
□ Rate limits ตั้งค่าแล้ว
□ CORS ตั้งค่า whitelist ถูก
 
## Monitoring
□ Error tracking (Sentry) connected
□ Performance monitoring connected
□ Alert rules ตั้งค่าแล้ว
□ Dashboard พร้อม monitor
 
## Rollback Plan
□ มีวิธี rollback code ใน < 5 นาที
□ มีวิธี rollback database ถ้า migration เสีย
□ On-call ใครดู production ช่วง deploy
 
รัน: git diff main...HEAD --stat แล้วสรุปให้

Blue-Green Deployment

Blue-Green คือการมี 2 environment เหมือนกัน สลับ traffic เมื่อ deploy ทำให้ rollback ทันทีได้โดยไม่มี downtime:

> อธิบาย Blue-Green deployment strategy
  และสร้าง deployment script สำหรับ:
  Infrastructure: Vercel (หรือ AWS ECS)
 
  Flow:
  1. Deploy version ใหม่ไปที่ Green environment
  2. Run smoke tests บน Green
  3. ถ้าผ่าน → switch traffic จาก Blue → Green
  4. ถ้าไม่ผ่าน → stay on Blue, debug Green
  5. หลัง stable → Green กลายเป็น Blue สำหรับ deploy ถัดไป
 
# deploy.sh
#!/bin/bash
set -e
 
echo "🚀 Starting deployment..."
 
# Deploy to staging
vercel --prod --scope=team --yes
 
# Run smoke tests
echo "🔍 Running smoke tests..."
npx playwright test tests/smoke/ --project=chromium
 
if [ $? -eq 0 ]; then
  echo "✅ Deployment successful!"
  # Notify Slack
  curl -X POST $SLACK_WEBHOOK -d '{"text":"✅ Deploy success!"}'
else
  echo "❌ Smoke tests failed! Rolling back..."
  vercel rollback
  curl -X POST $SLACK_WEBHOOK -d '{"text":"❌ Deploy failed, rolling back"}'
  exit 1
fi

Canary Release — ปล่อยทีละน้อย

Canary release คือการปล่อย feature ให้ user บางส่วนก่อน ถ้าไม่มีปัญหาค่อยขยาย เหมาะสำหรับ feature ใหญ่ที่ risk สูง:

// Feature flags สำหรับ Canary release
// src/lib/feature-flags.ts
import { getServerSession } from "next-auth"
 
export async function isFeatureEnabled(flag: string): Promise<boolean> {
  // ดึงจาก LaunchDarkly, Unleash, หรือ database
  const flags = await getFeatureFlags()
  return flags[flag]?.enabled ?? false
}
 
// ใช้งานใน component
const showNewCheckout = await isFeatureEnabled("new_checkout_v2")
 
return showNewCheckout ? <NewCheckout /> : <OldCheckout />
 
# Canary rollout plan
# Day 1: 5% ของ users
# Day 3: 25% ถ้าไม่มีปัญหา
# Day 7: 50%
# Day 10: 100%

Phase 7: Monitoring — รู้ปัญหาก่อน User รายงาน

Monitoring ที่ดีทำให้รู้ว่าระบบมีปัญหาก่อน user จะมา complain สร้างได้ใน 1-2 ชั่วโมงด้วย Claude

Error Tracking ด้วย Sentry

> ตั้งค่า Sentry สำหรับ Next.js app นี้:
 
  1. สร้าง sentry.client.config.ts และ sentry.server.config.ts
  2. Capture ทุก uncaught error
  3. Enrich errors ด้วย: user ID, session info,
     request details, environment
  4. Ignore errors ที่ไม่สำคัญ: network errors จาก bots
  5. Set up alerts: email เมื่อ error rate > 1%
  6. Create release tracking เพื่อดูว่า deploy ไหนทำให้เกิด error
 
// sentry.server.config.ts
import * as Sentry from "@sentry/nextjs"
 
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
  beforeSend(event) {
    // ไม่ส่ง error จาก bot
    if (event.request?.headers?.["user-agent"]?.includes("bot")) {
      return null
    }
    return event
  }
})

Application Metrics

// src/lib/metrics.ts — custom metrics
import { register, Counter, Histogram } from "prom-client"
 
export const httpRequestDuration = new Histogram({
  name: "http_request_duration_seconds",
  help: "Duration of HTTP requests in seconds",
  labelNames: ["method", "route", "status"],
  buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5],
})
 
export const orderCreated = new Counter({
  name: "orders_created_total",
  help: "Total number of orders created",
  labelNames: ["payment_method"],
})
 
export const paymentFailed = new Counter({
  name: "payment_failures_total",
  help: "Total number of payment failures",
  labelNames: ["reason"],
})
 
// ใช้งาน
orderCreated.inc({ payment_method: "credit_card" })
paymentFailed.inc({ reason: "insufficient_funds" })
 
// Dashboard ดูที่ /metrics

Alert Rules — แจ้งเตือนอัตโนมัติ

> สร้าง alert rules สำหรับ production:
 
  Critical (PagerDuty + SMS):
  - Error rate > 5% ใน 5 นาที
  - API P95 > 2000ms ใน 10 นาที
  - Payment failure rate > 10%
  - Server CPU > 90% นาน > 5 นาที
 
  Warning (Slack):
  - Error rate > 1%
  - API P95 > 500ms
  - Database connection pool > 80%
  - Memory > 80%
 
  Info (Log only):
  - New user registration
  - Order created
  - Deploy completed
 
# สร้าง Slack alert function
async function sendAlert(level: string, message: string) {
  await fetch(process.env.SLACK_WEBHOOK!, {
    method: "POST",
    body: JSON.stringify({
      text: `${level === "critical" ? "🚨" : "⚠️"} ${message}`,
    })
  })
}

Phase 8: A/B Testing — วัดผลด้วย Data จริง

A/B Testing คือการทดสอบ 2 version พร้อมกันเพื่อวัดว่า version ไหนดีกว่าจาก user behavior จริง ไม่ใช่ความเห็นของทีม

เมื่อไหร่ควรทำ A/B Test?

ควรทำ A/B Testไม่ต้องทำ A/B Test
UI/UX ที่คาดว่าจะกระทบ conversionBug fixes (ชัดเจนว่าต้องแก้)
Pricing หรือ promotion strategySecurity improvements
Onboarding flow ใหม่Feature ที่ทุกคน request
CTA copy หรือ button designTechnical refactoring
Checkout flow ปรับปรุงCompliance requirements
Search algorithm เปลี่ยนฐาน user น้อยเกินไป (< 1000/วัน)

A/B Test Setup ด้วย Claude

> สร้าง A/B test framework สำหรับ checkout button:
 
  Hypothesis:
  "เปลี่ยน CTA จาก Checkout เป็น Buy Now จะเพิ่ม conversion"
 
  Primary metric: Conversion rate (cart → order)
  Secondary metrics: Revenue per user, Time to checkout
  Guard rails: Cart abandonment ต้องไม่เพิ่มขึ้น
 
  Sample size: คำนวณด้วย statistical significance
  Duration: 2 สัปดาห์ (ให้ครบ weekly pattern)
 
  สร้าง:
  1. Experiment config
  2. Assignment logic (user ไหนเห็น variant ไหน)
  3. Event tracking
  4. Analysis query
// src/lib/experiments.ts
import { db } from "./db"
import { hashUserId } from "./utils"
 
interface Experiment {
  name: string
  variants: string[]
  weights: number[]  // ต้องรวมกันได้ 100
  startDate: Date
  endDate: Date
}
 
export async function getVariant(
  userId: string,
  experiment: Experiment
): Promise<string> {
  // Deterministic assignment: user เดิม = variant เดิมทุกครั้ง
  const hash = hashUserId(userId + experiment.name)
  const bucket = hash % 100
 
  let cumulative = 0
  for (let i = 0; i < experiment.variants.length; i++) {
    cumulative += experiment.weights[i]
    if (bucket < cumulative) {
      // Log assignment
      await logExperimentAssignment(userId, experiment.name, experiment.variants[i])
      return experiment.variants[i]
    }
  }
  return experiment.variants[0]
}
 
// ใช้งาน
const checkoutExperiment: Experiment = {
  name: "checkout_cta_q1_2025",
  variants: ["control", "buy_now"],
  weights: [50, 50],  // 50/50 split
  startDate: new Date("2025-01-15"),
  endDate: new Date("2025-01-29"),
}
 
const variant = await getVariant(session.user.id, checkoutExperiment)
const buttonText = variant === "buy_now" ? "Buy Now" : "Checkout"

Event Tracking สำหรับ A/B Test

// src/lib/analytics.ts
export async function trackEvent(
  userId: string,
  event: string,
  properties: Record<string, unknown>
) {
  await db.analyticsEvent.create({
    data: {
      userId,
      event,
      properties: JSON.stringify(properties),
      timestamp: new Date(),
    }
  })
}
 
// Track สำคัญใน checkout flow
await trackEvent(userId, "checkout_started", {
  experiment: "checkout_cta_q1_2025",
  variant: variant,
  cartValue: cart.total,
})
 
await trackEvent(userId, "order_completed", {
  experiment: "checkout_cta_q1_2025",
  variant: variant,
  orderId: order.id,
  revenue: order.total,
})

วิเคราะห์ผล A/B Test

> วิเคราะห์ผล A/B test นี้:
 
  Experiment: checkout_cta_q1_2025
  Duration: 2025-01-15 ถึง 2025-01-29
 
  Control (Checkout):
  - Impressions: 5,234
  - Conversions: 523 (10.0% conversion rate)
  - Revenue: ฿2,615,000
 
  Variant (Buy Now):
  - Impressions: 5,198
  - Conversions: 571 (10.98% conversion rate)
  - Revenue: ฿2,882,000
 
  บอกผม:
  1. Statistical significance (p-value)?
  2. Confidence interval?
  3. Effect size?
  4. ควร ship variant หรือไม่ พร้อมเหตุผล
  5. คำแนะนำ next experiment
 
# SQL Query วิเคราะห์
SELECT
  properties->>variant AS variant,
  COUNT(DISTINCT CASE WHEN event = "checkout_started" THEN userId END) as impressions,
  COUNT(DISTINCT CASE WHEN event = "order_completed" THEN userId END) as conversions,
  ROUND(100.0 * COUNT(DISTINCT CASE WHEN event = "order_completed" THEN userId END)
    / COUNT(DISTINCT CASE WHEN event = "checkout_started" THEN userId END), 2) AS conversion_rate,
  SUM(CASE WHEN event = "order_completed" THEN (properties->>revenue)::numeric END) AS revenue
FROM analytics_events
WHERE properties->>experiment = "checkout_cta_q1_2025"
  AND timestamp BETWEEN "2025-01-15" AND "2025-01-29"
GROUP BY variant

เสริมจากบทที่ 4: Loop Debugging ขั้น Advanced

บทที่ 4 ให้ Protocol พื้นฐาน ส่วนนี้จะลงลึกเทคนิคที่ใช้ได้กับ production bugs ที่ซับซ้อนกว่า

Root Cause Analysis (RCA) Framework

เมื่อ production มีปัญหาใหญ่ ใช้ RCA หา root cause จริงๆ ไม่ใช่แค่แก้ symptom:

# .claude/commands/rca.md
# Root Cause Analysis
 
ทำ RCA สำหรับ incident นี้:
 
## Timeline
สร้าง timeline ว่าอะไรเกิดขึ้นตามลำดับ:
- [เวลา] เกิดอะไร
- [เวลา] ใครพบ
- [เวลา] ทำอะไรแก้
- [เวลา] กลับมาปกติ
 
## 5 Whys Analysis
ถามว่า "ทำไม" ซ้ำ 5 ครั้งจนถึง root cause:
ทำไม? → ทำไม? → ทำไม? → ทำไม? → ทำไม?
 
## Root Causes
- Proximate cause: สิ่งที่ทำให้เกิด incident โดยตรง
- Root cause: ต้นตอที่แท้จริง
- Contributing factors: ปัจจัยที่ทำให้รุนแรงขึ้น
 
## Impact
- Users affected: [จำนวน]
- Duration: [เวลา]
- Revenue impact: [ประมาณ]
 
## Action Items
| Action | Owner | Priority | Due Date |
|--------|-------|----------|----------|
| [แก้ root cause] | [ชื่อ] | P0 | [วันที่] |
| [ป้องกันซ้ำ] | [ชื่อ] | P1 | [วันที่] |
 
## ป้องกัน recurrence
อะไรที่ต้องเปลี่ยนใน process, code, หรือ monitoring?

Production Debugging Protocol

เมื่อ production มีปัญหาและต้องแก้เร็ว Protocol นี้ช่วยให้คิดอย่างเป็นระบบแม้ตอนกดดัน:

1Assess — ประเมินก่อน
Critical หรือไม่? User กี่คนได้รับผล? Revenue impact? ต้อง rollback ทันทีไหม?
> Production incident: [อธิบายปัญหา]
  มี error log นี้:
  [paste logs]
 
  ช่วยประเมิน:
  1. Severity: P0/P1/P2/P3?
  2. Blast radius: กระทบ user กี่ %?
  3. ควร rollback ทันทีหรือแก้ไปข้างหน้า?
  4. ถ้าแก้: ใช้เวลานานแค่ไหน?
 
  ตอบภายใน 2 นาทีโดยไม่ต้องสมบูรณ์ 100%
  ต้องการ decision ก่อน
2Contain — หยุดความเสียหาย
ทำให้ระบบ stable ก่อน แม้จะยังไม่ได้แก้ root cause
# วิธี contain ที่พบบ่อย
# 1. Rollback deployment
vercel rollback  # หรือ git revert + deploy
 
# 2. Feature flag ปิด feature ที่มีปัญหา
await setFeatureFlag("new_payment", false)
 
# 3. Rate limiting เพื่อลด load
# 4. Redirect traffic ออกจาก broken endpoint
# 5. Scale up servers ถ้า load issue
3Diagnose — หา root cause
วิเคราะห์อย่างเป็นระบบ ไม่ใช่เดาสุ่ม
> วิเคราะห์ production incident:
 
  Logs ที่เก็บได้:
  [paste logs ทั้งหมด]
 
  Timeline:
  - 14:30 น. Deploy version 2.4.1
  - 14:45 น. Error rate เริ่มสูง
  - 15:00 น. User complaints
 
  Code ที่เปลี่ยนใน v2.4.1:
  [paste git diff หรือ PR description]
 
  ช่วย:
  1. วิเคราะห์ logs หา pattern
  2. เชื่อม logs กับ code ที่เปลี่ยน
  3. Identify root cause ที่น่าจะเป็นไปได้มากที่สุด
  4. เสนอ diagnostic steps เพิ่มเติมถ้ายังไม่แน่ใจ
4Fix — แก้และ verify
แก้ root cause พร้อมทดสอบก่อน deploy
5Document — บันทึกทุกอย่าง
สร้าง post-mortem ป้องกันซ้ำ

การจัดการ Dependencies ที่ทำให้เกิด Loop

บ่อยครั้ง loop เกิดจาก dependency ที่มี bug หรือ breaking change ไม่ใช่โค้ดของเราเอง:

> Error นี้เกิดหลัง update packages:
  TypeError: Cannot read property "x" of undefined
  ใน node_modules/some-library/index.js
 
  npm list | grep some-library
  some-library@3.0.0  ← update จาก 2.x
 
  ช่วย:
  1. วิเคราะห์ว่า breaking change อยู่ที่ไหน
  2. ดู changelog ของ library ว่าต้องทำอะไรบ้าง
  3. เสนอ migration path
  4. ถ้า migration ซับซ้อน เสนอ downgrade
     พร้อม lock version เพื่อ stability
 
# Lock version ป้องกัน auto-update
# package.json
"some-library": "2.8.1"  # ใช้ exact version
# ไม่ใช่ "^2.8.1" (อนุญาต minor update)
# ไม่ใช่ "~2.8.1" (อนุญาต patch update)

Debugging ด้วย Time Travel (Git Bisect Automation)

เมื่อไม่รู้ว่า commit ไหนทำให้เกิดบัก ใช้ Git Bisect อัตโนมัติ:

# สร้าง bisect script อัตโนมัติ
# bisect-test.sh
#!/bin/bash
# Script นี้จะถูกรันโดย git bisect
# exit 0 = good commit
# exit 1 = bad commit
 
npm run build 2>/dev/null  # ต้อง build ได้
if [ $? -ne 0 ]; then exit 1; fi
 
# รัน specific test ที่เกี่ยวกับ bug
npx vitest run tests/pricing.test.ts 2>/dev/null
exit $?
 
# รัน bisect
git bisect start
git bisect bad HEAD
git bisect good v2.3.0  # version ที่รู้ว่าดี
git bisect run ./bisect-test.sh
 
# Git จะหา commit ที่ทำให้เกิดบักอัตโนมัติ
# จากนั้นให้ Claude วิเคราะห์
> ได้ bad commit นี้:
  [paste commit diff]
  อธิบายว่า commit นี้ทำให้เกิด bug อย่างไร
  และวิธีแก้ที่ถูกต้อง

Memory Leak Detection

Memory leak ทำให้ server ช้าลงเรื่อยๆ จนต้อง restart เป็น production bug ที่พบบ่อยแต่หายาก:

> สงสัยว่ามี memory leak ใน @src/server/
  Memory เพิ่มจาก 200MB เป็น 800MB ใน 24 ชั่วโมง
  แล้ว restart ลดลงมา 200MB ใหม่
 
  ช่วยสร้าง:
  1. Memory monitoring endpoint: GET /api/debug/memory
     แสดง heap used, heap total, RSS
  2. Leak detection script ที่รัน
     ทุก 1 นาทีแล้ว log ถ้า memory เพิ่ม > 10MB/นาที
  3. Suspect code analysis:
     ดู @src/server/ หา patterns ที่มักทำให้ memory leak:
     - EventEmitter ที่ไม่ removeListener
     - setTimeout/setInterval ที่ไม่ clearTimeout
     - Closure ที่ hold reference
     - Cache ที่ไม่มี size limit
     - Stream ที่ไม่ปิด
 
// memory-monitor.ts
setInterval(() => {
  const mem = process.memoryUsage()
  console.log({
    heapUsed: Math.round(mem.heapUsed / 1024 / 1024) + "MB",
    heapTotal: Math.round(mem.heapTotal / 1024 / 1024) + "MB",
    rss: Math.round(mem.rss / 1024 / 1024) + "MB",
    timestamp: new Date().toISOString()
  })
}, 60000)

ตัวอย่าง: Feature ตั้งแต่ Vibe Coding ถึง Production จริง

ตัวอย่างนี้ walk through feature “ระบบ Coupon” ตั้งแต่เริ่มจนถึง production และ A/B test ให้เห็น full pipeline จริงๆ

Day 1: Vibe Coding
> สร้าง Coupon system:
  - Table: coupons (code, type, value, max_uses, expires_at)
  - Validate coupon: check code, expiry, usage limit
  - Apply coupon: ลดราคาตาม type (percent/fixed)
  - Track usage: บันทึกว่า user ไหนใช้
 
  Tech: Next.js + Prisma + PostgreSQL
  ทำ step by step รอ approve
Day 2: Testing
# หลัง implement เสร็จ
> เขียน comprehensive tests:
  - Unit: validateCoupon, calculateDiscount
  - Integration: POST /api/coupons/apply
  - Edge cases: หมดอายุ, หมด uses, coupon ซ้ำ
 
> เขียน E2E test:
  - User กรอก coupon code → เห็นราคาลด → checkout
 
# รัน tests
npm test
 
# ถ้า fail ไม่แก้เอง ส่ง error ให้ Claude
> test ที่ fail คือ:
  [paste error]
  แก้ให้ผ่านโดยไม่แก้ test logic
Day 3: Security + Performance
# Security audit
> /project:security-audit
 
# Performance benchmark
> benchmark validateCoupon function:
  - 100 calls consecutive
  - 50 concurrent calls
  - Database query analysis
 
# พบว่า lookup query ช้า 200ms
> เพิ่ม index บน coupons.code
  และ coupon_usages.coupon_id + user_id
 
# benchmark อีกครั้งหลัง index
# ได้ 8ms (เร็วขึ้น 25x)
Day 4: QA + Staging Deploy
# สร้าง QA test plan
> สร้าง test plan สำหรับ coupon feature
  ครอบคลุม functional, negative, boundary, UX
 
# Deploy to staging
git push origin feature/coupon-system
# Vercel สร้าง preview URL อัตโนมัติ
 
# รัน regression tests บน staging
npx playwright test tests/e2e/ --project=chromium \
  --config=playwright.staging.config.ts
 
# Deploy check
> /project:deploy-check
Day 5: Production + Monitoring
# Canary deploy: 10% ของ users ก่อน
# ตั้ง feature flag: coupon_system = 10%
 
# Monitor 24 ชั่วโมง
# - Error rate ปกติ
# - Coupon apply success rate > 99%
# - ไม่มี double-apply bugs
 
# ถ้าผ่าน → 100% users
# ตั้ง feature flag: coupon_system = 100%
Day 14: A/B Test ผล
# หลังจาก coupon system stable 1 สัปดาห์
# A/B test: "First-time coupon" popup
 
> วิเคราะห์ผล A/B test:
  Control: ไม่มี popup
  - Conversion rate: 8.2%
  - Average order value: ฿850
 
  Variant: Popup แจก 10% coupon สำหรับ new user
  - Conversion rate: 11.5% (+40%!)
  - Average order value: ฿780 (-8%)
  - Net revenue per user: +29%
 
  p-value: 0.001 (statistically significant)
  Confidence: 99.9%
 
  Decision: Ship variant ทั้ง 100%
  Next test: ทดลอง 15% vs 10% coupon

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

Quality Gateเกณฑ์คุณภาพที่โค้ดต้องผ่านก่อนจะไปขั้นตอนถัดไปได้
Testing Pyramidหลักการแบ่งสัดส่วน tests: Unit (70%) Integration (20%) E2E (10%)
Integration Testทดสอบที่ component หลายตัวทำงานร่วมกัน รวมถึง database จริง
E2E TestEnd-to-End ทดสอบทั้งระบบจาก browser จริง เหมือน user จริง
Core Web Vitalsชุด metrics ที่ Google ใช้วัด UX: LCP, INP, CLS
Load Testingทดสอบระบบด้วย traffic จำนวนมากเพื่อหา bottleneck
k6เครื่องมือ Load testing แบบ code-first ยอดนิยม
OWASP Top 10รายการช่องโหว่ความปลอดภัยเว็บที่พบบ่อยที่สุด 10 อันดับ
IDORInsecure Direct Object Reference ช่องโหว่ที่ user เข้าถึงข้อมูลคนอื่น
Blue-Green DeployDeploy strategy ที่มี 2 environment สลับกัน rollback ได้ทันที
Canary Releaseปล่อย feature ให้ user บางส่วนก่อน ค่อยขยายถ้าไม่มีปัญหา
Feature FlagSwitch เปิด/ปิด feature โดยไม่ต้อง deploy code ใหม่
A/B Testingทดสอบ 2 version พร้อมกันเพื่อวัดว่า version ไหนดีกว่าจาก data จริง
Statistical Significanceความมั่นใจทางสถิติว่าผลที่เห็นไม่ได้เกิดจากโชค
P95/P99Percentile 95/99 เวลา response ที่ช้า 5%/1% ของ requests
Root Cause Analysis (RCA)กระบวนการหา “ทำไม” จริงๆ ไม่ใช่แค่แก้ symptom
Post-mortemเอกสารวิเคราะห์ incident หลังผ่านไป เพื่อป้องกันซ้ำ
Regression Testทดสอบว่า feature เก่ายังทำงานได้หลัง deploy ใหม่
Memory Leakการที่ program ใช้ memory มากขึ้นเรื่อยๆ โดยไม่คืน