บทที่ 1 · Part 1 — Foundation
What System Design Is
Quality attribute, constraint และการ defend การตัดสินใจ — คำตอบ 4 แบบของ architect และ design loop
มีคำถามหนึ่งที่ทำให้ห้องประชุมเงียบได้ทุกครั้ง: "ทำไมต้องออกแบบแบบนี้" ถ้าคำตอบคือ "เพราะเป็น best practice" หรือ "เพราะ Netflix ทำแบบนี้" นั่นไม่ใช่ system design — นั่นคือการลอกโครงสร้างมาโดยไม่รู้ว่าโครงสร้างนั้นแก้ปัญหาอะไร
จบบทนี้คุณจะ
- นิยาม system design ได้เป็นประโยคเดียวที่ใช้งานได้จริง
- แยก quality attribute ออกจาก feature และรู้ว่าอันไหนกำหนดโครงสร้าง
- รู้จักคำตอบ 4 แบบของ architect และรู้ว่าเมื่อไหร่ต้องใช้อันที่ 4
- เข้าใจว่าทำไม design เป็น loop ไม่ใช่ waterfall
นิยามที่ใช้งานได้
System design คือการ เลือกโครงสร้าง ที่ทำให้ quality attribute เป็นจริง ภายใต้ constraint ที่มี และ defend การเลือกนั้นได้
ทั้งงานอยู่ในประโยคเดียวนี้ มี 3 คำที่ต้องขยาย
Quality attributes — สิ่งที่กำหนดโครงสร้างจริงๆ
Feature ไม่ค่อยกำหนดสถาปัตยกรรม แต่ quality attribute (หรือ non-functional requirement) กำหนด
"ระบบต้องโอนเงินได้" ไม่บอกอะไรเลยว่าต้องมีกี่ service ใช้ฐานข้อมูลอะไร แต่ "ต้องโอนได้ 1,000 tps ที่ p99 < 300 ms และห้ามเงินหายแม้ AZ ล่ม และต้องเก็บ audit trail 10 ปี" — อันนี้บังคับโครงสร้างแทบทั้งหมด
| Quality attribute | คำถามที่ต้องถามให้ได้ตัวเลข | หน่วยที่ต้องได้กลับมา |
|---|---|---|
| Throughput | peak เท่าไหร่ ไม่ใช่ average | req/s, txn/s, MB/s |
| Latency | p50/p99/p999 ของ endpoint ไหน | ms |
| Availability | ยอมล่มได้กี่นาทีต่อเดือน | % หรือ นาที/เดือน |
| Consistency | ข้อมูลเก่าได้กี่วินาที และเก่าตรงไหนไม่ได้เลย | วินาที + รายชื่อ field |
| Durability | ยอมเสียข้อมูลย้อนหลังได้กี่นาที | RPO เป็นวินาที/นาที |
| Security & privacy | ข้อมูลอะไรเป็น sensitive ใครเข้าถึงได้ | classification + access matrix |
| Cost | เพดานงบต่อเดือน และต้นทุนต่อ transaction | บาท/เดือน, บาท/txn |
| Operability | ทีมกี่คนดูแล มี on-call ไหม | คน, ชั่วโมง/สัปดาห์ |
| Time-to-market | ต้องขึ้นเมื่อไหร่ และอะไรเลื่อนได้ | วันที่ + scope ที่ตัดได้ |
เทคนิคเปลี่ยนคำคลุมเครือให้เป็นตัวเลข
ทุกครั้งที่ได้ยินคำว่า "เร็ว" "เยอะ" "ห้ามล่ม" "real-time" ให้ถามกลับ 2 คำถาม: "วัดที่ไหน" และ "เท่าไหร่ถือว่าไม่ผ่าน" ถ้าตอบไม่ได้ requirement นั้นยังไม่มีอยู่จริง — มีแต่ความรู้สึก
Constraints — สิ่งที่ทำให้ design เป็นงานวิศวกรรม ไม่ใช่งานอดิเรก
Constraint คือของที่คุณเปลี่ยนไม่ได้ในรอบนี้ และมันมักไม่ใช่เรื่อง technical:
- ทีม — มีคนกี่คน รู้ภาษาอะไร ดูแล Kubernetes เป็นไหม มี on-call rotation ไหม
- เงิน — งบ infra ต่อเดือน และงบสำหรับ vendor/license
- Regulator — สำหรับ fintech ไทยคือ BOT, PDPA, และถ้าแตะบัตรก็ PCI-DSS ข้อกำหนดเรื่องที่เก็บข้อมูล (data residency) และระยะเวลาเก็บเป็น constraint แข็ง
- สัญญาที่เซ็นไปแล้ว — vendor ที่ใช้อยู่, bank partner ที่ API เป็นแบบนี้แก้ไม่ได้
- ระบบเดิม — ฐานข้อมูลอายุ 8 ปีที่ยังมี business logic อยู่ใน stored procedure
- Deadline — วันที่ประกาศกับตลาดไปแล้ว
Design ที่ไม่พูดถึง constraint เลยคือ design ที่ยังไม่ถูกทดสอบว่าทำได้จริง
Defend — บอกได้ว่าแลกอะไรไป
Defend ไม่ได้แปลว่า "พิสูจน์ว่าถูก" แต่แปลว่า บอกได้ว่ายอมเสียอะไรเพื่อได้อะไร รูปประโยคที่ใช้ได้:
"เราเลือก eventual consistency สำหรับ notification feed ยอมรับความเก่าได้ถึง 5 วินาที เพราะผลกระทบทางธุรกิจคือ badge count ขึ้นช้า ไม่ใช่ยอดเงินผิด — ส่วนยอดเงินเราใช้ strong read จาก primary เสมอ"
สังเกตว่ามี 3 ส่วน: เลือกอะไร, ยอมเสียอะไรเป็นตัวเลข, เพราะผลกระทบคืออะไร
The three-sentence test
Design ที่คุณเสนอควรย่อเป็น 3 ประโยคได้: มันทำอะไร, มันอยู่รอดได้ยังไง, มันยอมเสียอะไร ถ้าย่อไม่ได้ แปลว่าคุณยังไม่เข้าใจ design ของตัวเอง ลองทำกับระบบที่คุณดูแลอยู่ตอนนี้เลย
คำตอบ 4 แบบของ architect
Engineer ที่ยังใหม่พยายามมีคำตอบให้ทุกคำถาม architect ที่โตแล้วมีคำตอบ 4 แบบ และใช้แต่ละแบบอย่างแม่นยำ
| # | รูปประโยค | หมายความว่า | สิ่งที่ต้องทำต่อ |
|---|---|---|---|
| 1 | "นี่คือ design และนี่คือเหตุผล" | คุณรู้จริง | เขียนเป็น ADR |
| 2 | "ขึ้นอยู่กับ X — ถ้า X เป็น A ใช้แบบ 1, ถ้าเป็น B ใช้แบบ 2" | คุณรู้ทางแยก แต่ไม่รู้ input | ไปหา X ให้ได้ |
| 3 | "ยังไม่รู้ — นี่คือวิธีที่จะหาคำตอบ และจะรู้เมื่อไหร่" | คุณรู้ว่าไม่รู้ | spike / load test / ถาม vendor |
| 4 | "อันนี้ไม่ใช่การตัดสินใจของผม" | เรื่องนี้มีเจ้าของอื่น | escalate พร้อมทางเลือก |
คำตอบแบบที่ 4 สำคัญที่สุดในองค์กรที่ถูกกำกับดูแล และเป็นแบบที่ engineer มักข้าม ให้ฝึกจับสัญญาณ — เรื่องพวกนี้ ไม่ใช่ ของ architect คนเดียว:
- เพดานการโอน/ถอนต่อวัน และเงื่อนไขที่ยอมให้ทำรายการได้
- ระยะเวลาเก็บข้อมูลลูกค้าและข้อมูลธุรกรรม
- KYC tier threshold และเกณฑ์ที่ถือว่าเป็นธุรกรรมน่าสงสัย
- การยอมรับ security exception หรือ compensating control
- การแถลงต่อสาธารณะเมื่อเกิด incident
อย่าคิดนโยบายขึ้นมาเองในโค้ด
การ hardcode if amount > 50000 { reject } โดยไม่มีเอกสารว่าใครอนุมัติเลข 50,000
คือการเขียนนโยบายบริษัทลงในไฟล์ Go — และเวลา auditor ถามว่า "ใครกำหนดเลขนี้"
จะไม่มีคำตอบ ให้ทำ 2 อย่าง: ดึงเลขออกเป็น configuration
และบันทึกว่าใครอนุมัติเมื่อไหร่
Design เป็น loop ไม่ใช่ waterfall
Design ที่แย่ส่วนใหญ่มาจากการรับ requirement ที่ไม่เคยเป็นเรื่องจริงมาตั้งแต่ต้น การประมาณตัวเลขเร็วๆ คือวิธี push back ด้วยหลักฐานแทนที่จะเถียงด้วยความเห็น
ตัวอย่างที่เกิดบ่อย: business บอกว่า "วันแรกจะมีผู้ใช้ 1 ล้านคน" คุณคำนวณ 10 นาทีแล้วพบว่าถ้าเป็นจริงต้องมี 40 node กับ Kafka cluster พอเอาตัวเลขไปคุย ปรากฏว่าตัวเลขจริงคือ 20,000 คนในไตรมาสแรก — design ทั้งหมดเปลี่ยน และคุณประหยัดงบไปหลายแสนต่อเดือน
จุดที่ควรวน loop ให้เร็วที่สุด
วน requirements → estimate ให้จบก่อนเริ่มวาด box ใดๆ
การวาด architecture ทำให้คนในห้องรู้สึกว่าตกลงกันแล้ว
ทั้งที่ยังไม่มีใครรู้ว่าระบบต้องรับโหลดเท่าไหร่
สิ่งที่ system design ไม่ใช่
| ไม่ใช่ | เพราะ |
|---|---|
| การเลือก tech stack | stack เป็นผลลัพธ์ของ requirement ไม่ใช่จุดเริ่ม |
| การวาด box กับลูกศรให้สวย | diagram คือเครื่องมือสื่อสาร ไม่ใช่ตัว design (บทที่ 20) |
| การ copy สถาปัตยกรรมของบริษัทใหญ่ | บริษัทเหล่านั้นมี constraint ต่างจากคุณสิ้นเชิง |
| การหาคำตอบที่ "ถูกที่สุด" | มีแต่คำตอบที่เหมาะกับ constraint ชุดนี้ ณ เวลานี้ |
| งานที่ทำครั้งเดียวจบ | ระบบเปลี่ยน โหลดเปลี่ยน ทีมเปลี่ยน — design ต้องถูกทบทวน |
Resume-driven design
อาการ: เลือกเทคโนโลยีเพราะอยากใช้ ไม่ใช่เพราะปัญหาต้องการ วิธีตรวจตัวเอง — ตอบคำถามนี้ให้ได้ว่า "ถ้าไม่ใช้ของนี้ อะไรจะพัง และพังเมื่อโหลดเท่าไหร่" ถ้าตอบไม่ได้ คุณยังไม่มีเหตุผลที่จะใช้มัน (รายการ anti-pattern ทั้งชุดอยู่ในบทที่ 17)
Lab 1 — ทดสอบ design ที่คุณมีอยู่
หยิบระบบที่คุณดูแลอยู่จริง 1 ตัว แล้วทำ 3 อย่าง (ใช้เวลาประมาณ 20 นาที):
- เขียน three-sentence test — มันทำอะไร / อยู่รอดได้ยังไง / ยอมเสียอะไร ถ้าประโยคที่ 3 เขียนไม่ออก แปลว่าไม่มีใครเคยตัดสินใจเรื่องนั้นอย่างตั้งใจ
- ลิสต์ quality attribute ที่มีตัวเลขจริง — เทียบกับตารางด้านบน ช่องไหนว่างคือความเสี่ยงที่ยังไม่ถูกวัด
- หา "คำตอบแบบที่ 4" ที่ซ่อนอยู่ในโค้ด — ค่า threshold, retention, limit ที่ไม่มีเอกสารว่าใครอนุมัติ เขียนรายการนี้ไว้ แล้วเอาไปคุยกับเจ้าของเรื่อง
สรุปบทนี้
System design คือการเลือกโครงสร้างให้ quality attribute เป็นจริงภายใต้ constraint แล้วอธิบายได้ว่าแลกอะไรไป — ตัวเลขมาก่อนกล่อง, constraint มาก่อนเทคโนโลยี, และเรื่องที่มีเจ้าของอื่นต้อง escalate ไม่ใช่ตัดสินเองในโค้ด บทถัดไป คือตัวเลขที่ต้องจำเพื่อทำ loop นี้ให้เร็วพอใช้งานในห้องประชุม