ใช้งานใน Production
จาก vibe coding สู่ production จริง — 8 phase ตั้งแต่ quality gate, testing, security audit ตาม OWASP, performance, QA, deployment, monitoring จนถึง A/B test
บทที่ 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 ช่วยอะไร |
|---|---|---|---|
| 1 | Code Quality | Lint, Format, Type check | Auto-fix + review |
| 2 | Unit Testing | Test ทุก function ทุก edge case | เขียน + รัน test |
| 3 | Integration Testing | Test ที่ component ทำงานร่วมกัน | สร้าง test scenario |
| 4 | Security Audit | หาช่องโหว่ก่อน deploy | OWASP checklist |
| 5 | Performance | Benchmark + optimize | หา bottleneck |
| 6 | QA Testing | Manual + automated E2E | สร้าง test plan |
| 7 | Staging Deploy | ทดสอบใน environment จริง | Deployment script |
| 8 | Monitoring Setup | Log, metric, alert | เขียน dashboard |
| 9 | Production Deploy | Release strategy | Blue/green, canary |
| 10 | A/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 คืออะไร:
| Metric | Poor | Needs Work | Good | Excellent |
|---|---|---|---|---|
| Page Load (LCP) | > 4s | 2.5-4s | < 2.5s | < 1s |
| API Response (P95) | > 1000ms | 500-1000ms | < 500ms | < 100ms |
| Time to Interactive | > 5s | 3.8-5s | < 3.8s | < 1s |
| First Byte (TTFB) | > 1800ms | 900-1800ms | < 900ms | < 200ms |
| Core Web Vitals (CLS) | > 0.25 | 0.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 ID | Test Case | Steps | Expected | Priority |
|---|---|---|---|---|
| QA-001 | แก้ชื่อสำเร็จ | 1.กรอกชื่อใหม่ 2.Save | ชื่อเปลี่ยนทันที | High |
| QA-002 | ชื่อว่างเปล่า | 1.ลบชื่อออก 2.Save | Error: Name required | High |
| QA-003 | ชื่อยาวเกิน | 1.กรอก 200 ตัว 2.Save | Error: Max 100 chars | Medium |
| QA-004 | Email ใหม่ | 1.เปลี่ยน email 2.Save | Email verify ถูกส่ง | High |
| QA-005 | Avatar ขนาดใหญ่ | 1.Upload 5MB PNG | Auto resize < 500KB | Medium |
| QA-006 | Avatar format ผิด | 1.Upload .pdf | Error: Invalid format | Medium |
| QA-007 | Preview ก่อน save | 1.เปลี่ยนรูป 2.ดู preview | Preview ถูกต้อง | 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 | ใช้สำหรับ | Database | Deploy เมื่อ |
|---|---|---|---|
| Local Dev | Development ส่วนตัว | Local SQLite/PG | ตลอดเวลา |
| Staging | QA + Integration test | Staging DB (copy prod) | ทุก PR merge |
| Preview | Review per PR | ใช้ร่วมกับ Staging | ทุก PR สร้าง |
| Production | User จริง | Production DB | Manual 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 ที่คาดว่าจะกระทบ conversion | Bug fixes (ชัดเจนว่าต้องแก้) |
| Pricing หรือ promotion strategy | Security improvements |
| Onboarding flow ใหม่ | Feature ที่ทุกคน request |
| CTA copy หรือ button design | Technical 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 นี้ช่วยให้คิดอย่างเป็นระบบแม้ตอนกดดัน:
| 1 | Assess — ประเมินก่อน 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 ก่อน
| 2 | Contain — หยุดความเสียหาย ทำให้ระบบ 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
| 3 | Diagnose — หา 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 เพิ่มเติมถ้ายังไม่แน่ใจ
| 4 | Fix — แก้และ verify แก้ root cause พร้อมทดสอบก่อน deploy |
|---|
| 5 | Document — บันทึกทุกอย่าง สร้าง 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 Test | End-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 อันดับ |
| IDOR | Insecure Direct Object Reference ช่องโหว่ที่ user เข้าถึงข้อมูลคนอื่น |
| Blue-Green Deploy | Deploy strategy ที่มี 2 environment สลับกัน rollback ได้ทันที |
| Canary Release | ปล่อย feature ให้ user บางส่วนก่อน ค่อยขยายถ้าไม่มีปัญหา |
| Feature Flag | Switch เปิด/ปิด feature โดยไม่ต้อง deploy code ใหม่ |
| A/B Testing | ทดสอบ 2 version พร้อมกันเพื่อวัดว่า version ไหนดีกว่าจาก data จริง |
| Statistical Significance | ความมั่นใจทางสถิติว่าผลที่เห็นไม่ได้เกิดจากโชค |
| P95/P99 | Percentile 95/99 เวลา response ที่ช้า 5%/1% ของ requests |
| Root Cause Analysis (RCA) | กระบวนการหา “ทำไม” จริงๆ ไม่ใช่แค่แก้ symptom |
| Post-mortem | เอกสารวิเคราะห์ incident หลังผ่านไป เพื่อป้องกันซ้ำ |
| Regression Test | ทดสอบว่า feature เก่ายังทำงานได้หลัง deploy ใหม่ |
| Memory Leak | การที่ program ใช้ memory มากขึ้นเรื่อยๆ โดยไม่คืน |