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

ใช้งานใน Production

จาก vibe coding สู่ production จริง — 8 phase ตั้งแต่ quality gate, testing, security audit ตาม OWASP, performance, QA, deployment, monitoring จนถึง A/B test

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

บทที่ 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 มากขึ้นเรื่อยๆ โดยไม่คืน