Skip to content

บทที่ 00 — Microservices Mindset: ก่อนจะเริ่มเขียน ต้องเข้าใจ "ทำไม"

สารบัญ | บทที่ 01: Service Decomposition →

TL;DR: กล่องนี้เป็นแค่ "ตัวอย่างล่วงหน้า" — ถ้าศัพท์ยังไม่คุ้นไม่ต้องห่วง ทุกคำจะถูกอธิบายเต็ม ๆ ในเนื้อหาด้านล่าง บทนี้ตอบ "เมื่อไหร่ควร/ไม่ควรใช้ microservices" ผ่านหัวข้อเหล่านี้:

  • นิยาม microservices ของ Sam Newman
  • สเปกตรัม monolith ↔ micro (ช่วงต่อเนื่องระหว่าง 2 ขั้ว ไม่ใช่เลือกได้แค่ 2 แบบ)
  • 8 fallacies of distributed computing (8 ความเชื่อผิด ๆ เรื่องระบบกระจาย — กับดักคลาสสิกที่คน dev distributed ใหม่ ๆ ตกทุกคน)
  • monolith comeback — กระแสย้ายกลับ monolith (Prime Video 2023, Shopify, DHH)
  • distributed monolith (โมโนลิธกระจายตัว — บอกว่าเป็น microservices แต่จริง ๆ ทุก service ต้อง deploy พร้อมกัน = ได้แต่ความซับซ้อนของ distributed system โดยไม่ได้ประโยชน์)
  • cost equation (สมการต้นทุน — ชั่งน้ำหนัก benefit vs overhead ของ microservices)
  • anti-patterns (รูปแบบที่ควรเลี่ยง) และ Strangler Fig (วิธีค่อย ๆ ย้ายจาก monolith ไป microservices)

ข้ามได้ถ้า: อ่าน Sam Newman มาแล้ว + ไม่หลงตามกระแสอยู่แล้ว — แต่เนื้อหาพื้นฐาน (basic) ห้ามข้าม

บทนี้ยาว และไม่มีโค้ดเลย — อ่านให้จบก่อนข้ามไปบทอื่น เพราะถ้าผิดตั้งแต่ mindset ทุกบทหลังจะผิดตาม

เป้าหมายของบทนี้:

  1. เข้าใจว่า microservices คืออะไร จริง ๆ (ไม่ใช่แค่ "service เล็ก ๆ")
  2. รู้ว่ามันมา จากปัญหาอะไร และก่อนหน้านี้คนแก้ยังไง
  3. รู้ว่า เมื่อไหร่ควรใช้ และ เมื่อไหร่ไม่ควรใช้ (อันนี้สำคัญที่สุด)
  4. รู้จัก 8 fallacies of distributed computing — กับดักที่คนใหม่ตกทุกคน
  5. มี framework สำหรับตัดสินใจ "เริ่มจาก monolith หรือ microservices?"

ใช้เวลาประมาณ 60-90 นาที — อ่าน + คิดตาม


Part 1: Microservices คืออะไร (จริง ๆ)

1.1 นิยามที่ฟังบ่อยที่สุด (และที่มันยังไม่พอ)

ถ้าคุณ Google "what is microservices" จะเจอประมาณนี้:

"An architectural style that structures an application as a collection of small, autonomous services."

แปลตรงตัว: "สถาปัตยกรรมที่ตัดแอปเป็น service เล็ก ๆ หลายตัวที่ทำงานเป็นอิสระต่อกัน"

ฟังดูง่ายใช่มั้ย? แต่นิยามนี้ ผิดและถูกในเวลาเดียวกัน เพราะคำว่า:

  • "small" — เล็กแค่ไหน? 100 บรรทัด? 10,000 บรรทัด?
  • "autonomous" — แปลว่าอะไร? คุยกันไม่ได้เลย?
  • "a collection of services" — service ใน monolith เก่า ๆ ก็มีเหมือนกัน

ถ้าจะให้นิยามที่ใช้ตัดสินใจได้จริง ๆ ผมชอบนิยามของ Sam Newman (ผู้เขียน "Building Microservices") มากกว่า:

"Microservices (ไมโครเซอร์วิส) are independently releasable (ปล่อยได้อิสระ) services (service หลายตัว) that are modeled around (ออกแบบโดยยึด) a business domain (โดเมนธุรกิจ)."

— Sam Newman

(แปลเต็ม: "Microservices คือ service ที่ปล่อย/deploy ได้อย่างอิสระแต่ละตัว และถูกออกแบบโดยยึดตามขอบเขตของธุรกิจ")

📖 กางศัพท์: คำว่า releasable = "ปล่อยออก/ขึ้นใช้งานได้" (release = การปล่อยเวอร์ชันใหม่ของซอฟต์แวร์), independently = "อย่างอิสระ ไม่ขึ้นกับใคร", business domain = "ขอบเขตของงานธุรกิจ" เช่น การสั่งซื้อ การจ่ายเงิน การจัดส่ง

คีย์เวิร์ดสำคัญคือ "independently releasable" (deploy ทีละตัวได้โดยไม่กระทบตัวอื่น — คำว่า deploy = "นำขึ้นเครื่อง server ให้ทำงานจริง") และ "modeled around a business domain" (ตัดตามธุรกิจ ไม่ใช่ตามเทคโนโลยี)

ขยาย 2 คำนี้:

"Independently releasable"

หมายถึง: ถ้าคุณแก้โค้ดใน service A แล้วต้อง deploy service B ตามด้วย → คุณยังไม่ได้ทำ microservices, คุณยังทำ monolith ที่กระจายตัวอยู่ (distributed monolith = ตัดเป็น service หลายตัวแล้ว แต่ยังต้อง deploy พร้อมกันเหมือน monolith เดิม — ลงลึกเต็มที่ Part 6.1)

ตัวอย่างที่ ใช่ microservices:

  • แก้ pricing rule ใน pricing-service → deploy แค่ตัวเดียว, order-service ที่เรียกใช้ไม่ต้องแก้
  • เพิ่ม field ใน database ของ user-service → ไม่กระทบ notification-service

ตัวอย่างที่ ไม่ใช่:

  • แก้ schema ใน DB ที่ share กัน 5 service → ต้อง deploy 5 ตัวพร้อมกัน
  • เพิ่ม field ใน DTO (Data Transfer Object — ก้อนข้อมูลที่ service ส่งหากัน) → service ที่เรียกใช้ทุกตัวต้อง redeploy

"Modeled around a business domain"

หมายถึง: แต่ละ service ต้องสะท้อน "หน่วยธุรกิจ" ไม่ใช่ "หน่วยเทคนิค"

ตัด service ที่ผิด (ตามเทคนิค):

text
- database-service     (← ทำเรื่อง DB ทั้งหมด)
- email-service        (← ส่ง email ให้ทุกคน)
- auth-service         (← auth ของทุก feature)
- frontend-service     (← UI ของทุกหน้า)

ตัด service ที่ถูก (ตาม domain):

text
- catalog              (← จัดการสินค้า — มี DB ของตัวเอง, ส่ง email ตอนสินค้าหมด)
- ordering             (← รับ order — มี DB ของตัวเอง, ส่ง email confirm)
- shipping             (← จัดส่ง — มี DB ของตัวเอง, ส่ง email tracking)
- billing              (← เรียกเก็บเงิน — มี DB ของตัวเอง)

ความต่างคือ: ถ้าตัดตาม domain ตอน เพิ่ม feature ใหม่ เช่น "discount" คุณจะแก้แค่ ordering กับ billing ไม่ต้องไปแตะ email-service หรือ database-service ที่ทุกทีมต้อง coordinate กัน

💡 เปรียบเทียบกับชีวิตจริง: ถ้าบริษัทแบ่งแผนกตามทักษะ (แผนก "พิมพ์เอกสาร", "เซ็นชื่อ", "ส่งของ") — ทำ project เดียวก็ต้อง coordinate 3 แผนก. แต่ถ้าแบ่งตาม "ทีม sales", "ทีม marketing", "ทีม operations" — แต่ละทีมทำ end-to-end ได้เอง


1.2 Microservices ไม่ใช่ "service ตัวเล็ก ๆ"

มือใหม่หลายคนเข้าใจผิดว่า microservices = service ขนาดเล็ก → แตกเล็กที่สุดเท่าที่ทำได้

ผลคือ:

  • มี 50 service สำหรับ app ที่ user แค่ 1,000 คน
  • 1 user request ต้องวิ่งข้าม 8 service → latency พุ่ง
  • ทีม 5 คน maintain 50 service ไม่ไหว
  • debug ทีหนึ่งต้องเปิด log 12 ที่

ขนาดที่ถูกต้องคือ: "เล็กพอที่ทีมหนึ่งทีมจะดูแลได้, ใหญ่พอที่จะเป็นหน่วยธุรกิจเดียวที่สมบูรณ์"

มีคนเรียกว่า "Two-pizza rule" (กฎพิซซ่า 2 ถาด — สำนวนของ Amazon): ทีมที่ดูแล 1 service ควรกินพิซซ่า 2 ถาดอิ่ม = ไม่เกิน 8-10 คน (ไม่ใช่ถาดพิซซ่าจริง — เป็นการเปรียบเทียบขนาดทีม)

หรือ "Self-contained system" — service เดียวจัดการ:

  • API ของมัน
  • DB ของมัน
  • Business logic ของมัน
  • Frontend (ถ้ามี — เช่น admin ของ feature นั้น)

1.3 สเปกตรัม (spectrum = ช่วงต่อเนื่อง — ไม่ใช่ 2 ขั้ว) Monolith ↔ Microservices

อย่าคิดว่ามี 2 ขั้วเท่านั้น — มี สเปกตรัม ยาวอยู่ตรงกลาง

Monolith (โมโนลิธ)

ข้อดี:

  • Simple — 1 repo, 1 deploy, 1 DB
  • Local function call — เร็วมาก (nanosecond)
  • Transaction across modules ง่าย (ใช้ DB transaction)
  • Debug ง่าย (stack trace เดียวจบ)

ข้อเสีย (เมื่อโต):

  • Build/test ช้า (Java app 5GB compile 30 นาที)
  • Deploy 1 บรรทัดต้อง deploy ทั้งก้อน
  • 1 bug ทำล้มทั้งระบบ
  • Tech stack เปลี่ยนยาก (ทุกคนต้องใช้ Java เพราะของเดิมเป็น Java)
  • ทีมใหญ่ → conflict merge บ่อย

Modular Monolith (โมโนลิธแบบมีโมดูล)

เหมือน monolith แต่แบ่ง module ภายในให้ชัดเจน — เป็นจุดเริ่มต้นที่หลายทีมแนะนำ

สำคัญ: แต่ละ module คุยกันผ่าน public API ของ module เท่านั้น ห้ามเรียก internal directly

ข้อดี: ได้ separation of concern แบบ microservices แต่ไม่มี network overhead

คำแนะนำ: ถ้าคุณไม่แน่ใจว่าควรใช้ microservices ไหม → เริ่มจาก modular monolith ก่อนเสมอ. ถ้าต่อมาจำเป็นต้องแตกจริง ๆ การแตก module ที่ตัดชัดอยู่แล้วทำได้ง่ายกว่าแตก spaghetti monolith มาก

Service-Oriented Architecture (SOA) — รุ่นพี่ของ microservices

ก่อน microservices มี SOA (เกิดประมาณปี 2000s):

  • แตก app เป็น service เหมือนกัน
  • แต่คุยผ่าน Enterprise Service Bus (ESB) (อ่าน "อี-เอส-บี" = bus กลาง — ระบบส่งข้อความกลางที่ทุก service คุยผ่าน) — bus กลางที่จัดการทุก message
  • ใช้ SOAP (โปรโตคอลแลกเปลี่ยนข้อมูลแบบเก่า ห่อด้วย XML) + XML (หนัก)
  • มักจะ share database

ปัญหา: ESB กลายเป็น single point of failure (จุดเดียวที่พังได้ — ถ้าตัวนี้ตาย ทั้งระบบตาย) + bottleneck (คอขวด — จุดที่จำกัดความเร็วระบบ)

Microservices = SOA ที่ "เอา ESB ออก" + ใช้ HTTP/JSON หรือ lightweight message broker แทน

True Microservices

📖 Message Broker = ตัวกลางรับ-ส่ง message แบบ async (ไม่ต้องรอตอบกลับทันที) ระหว่าง service — จะอธิบายเต็มในบท 06

คุณสมบัติ:

  • แต่ละ service มี DB ของตัวเอง (ห้าม share!)
  • คุยผ่าน network (HTTP/gRPC sync, message broker async)
  • deploy ได้อิสระ
  • มี versioning ของ API

Part 2: ทำไมต้องมี Microservices (ประวัติย่อ)

2.1 ยุคก่อน — Monolith เหนือกาลเวลา

ก่อนปี 2010 ส่วนใหญ่เป็น Monolith:

  • 1 codebase ใหญ่
  • ทีม 100 คนช่วยกัน
  • 1 ไฟล์ war/ear ขนาด 2GB
  • Deploy 2-4 ครั้งต่อปี (ไม่ใช่ต่อวัน!)

ตัวอย่าง: ธนาคารยุค 90s รัน mainframe เดียว, code COBOL หลายล้านบรรทัด — เปลี่ยน 1 บรรทัดต้อง regression test 6 เดือน

2.2 ปัญหาที่ทำให้คนทนไม่ไหว

ปัญหา 1: Build/Deploy ช้าจน productivity ตก

text
ทีม 200 คน + monolith 5M lines
→ build 45 นาที, test suite 3 ชม.
→ คน A กับ คน B merge conflict ทุก PR
→ deploy ต้อง wait window — สัปดาห์ละครั้ง
→ ถ้า rollback ก็ rollback ทั้งก้อน (ทั้งที่บั๊กแค่ feature เดียว)

ปัญหา 2: Scale ไม่ตรงจุด

ถ้า search ใช้ CPU เยอะแต่ profile ไม่ค่อยใช้ → ต้อง scale ทั้ง app (ทุก instance รวม profile)

ปัญหา 3: Tech stack ถูกล็อค

ของเดิมเป็น Java → ทุก feature ใหม่ต้อง Java แม้ feature นั้น Python จะเหมาะกว่า

ปัญหา 4: 1 bug ฉุดทั้งระบบ

OutOfMemoryError (Java exception ตอน memory เต็ม) ใน 1 module ทำ JVM (Java Virtual Machine — engine ที่รัน Java program) ล้ม → ทั้ง app ตาย

2.3 จุดเริ่มต้น

ปี 2008-2011 — Amazon, Netflix, eBay, Spotify เริ่มแตก monolith ขนาดใหญ่ของตัวเอง

  • Amazon (2002): Jeff Bezos สั่งทุก team ต้องคุยกันผ่าน "service interface" เท่านั้น — ห้าม share DB. ใครละเมิด = ไล่ออก
  • Netflix (2008): หลังเหตุการณ์ DB corruption ที่ทำ Netflix ล่ม 3 วัน → ตัดสินใจย้ายไป AWS + microservices
  • Spotify (2012): "Squad model" — ทีมเล็ก 6-10 คน owns 1+ service

คำว่า "microservices" เริ่มใช้กันแพร่หลายราว 2014 จาก blog ของ James Lewis และ Martin Fowler

2.4 ⚠️ "Monolith comeback" — ลูกตุ้มแกว่งกลับ (2023-2026)

หลังจาก 10 ปีของ "microservices ทุกอย่าง" — ปี 2023-2026 มีกระแส "monolith comeback" (monolith กลับมา) หรือ "service repatriation" (นำ service กลับบ้าน — repatriation = นำกลับประเทศ; ในที่นี้ = ย้าย microservices กลับมารวมเป็น monolith):

🔥 Case 1: Amazon Prime Video (พ.ค. 2023)

ทีมย่อยที่ทำ audio/video quality monitoring ของ Prime Video (เครื่องมือเฉพาะทาง 1 ตัว ไม่ใช่ทั้งแพลตฟอร์ม Prime Video) เปิด blog เล่าการ ย้ายจาก serverless microservices กลับเป็น monolith — ผลคือ:

  • ลด cost ของเครื่องมือนั้นลง 90%
  • ลด latency
  • เพิ่ม scalability

สาเหตุ:

  • Service A เรียก B sync ทุก frame ของวิดีโอ → S3 (ที่เก็บไฟล์ของ AWS) storage cost + Lambda (บริการรันโค้ดเป็นครั้ง ๆ จ่ายตามจำนวนครั้งที่เรียก) invocation cost พุ่ง
  • Container orchestration cost (Step Functions — ตัวจัดลำดับงานของ AWS + Lambda) > business value
  • Modular monolith ที่ scale แนวตั้งทำงานดีกว่าสำหรับ workload "video frame analysis"

📖 คำเหล่านี้ (S3, Lambda, Step Functions) เป็นบริการเฉพาะของ AWS — เดี๋ยวเจอรายละเอียดในบทหลัง ตอนนี้แค่รู้ว่าแต่ละอย่างมีค่าใช้จ่ายที่ทบกันได้ก็พอ

📖 fan-out (high-fanout sync call) = การเรียก call ที่กระจายไปหลายปลายทางพร้อมกัน เช่น 1 request เรียก 10 service พร้อมกัน

Lesson: microservices ไม่ใช่ "ดีกว่า monolith เสมอ" — workload บาง pattern (per-frame analysis, high-fanout sync call) monolith จะดีกว่า

🔥 Case 2: Shopify (Modular Monolith)

Shopify รัน Rails monolith ขนาด ~3 ล้านบรรทัด, 1000+ engineer → ใช้ "Componentization" (modular monolith):

  • แยก packs/ (module) — บังคับ public API per module
  • Tool: Packwerk (open source) — enforce module boundary at compile time
  • 1 deploy, 1 DB → debug + transaction ง่าย
  • Scale ทีมโดยไม่ตัด service

→ "เราเป็นบริษัทใหญ่ที่สุดที่ยังใช้ monolith" + ทำกำไรได้

🔥 Case 3: DHH (37signals) — "Beach Once More"

DHH (David Heinemeier Hansson) ผู้สร้าง Ruby on Rails และผู้ก่อตั้ง 37signals (บริษัทที่ทำ Basecamp และ HEY email service) ย้ายออกจาก cloud (AWS) + เลิก microservices → ประหยัด $2M/ปี + ทำงานง่ายขึ้น

📖 "Beach Once More" = ชื่อบทความของ DHH ที่ประกาศย้ายออกจาก cloud — เป็นการเล่นคำภาษาอังกฤษ หมายถึงได้กลับสู่ความเรียบง่าย/ได้พักผ่อนอีกครั้งหลังจากเหนื่อยกับ cloud

🔥 Case 4: Istio's own team

Istio (microservices flagship — ผลิตภัณฑ์หลักที่เป็นตัวแทน microservices!) merge control plane component (Pilot, Citadel, Galley, Sidecar Injector) เข้าเป็น 1 binary (istiod) ในปี 2020 เพื่อลด operational complexity ของการ deploy/upgrade control plane เอง — ไม่ใช่การเปลี่ยนคำแนะนำเรื่อง data-plane architecture สำหรับผู้ใช้งาน แค่ตัว control plane เองก็ยังเจอ cost ของ inter-service call ระหว่างส่วนประกอบภายในสูงเกินไป


"Monolith comeback" บอกอะไร?

  1. Workload ที่มี high-frequency internal call ไม่เหมาะกับ microservices — function call 1ns vs network call 1ms
  2. Cloud cost คิดเป็น opex หลัก (opex = Operating Expenditure = ค่าใช้จ่ายดำเนินงานต่อเนื่อง เช่น cloud bill รายเดือน) — Lambda invocation, cross-AZ, K8s overhead ทบกัน
  3. Modular monolith คือ "default ที่ดีกว่า" สำหรับ team < 100 คน
  4. Microservices ยังเหมาะ เมื่อ: ทีม > 100, scale per-component ต่างกันมาก, regulation บังคับ isolation, polyglot requirement

💡 Sam Newman (2024): "I've been preaching microservices for 10 years. I now spend half my time talking people out of them."

(แปล: "ผมสอน/เผยแพร่ microservices มา 10 ปี — ตอนนี้ครึ่งหนึ่งของเวลา ผมใช้ไปกับการ ห้าม คนใช้มัน")


2.5 ทำไมตอนนี้ (2026) ทำง่ายกว่าเมื่อก่อน

เครื่องมือพร้อมแล้ว (ยังไม่ต้องเข้าใจทุกตัวตอนนี้ — แค่ Docker = ซอฟต์แวร์ห่อแอปให้รันเหมือนกันทุกเครื่อง และ Kubernetes (K8s) = ตัวจัดการรัน container จำนวนมาก คือชื่อที่จะเจอบ่อยที่สุด รายละเอียดอยู่ในบทหลัง):

ปัญหาเครื่องมือที่แก้
รัน 50 service ใน laptopDocker Compose (เครื่องมือรันหลาย container พร้อมกันบนเครื่องเดียว)
Deploy 50 service ใน productionKubernetes
Service หากันยังไงDNS + Service Discovery
Config 50 serviceConfigMap / Spring Cloud Config
Trace request ข้าม serviceOpenTelemetry + Jaeger/Tempo (OpenTelemetry = มาตรฐาน collect log/trace; Jaeger/Tempo = เครื่องมือดู trace)
Async messagingKafka / RabbitMQ
Auth ระหว่าง servicemTLS (เข้ารหัสและยืนยันตัวตนทั้งสองฝ่าย) / OAuth2 / Service Mesh (infra layer จัดการ network ระหว่าง service)
Test ระบบทั้งหมดContract testing (Pact) (ทดสอบว่า service คุยกันตรง spec) , Testcontainers (รัน Docker container จริงในเทส)

ถ้าย้อนกลับไปปี 2010 ที่ Docker ยังไม่มี — microservices = ลำบากมาก ทุกคนต้องเขียน infrastructure เอง


Part 3: 8 Fallacies of Distributed Computing (ของต้องรู้!)

📝 อ่านครั้งแรกแค่ scan หัวข้อก่อน — Part 3 มีบางส่วนอ้างเทคนิคเช่น timeout, retry, circuit breaker, mTLS ที่จะเรียนในบทหลัง ตอนนี้แค่รู้ชื่อก็พอ — รายละเอียดทั้งหมดจะตามมาเอง เป้าหมายตอนนี้คือเข้าใจว่า "มีกับดักอะไรรอเราอยู่" 8 ข้อ

ถ้าคุณจะข้ามจาก monolith → microservices คุณกำลังเปลี่ยนจาก "ทุก function call เร็วและเชื่อถือได้" → "ทุก function call ผ่าน network ที่อาจล้มได้"

ในปี 1994 Peter Deutsch ที่ Sun Microsystems เขียนรายการ "ความเข้าใจผิดที่ทุก dev ตกในระบบกระจาย" — เรียกว่า 8 Fallacies of Distributed Computing (fallacy = ความเชื่อผิด ๆ; ศัพท์จากวิชาตรรกศาสตร์/ปรัชญา)

ทั้ง 8 ข้อ ผิดทั้งหมด แต่ dev มือใหม่จะสมมติว่าจริงโดยไม่รู้ตัว:

Fallacy 1: "The network is reliable" (network ใช้ได้เสมอ)

❌ ความเข้าใจผิด: "เขียน code call service → ถึง 100%"

ความจริง: Network ล่มตลอดเวลา ในระดับเล็ก

  • Packet loss 0.1-1% เป็น baseline ของ data center
  • TCP connection reset ระหว่าง pod restart
  • DNS resolution fail ชั่วคราว
  • Cloud provider เปลี่ยน routing → traffic drop ชั่วครู่
  • Switch / cable / NIC ตาย

🔥 Real incident: AWS US-EAST-1 (Nov 2020) — Kinesis ในภูมิภาคล่ม 17 ชั่วโมง เพราะ server เพิ่ม capacity แล้ว front-end fleet ติดต่อ back-end fleet ไม่ได้ — fallacy นี้ตรง ๆ. Service ทั่ว AWS (Cognito, EventBridge, CloudWatch) ล่มตาม

✅ ต้องทำ — รายการนี้บอกชื่อวิธีแก้ไว้ก่อน แต่ยังไม่ต้องเข้าใจลึกตอนนี้ (จะสอนละเอียดในบทที่อ้างถึง):

  • Timeout บังคับ ทุก network call (connection + read + overall — บท 03 Part 2)
  • Retry with exponential backoff + jitter (= ลองใหม่แบบเว้นช่วงถี่ขึ้นเรื่อย ๆ + สุ่มเวลานิดหน่อยกันชนกัน — บท 03 Part 3)
  • Circuit breaker เปิดเมื่อ fail rate สูง (= ฟิวส์ตัดไฟ กันระบบล้มเป็นโดมิโน — รายละเอียดบท 13)
  • Idempotent operation — retry ได้โดยไม่ duplicate (idempotent = ทำซ้ำได้ผลเหมือนเดิม — ดู Glossary Part 10)
  • ไม่สมมติ "เห็น response = สำเร็จ"

Fallacy 2: "Latency is zero" (เรียก service อื่นไม่เสียเวลา)

❌ ความเข้าใจผิด: "call function = call service = เร็วเหมือนกัน"

ความจริง (latency ladder ที่ต้องจำ):

OperationTimeเทียบเป็นชีวิตจริง
L1 cache hit1 nsชั่วพริบตา
RAM access100 nsแค่กระดิกนิ้ว
SSD read100 μsไปกินกาแฟ
Network: same DC (same-AZ pod-to-pod 100μs-1ms, cross-AZ 500μs-3ms ใน modern K8s)500 μs - 2 msบินไปกินกาแฟ
Network: same region5-30 msกลับไปบ้าน
Network: cross-region50-200 msบินข้ามทวีป

📖 L1 cache = หน่วยความจำใน CPU ที่เร็วที่สุด — เร็วกว่า RAM ราว 100 เท่า, ขนาดเล็ก (~32-64 KB ต่อ core)

📖 AZ (Availability Zone) = โซนศูนย์ข้อมูลแยกกันทางกายภาพใน cloud (แต่ละ region มีหลาย AZ), pod = หน่วยรันเล็กที่สุดของ container ใน K8s, K8s = ตัวย่อของ Kubernetes — รายละเอียดเต็มอยู่บทหลัง ตอนนี้แค่รู้ว่ายิ่งข้าม AZ/region ยิ่งช้า

ตัวอย่างคำนวณ:

  • Monolith: 1 user request → 1 function call (~1 ms total)
  • Microservices: 1 request → A → B → C → D → DB (5 hops × 5ms = 25 ms minimum, ก่อนรวม processing)
  • ถ้าทำ 5 sync call ใน parallel (BFF pattern — Backend For Frontend, gateway เฉพาะของ client แต่ละชนิด — อธิบายเต็มบท 04) — total = max ของแต่ละ call

🔥 Real incident: Amazon Prime Video (May 2023) — ทีมย่อยที่ทำ video frame analysis พบว่า microservices (sync call ทุก frame ระหว่าง service) ทำ latency × cost พุ่ง → migrate กลับเป็น monolith ลด cost ของเครื่องมือนั้นลง 90% (ไม่ใช่ทั้งแพลตฟอร์ม Prime Video). Network call ที่ "ดูเหมือนถูก" ทบกันเป็นต้นทุนหลัก

✅ ต้องทำ:

  • ออกแบบ call graph ตื้น — fan-out parallel ดีกว่า chain serial
  • Async ที่ทำได้ (บท 02) — caller ไม่รอ
  • Cache aggressively — Redis/local cache ลด round-trip
  • Co-locate hot services — service ที่คุยกันบ่อยอยู่ same AZ
  • Batch calls — 1 call ดึง 100 records ดีกว่า 100 calls

Fallacy 3: "Bandwidth is infinite" (ส่งของขนาดไหนก็ได้)

❌ ความเข้าใจผิด: "JSON 1MB ส่งไม่กี่ ms ก็ถึง"

ความจริง:

  • DC internal bandwidth: 1-10 Gbps shared ระหว่าง pod
  • VM แต่ละขนาดมี limit (t3.medium = 5 Gbps burst, ค่า sustain ต่ำกว่า)
  • TCP slow start (กลไกที่ TCP เริ่มส่งข้อมูลช้า ๆ แล้วค่อย ๆ เร็วขึ้น — ทำให้ connection ใหม่ทุกครั้งมี latency สูงกว่า connection เดิม) — connection ใหม่ต้องค่อย ๆ เร่ง throughput
  • ส่ง 100MB × 1000 req/s = 100 GB/s — เกินขีดของ network แน่นอน

🔥 Real incident: Twitter (2010s) — internal service ส่ง full user profile ทุก call (รวม friends list 10MB+) → bandwidth ระเบิด ตอน trend ดัง. แก้: ส่งแค่ user_id, ดึง profile lazy

✅ ต้องทำ:

  • Paginationlimit + cursor ทุก list endpoint
  • GraphQL / sparse fieldsets — client ขอเฉพาะ field ที่ต้องใช้
  • Compression — gzip/zstd ที่ HTTP layer, Protobuf binary ที่ message
  • Streaming สำหรับ large payload (gRPC streaming, chunked HTTP)
  • อย่า embed file — เก็บ S3 ส่งแค่ URL
  • ตั้ง max request/response size ป้องกัน abuse

Fallacy 4: "The network is secure" (network ภายในปลอดภัย)

❌ ความเข้าใจผิด: "service ภายใน VPC คุยกันโดยไม่ต้อง encrypt"

📦 ศัพท์เสริม (มือใหม่ข้ามได้ ค่อยกลับมาดูทีหลัง) — ต้องรู้ก่อนอ่านย่อหน้าถัดไป:

  • VPC (Virtual Private Cloud) = วงเครือข่ายส่วนตัวของเราบน cloud
  • SSRF (Server-Side Request Forgery) = ช่องโหว่ที่หลอกให้ server เราไป "ยิง request" ไปยังที่ที่ผู้โจมตีต้องการ
  • supply chain (attack) = การโจมตีผ่าน "ห่วงโซ่ซอฟต์แวร์" คือฝังโค้ดร้ายในไลบรารีที่คนอื่นเอาไปใช้ต่อ
  • IAM (Identity and Access Management) = ระบบจัดการสิทธิ์/ตัวตน บน cloud ว่าใครทำอะไรได้บ้าง
  • EC2 metadata = ข้อมูลลับประจำเครื่อง server ของ AWS (EC2 = เครื่อง server เสมือนของ AWS) ที่เข้าถึงได้จากในเครื่อง — ถ้ารั่ว = ขโมยสิทธิ์ได้

ความจริง: "Perimeter security" เป็นความคิดเก่า — เมื่อ attacker เข้ามาใน VPC ได้ (compromised credentials, SSRF, supply chain) ทุก internal service ถูกเปิด

🔥 Real incident: Capital One (2019) — SSRF + IAM misconfig ทำ attacker เข้า EC2 metadata → get IAM role → access S3 → leak 100M customer records + $80M fine. ปัญหา: internal services trust "request จาก VPC"

🏢 เปรียบเทียบให้เห็นภาพ: การโจมตี Capital One เหมือนโจรเข้ามาในตึก (VPC) ได้แล้ว เดินทะลุทุกชั้นได้สบายเพราะภายในตึกไม่มี security (ทุกชั้นเชื่อใจกัน) → Zero Trust = ทุกประตูในตึกต้องสแกนบัตรเสมอ แม้คุณอยู่ในตึกแล้ว

🔥 Real incident: xz utils backdoor (Mar 2024) — supply chain attack ใส่ backdoor (ประตูหลังลับไว้แอบเข้าระบบ) ใน Linux ecosystem 2 ปี เกือบสำเร็จ — เตือนว่า "ภายใน" ก็ไม่ปลอดภัย

📖 คำในลิสต์ด้านล่างนี้เป็นชื่อเทคนิคที่จะสอนละเอียดบทหลัง (mTLS/Istio บท 16-17, JWT บท 16) — ตอนนี้แค่รู้ว่ามีวิธีแก้อยู่ก็พอ: mTLS = การเข้ารหัส+ยืนยันตัวตนทั้งสองฝั่ง, Istio/Linkerd = เครื่องมือ service mesh ที่จัดการ mTLS ให้อัตโนมัติ, JWT (JSON Web Token) = โทเคนยืนยันตัวตนที่หมดอายุได้

✅ ต้องทำ (Zero Trust principle — บท 16):

  • mTLS ระหว่างทุก service (auto-managed ด้วย Istio/Linkerd)
  • Network policy ใน K8s — service A คุย B ได้เท่านั้น
  • Short-lived credentialsJWT 5-15 นาที + refresh, ไม่ใช่ token ตลอดกาล
  • Authorization ทุก call — แม้ภายใน
  • Audit log ทั้งหมด — ใครคุยกับใครเมื่อไหร่

Fallacy 5: "Topology doesn't change" (service IP ไม่เปลี่ยน)

❌ ความเข้าใจผิด: "deploy แล้ว IP ของ service B = 10.0.5.42"

ความจริง:

  • K8s pod restart → IP ใหม่ทุกครั้ง
  • Autoscale → instance เกิด/ตายตลอด
  • Spot instance / preemptible → cloud คืน server ได้ทุกเมื่อ
  • AZ failover → ทั้ง subnet เปลี่ยน

🔥 Real incident: Netflix (pre-Eureka, 2012) — service A hardcode IP ของ service B. EC2 instance ของ B replace → A ทั้งฝูง call IP ตายเป็นชั่วโมง → cascading failure → ทำให้ Netflix ลงทุนสร้าง Eureka เป็น service discovery

🔥 Real incident: บริษัท health tech (2022) — hardcoded service hostname ใน multi-cluster deploy → switch cluster แล้ว app เก่ายัง call cluster เก่า → 4 ชม. outage

✅ ต้องทำ:

  • Service Discovery — K8s DNS, Consul, Eureka (บท 05)
  • Logical name เสมอ: payment-service.svc.cluster.local ไม่ใช่ IP
  • Health check + load balancer — drop instance ตายอัตโนมัติ
  • DNS TTL ต่ำ (30s-1min) สำหรับ internal service
  • Retry with new connection — connection pool refresh

Fallacy 6: "There is one administrator" (มีคนเดียวคุมทุกอย่าง)

❌ ความเข้าใจผิด: "ทีม DevOps ดูได้ทุก service เหมือน monolith"

ความจริง: Microservices = หลายทีมเป็นเจ้าของแต่ละ service. แต่ละทีมตั้ง config, deploy, monitor แยกกัน → drift จาก standard

🔥 Real incident: Stripe (2022) — gateway misconfig ใน team หนึ่ง ทำ data leak ระหว่าง customer (อ่านรายละเอียดได้ทีหลัง — ตอนนี้แค่รู้ว่า misconfig ทำให้ข้อมูลรั่วข้ามผู้ใช้). คนตั้ง config ผิด → ไม่มี policy บังคับ → leak

🔥 Real incident: GitLab (2017) — backup ถูก disable ใน production โดยไม่มีใครรู้ → ตอน DB delete accidentally — backup ไม่มี → สูญข้อมูล 6 ชม.

✅ ต้องทำ:

  • Centralized config — Spring Cloud Config / Consul KV (บท 05)
  • Policy as code — OPA, Kyverno bind ใน CI/CD + admission webhook
  • Internal Developer Platform (IDP) — Backstage, Humanitec — ลด surface ที่ทีมต้องตั้งเอง
  • GitOps — production = git repo (บท 18) → audit trail + rollback
  • Standardized observability — บังคับทุก service expose metric/trace ตาม convention เดียวกัน

Fallacy 7: "Transport cost is zero" (ส่งข้อมูลไม่เสียเงิน)

❌ ความเข้าใจผิด: "service คุยกันภายใน cloud ฟรี"

ความจริง (AWS pricing baseline 2026):

  • Same AZ: $0 (ฟรี) — แต่ระวัง: NAT Gateway traffic แม้ภายใน AWS account คิด $0.045/GB. บาง AWS service เริ่มยกเว้นค่า cross-AZ data transfer ในบางกรณี (เช่น ECR pull) — ตรวจ current pricing ที่หน้า pricing ของ AWS เสมอ เพราะเงื่อนไขเปลี่ยนบ่อย
  • Cross-AZ: $0.01-0.02/GB (ทั้ง 2 ทาง — แพง!)
  • Cross-region: $0.02-0.09/GB
  • Egress to internet: $0.05-0.12/GB

→ Service A (AZ-a) คุย Service B (AZ-b) 1 TB/วัน = $300-600/เดือน ต่อ pair. มี 100 service pair = $30-60K/เดือนแค่ data transfer

🔥 Real incident: Twitter (pre-2020) — เสีย ~$100M/yr กับ cross-AZ traffic ก่อน optimize. Service ไม่ได้ aware ว่าตัวเองอยู่ AZ ไหน → คุยข้าม AZ ไปมาเรื่อย ๆ

🔥 Real incident: บริษัท SaaS (2024) — log shipping ข้าม region (US-EAST → US-WEST) ทุก 5 วินาที × 50 service = bill $20K/เดือนเฉพาะ data transfer

✅ ต้องทำ:

  • AZ-aware routing — service หาคู่ใน AZ เดียวกันก่อน (K8s topology-aware hint, Istio locality routing)
  • Compress data ระหว่าง service (gzip, Snappy, zstd)
  • Co-locate workloads — service ที่คุยกันบ่อยอยู่ AZ เดียวกัน
  • Aggregate before transfer — batch log/metric ก่อน ship cross-region
  • Cache ลด transfer ซ้ำซ้อน
  • Monitor data transfer cost เป็น metric หลัก (FinOps)

Fallacy 8: "The network is homogeneous" (network เหมือนกันทุกที่)

❌ ความเข้าใจผิด: "เขียน HTTP client ทดสอบ local ผ่าน = production ผ่าน"

ความจริง: Network ใน production ผสมหลายอย่าง

  • Service A ใน K8s (Linux + iptables + CNI)
  • Service B บน VM (Linux/Windows different MTU)
  • Service C บน Lambda (firecracker microVM)
  • Service D บน serverless DB (PrivateLink)
  • ทุกระดับมี MTU, timeout, idle disconnect, keep-alive ต่างกัน

📦 ศัพท์เสริม (ข้ามได้):

  • MTU (Maximum Transmission Unit) = ขนาดสูงสุดของ "ก้อนข้อมูล" ที่ส่งผ่าน network ได้ในครั้งเดียว — ถ้าตั้งไม่ตรงกันสองฝั่ง ข้อมูลใหญ่จะมีปัญหา
  • microVM = เครื่องเสมือนจิ๋ว (Firecracker คือ engine ที่ AWS Lambda ใช้รันโค้ดเรา) เบาและเปิดเร็วกว่า VM ปกติ
  • idle disconnect = การที่ network ตัดการเชื่อมต่อทิ้งเมื่อ "เงียบ" ไม่มีข้อมูลวิ่งนานเกินกำหนด
  • keep-alive = การส่งสัญญาณเล็ก ๆ เป็นระยะเพื่อ "บอกว่ายังอยู่" กันโดนตัด

🔥 Real incident: Slack (2021) — Slack ใช้ gRPC bidirectional streaming (bidi-streaming — ส่งข้อมูลสองทางพร้อมกันในการเชื่อมต่อเดียว) ผ่าน ALB (Application Load Balancer — ตัวกระจาย traffic ของ AWS ชนิดหนึ่ง) บน K8s. ALB มีค่า default ตัดการเชื่อมต่อที่ "ว่างงาน" (idle connection) ทิ้งที่ 60 วินาที แต่ gRPC stream ของ Slack ถือ connection ไว้นานกว่านั้น → โดนตัดกลางทาง → เกิด reconnect storm (ทุก client พยายามเชื่อมต่อใหม่พร้อมกันเป็นจำนวนมาก จนระบบรับไม่ไหวซ้ำ) → ล่ม 3 ชม.

🛠 Mitigation ปี 2026: สำหรับ gRPC bidi streaming ใช้ NLB (Network Load Balancer — HTTP/2 native + timeout ยาวกว่า) แทน ALB, หรือเพิ่ม ALB idle timeout เป็น 4000s + ตั้ง gRPC keepalive 30s

🔥 Real incident: บริษัท fintech (2024) — Go consumer ใช้ Kafka client version เก่า — ไม่ support KIP-848 protocol ของ Kafka 4.0 → rebalance ไม่ทำงานข้าม version → silent message stuck

📦 ศัพท์เสริม (ข้ามได้ เดี๋ยวลงลึกบท 08 Kafka):

  • KIP (Kafka Improvement Proposal) = เอกสารข้อเสนอปรับปรุง Kafka แต่ละข้อมีเลขกำกับ (เช่น KIP-848 = ข้อเสนอเปลี่ยนวิธี rebalance)
  • rebalance = การที่ Kafka จัดสรร "งาน" (partition) ใหม่ให้ consumer แต่ละตัวเมื่อมีตัวเข้า/ออกกลุ่ม
  • silent message stuck = message ค้างเงียบ ๆ ไม่ถูกประมวลผล โดยไม่มี error ฟ้อง (อันตรายเพราะหาไม่เจอ)

✅ ต้องทำ:

  • ทดสอบใน production-like environment — ใช้ Testcontainers + chaos testing
  • Standardize protocol — ใช้ HTTP/2 หรือ gRPC version เดียวกันทั่วบริษัท
  • Keep-alive + ping — กัน idle disconnect (gRPC keepalive 30s)
  • Configurable timeouts — ไม่ใช่ hardcode
  • Contract testing (Pact) — verify protocol ระหว่าง service version
  • Avoid protocol-specific features ที่ infra ไม่รองรับ (เช่น HTTP/2 push, Server-Sent Events ผ่าน proxy เก่า)

🎯 สรุป: ทั้ง 8 fallacies คือ "สมมุติของ monolith ที่ใช้กับ microservices ไม่ได้"

Fallacyสมมุติ monolithความจริง microservices
1. Reliablefunction ไม่ thrownetwork throw ตลอด
2. Latency=0function call เร็ว1-200 ms ต่อ hop
3. Bandwidth=∞memory copy ฟรีlimited Gbps
4. Secureprocess เดียว trust ตัวเองVPC ไม่ปลอดภัย
5. Topology staticobject reference เดียวIP เปลี่ยนตลอด
6. One admindev คนเดียวรู้ทั้ง appหลายทีม config drift
7. Transport freememory copy ไม่เสียเงิน$0.01/GB cross-AZ
8. Homogeneous1 JVM 1 OSผสม K8s/VM/Lambda

💡 กฎทอง: ก่อนเขียน network call ใหม่ — ถามตัวเอง 8 ข้อนี้. ถ้าตอบไม่ได้แต่ละ fallacy = code นั้นจะมีปัญหาใน production

🛠️ Checkpoint 3.1 — ปิดหน้าจอ ลองตอบ:

💡 ถ้ายังไม่เข้าใจ ตอบเดา ๆ ได้ — จุดประสงค์คือทำให้เห็นว่ามีปัญหาอะไรรออยู่ ไม่ใช่ทดสอบความรู้

  1. ถ้า service A เรียก service B แล้ว B timeout — คุณทำอะไร?
  2. ลองนึกภาพต้องทำ 2 อย่างพร้อมกัน: บันทึก order ลง database และส่งข้อความแจ้ง warehouse ใน monolith คุณมั่นใจว่า save DB สำเร็จเพราะ return ไม่ throw — ใน microservices ถ้าส่ง message สำเร็จ แต่ DB save fail (network issue ตอน commit) ระบบจะ "consistent" ไหม? (ตอบคร่าว ๆ พอ — ปัญหา "เขียน 2 ที่ไม่พร้อมกัน" นี้เรียกว่า dual-write problem เดี๋ยวลงลึกบท 06 และ 12 เรื่อง Outbox pattern)
  3. ทำไมต้องใช้ correlation ID? (correlation ID = รหัสติดตามที่แปะไปกับ request เพื่อตามรอยข้าม service — ลงลึกบท 15)

ถ้าตอบไม่ได้ → อ่าน Part 3 ซ้ำ. อันนี้เป็นรากฐานของทั้งเล่ม


Part 4: เมื่อไหร่ "ควร" ใช้ Microservices

4.1 เกณฑ์ที่บอกว่า "พร้อม"

ใช้ checklist นี้ — ถ้าตอบ "ใช่" ส่วนใหญ่ → microservices น่าจะคุ้ม

✅ ปัจจัยด้านองค์กร

  • [ ] มี ทีมมากกว่า 1 ทีม (อย่างน้อย 2-3 ทีม) ที่ทำงานบน app เดียวกัน
  • [ ] ทีมเริ่ม block กันเอง — รอ merge, รอ deploy window
  • [ ] ทีมต้อง release ความเร็วต่างกัน (ทีม mobile deploy ทุกวัน, ทีม core เดือนละครั้ง)
  • [ ] บริษัทยินดี ลงทุน DevOps/Platform team (Kubernetes, observability ฯลฯ)
  • [ ] มี on-call culture — ทีมที่เขียน service จะ on-call ของ service ตัวเอง

✅ ปัจจัยด้านเทคนิค

  • [ ] มี CI/CD ที่ดี — deploy ปุ่มเดียว, rollback อัตโนมัติ
  • [ ] มี observability — log/metric/trace centralized
  • [ ] มี container/Kubernetes หรืออย่างน้อย container orchestration
  • [ ] เข้าใจ distributed tracing
  • [ ] รู้จัก message broker (Kafka/RabbitMQ)

✅ ปัจจัยด้าน workload

  • [ ] บาง component scale ต่างกันมาก (search ต้องการ 100 CPU, profile แค่ 2 CPU)
  • [ ] บาง component เปลี่ยนบ่อย (recommendation algorithm), อีกบาง component stable มาก (auth)
  • [ ] อยากใช้ tech stack ต่าง ในบาง component (ML ใช้ Python, real-time ใช้ Go, business logic ใช้ Java)

4.2 เกณฑ์ที่บอกว่า "ยังไม่พร้อม"

🚫 อย่าเพิ่งทำ microservices ถ้า...

  • [ ] ทีมเล็ก (1-5 คน)
  • [ ] App ยังเล็ก / ยังไม่มี user
  • [ ] ยังไม่มี CI/CD
  • [ ] ยังไม่มี monitoring
  • [ ] ยังไม่เคยใช้ container
  • [ ] ยังไม่เข้าใจ domain ที่ทำ (เพิ่งเริ่ม startup, requirement ยัง pivot บ่อย)
  • [ ] อยากใช้ microservices เพราะ resume-driven development (การพัฒนาแบบเอาไปใส่เรซูเม่ — "ฉันอยากเขียนใน CV ว่าเคยทำ")

4.3 หลักการ "Monolith First" ของ Martin Fowler

"Almost all the successful microservice stories have started with a monolith that got too big and was broken up."

"Almost all the cases where I've heard of a system that was built as a microservice system from scratch, it has ended up in serious trouble."

— Martin Fowler

แปล: เคสที่ microservices สำเร็จ — ส่วนใหญ่ เริ่มจาก monolith แล้วโตจนต้องแตก
เคสที่เริ่ม microservices ตั้งแต่ day 1 — มักจะเจ๊ง

ทำไม?

  1. ไม่รู้ domain ดีพอ — เริ่ม startup คุณไม่รู้ business model จะเป็นยังไง. ตัด service ผิดแล้ว refactor ข้าม service ยากมาก
  2. Over-engineering — startup ที่มี 1,000 user แต่มี 30 service = scale มากเกินไป, จ่ายค่า ops มากเกินไป
  3. Decomposition ที่ถูก = ต้องเห็น pattern ก่อน — pattern จะออกมาตอนคุณรัน monolith ไป 6 เดือน-2 ปี

เริ่มจาก modular monolith เสมอ ถ้าไม่ใช่ Netflix รุ่น 2026 ที่รู้ domain ดี


Part 5: Cost / Benefit Reality Check

5.1 ต้นทุนที่มือใหม่ลืม

มือใหม่มัก list benefit ของ microservices ได้คล่อง แต่ลืม cost. ลองดู:

📖 replica = สำเนาของ service ที่รันคู่ขนานกัน (รันซ้ำเพื่อรองรับโหลด/กันล่ม), pod = หน่วยรันของ container ใน Kubernetes 1 หน่วย

ต้นทุนทางตรง (จ่ายเงิน)

ต้นทุนจำนวน (โดยประมาณ)
Cloud infrastructure (50 service × 3 replica = 150 pod)[^scale]$5K-30K/month

[^scale]: ตัวเลขนี้สำหรับ ~30-50 service ขนาดกลาง (เช่น mid-size startup/scale-up) — startup เริ่มต้น (5-10 service, 1 replica) อาจอยู่ที่ $500-2K/month, enterprise scale (200+ service) อาจ $100K+/month | Kafka cluster (3 broker + ZK/KRaft) | $1K-5K/month | | Monitoring (Datadog/New Relic) | $1K-10K/month | | Service mesh (Istio control plane) | $500-2K/month | | Container registry, secrets mgmt | $100-500/month | | Developer tooling | $1K-5K/month |

จุดเริ่ม: ก่อนรับ user คนแรกอาจเสีย $10-50K/month แค่ infrastructure

ต้นทุนทาง engineering

ต้นทุนความหมาย
Platform teamต้องมีทีมดูแล K8s, broker, observability — 2-5 คน
Cognitive loaddev ต้องรู้ network, retry, idempotency, eventual consistency
Debug timeจาก stack trace เดียว → ต้องดู 5 service log + trace
Test timeunit test ของ service A ไม่พอ — ต้องมี contract test, integration test
Onboarding timeคนใหม่เข้ามาต้องใช้เวลานานกว่า monolith

ต้นทุนที่จับต้องไม่ได้

  • Eventual consistency — user เห็นข้อมูลเก่าบางครั้ง (เพราะ replication lag, async update)
  • Distributed transaction — ไม่มี ACID อีกแล้ว (ACID = คุณสมบัติของ transaction ใน DB เดียวที่รับประกันว่างานสำเร็จครบหรือย้อนกลับทั้งหมด ไม่ทำครึ่ง ๆ กลาง ๆ). ข้าม service ต้องใช้ Saga pattern แทน
  • Versioning hell — ตอน upgrade ต้องดูว่า service ไหน expect API v1, v2
  • Production incident ซับซ้อนกว่า — root cause อยู่ไหนยังไม่รู้

5.2 ROI Equation

ลองคิดเป็นสมการ:

text
Net Benefit = Speed Gain × Team Count
            - Infra Cost
            - Cognitive Cost × Team Count
            - Reliability Cost (incident time)

→ Microservices คุ้ม เมื่อ:

  • Team count สูง (5+ ทีม)
  • Speed gain ต่อทีมสูง (release ที่เคยเดือนละครั้ง → วันละครั้ง)
  • มีทรัพยากรพอจ่าย infra + platform team

ไม่คุ้ม เมื่อ:

  • ทีมเดียว, app เล็ก, จ่าย infra ไม่ไหว

💡 ตัวเลขโดยประมาณ (จากประสบการณ์ของหลายบริษัท):

  • ต่ำกว่า ~10 dev → monolith ดีกว่า
  • 10-30 dev → modular monolith
  • 30-100 dev → เริ่มพิจารณา microservices บางส่วน
  • 100+ dev → microservices ค่อย ๆ ขยาย

Part 6: Anti-patterns (กับดักที่คนใหม่ตก)

6.1 Distributed Monolith — ตัด service แต่ยังพันกัน

อาการ:

  • แก้ service A → ต้อง deploy service B, C, D ตามด้วย
  • Share database 1 ตัวระหว่างหลาย service
  • Service A เรียก B sync, B เรียก C sync, C เรียก D sync (call chain ยาว)
  • Release ต้อง coordinate timing

= ได้ความซับซ้อนของ microservices + ความเปราะของ monolith = worst of both worlds

วิธีแก้: หยุดสร้าง service เพิ่ม → กลับไปดู bounded context, แก้ coupling ก่อน

6.2 Nano-services — ตัดเล็กเกินไป

อาการ:

  • มี service add-numbers-service ที่บวกเลข 2 ตัวคืน
  • 1 user request วิ่งข้าม 20 service
  • ใช้ memory + CPU ของ overhead (each service มี JVM/runtime) มากกว่า business logic

วิธีแก้: รวม nano-service ที่ใกล้ domain เดียวกันกลับเป็น 1 service

6.3 Shared Database

อาการ: 5 service เขียน table เดียวกัน

ปัญหา: เปลี่ยน schema 1 column = ต้องเปลี่ยนทุก service ใช้ table นั้น (= ไม่ใช่ independently releasable แล้ว)

วิธีแก้: 1 service owns 1 set of tables. ถ้าต้องอ่านข้าม service → ใช้ API หรือ event

6.4 Synchronous Everything

อาการ: ทุก inter-service communication ใช้ REST sync

ปัญหา: latency ทบกัน, ถ้า downstream ล่ม upstream ล่มตาม

วิธีแก้: ใช้ async (event) เมื่อทำได้, ใช้ sync เมื่อจำเป็น

6.5 Premature Decomposition

อาการ: ตั้ง startup ใหม่ → ตั้งใจมีตั้งแต่วันแรก 15 service

ปัญหา: ตอน pivot ต้อง refactor ข้าม service หลายตัว

วิธีแก้: เริ่มจาก modular monolith → แตกเมื่อเห็น pain point ชัดเจน

6.6 Sharing Code Across Services

อาการ: มี library common-models ที่ทุก service depend

ปัญหา: เปลี่ยน 1 line = ทุก service ต้อง upgrade

วิธีแก้: ให้ service ทำซ้ำ (duplicate) บางส่วน — duplication ดีกว่า coupling. ถ้าต้อง share จริง ๆ ให้ version semver และ deprecate ค่อย ๆ ทำ

6.7 Ignoring Data Ownership

อาการ: ไม่ชัดเจนว่า "user data" อยู่ที่ service ไหน — auth, profile, account ต่างก็มี

ปัญหา: ข้อมูลไม่ตรงกัน, ใครเป็น source of truth?

วิธีแก้: กำหนดชัดเจน 1 piece of data = 1 service owns. service อื่นเก็บ "copy" ที่อาจ stale ได้

6.8 "Cargo Cult" — เลียนแบบ Big Tech โดยไม่เข้าใจบริบท

อาการ:

  • ทีม 5 คน อ่าน Netflix engineering blog → ทำ chaos engineering (จงใจทำให้ระบบพังบางส่วนเพื่อทดสอบความทนทาน) + service mesh + 30 microservices
  • "Spotify ใช้ Squad model → เราก็ต้องใช้"
  • "Uber มี 4000 service → ของเราต้องมีหลายร้อย"

ปัญหา: Netflix/Uber/Spotify มี:

  • 1000+ engineer
  • Platform team 50+ คน
  • งบ infra หลัก $100M/ปี
  • Domain ที่ scale ขนาดมหึมา

คุณมี 5 คน + งบ $10K/เดือน → architecture เดียวกันจะตายแน่

วิธีแก้: ถามตัวเองทุกครั้งที่ copy idea จาก big tech: "ฉันมี constraint เดียวกับเขาไหม? scale เท่ากันไหม?"

6.9 No Observability

อาการ: deploy 50 service โดยไม่มี log centralized / metric / trace

ปัญหา: bug ใน production = ตามไม่ได้

วิธีแก้: observability ต้องมาก่อน microservices — ดูบท 15 และหมวด observability/


Part 7: เส้นทางย้ายจาก Monolith → Microservices

7.1 Strangler Fig Pattern

ตั้งชื่อตามต้นไม้ "ไทรเลือก" ที่ค่อย ๆ พันต้นไม้เดิมจน feeder ตายไป

ข้อดี: ทำขนาน production ได้ — ไม่ต้องหยุด business

7.2 ลำดับการตัด (priority)

ตัด feature ตามลำดับนี้ (ส่วนใหญ่):

  1. เริ่มจาก leaf — feature ที่ไม่มีใครพึ่ง (เช่น report, analytics, notification)
  2. Feature ที่ scale ต่างจากอื่น — search, real-time chat
  3. Feature ที่ team ใหม่จะ own — เริ่มจากตรงนี้ให้ team ใหม่ทดลอง
  4. Feature ที่ tech stack ต่าง — ML, image processing
  5. Core domain — สุดท้ายเสมอ (เพราะเปลี่ยนยากที่สุด)

7.3 Database Decomposition Order

อย่ากระโดดข้าม! Stage 2 = ปลอดภัย / ทดลอง pattern โดยไม่เสีย transaction guarantee ของ DB เดียว


Part 8: Mental Model สำหรับ Decision Making

8.1 Framework: 5 คำถามก่อนสร้าง service ใหม่

ก่อนคิดจะแตก service ใหม่ ถามตัวเอง:

  1. มี bounded context ของตัวเองชัดเจนไหม? — ถ้าตอบไม่ได้ว่าเป็น domain อะไร = ยังไม่ตัด
  2. มีทีมที่จะดูแล on-call ของ service นี้ตลอด life cycle ไหม? — ถ้าไม่มี = ยังไม่ตัด
  3. ตอนนี้มันก่อปัญหาที่ monolith ทำให้ช้า / scale ไม่ได้ / deploy ไม่ได้จริง ๆ ไหม? — ถ้าไม่ = อาจไม่จำเป็น
  4. ถ้าตัดแล้ว ภายใน 3 เดือนเราต้องเพิ่ม / แก้ feature ในนี้ไหม? — ถ้าใช่ = อาจรอ requirement stable ก่อน
  5. เราพร้อมรับ eventual consistency ที่ตามมาไหม? — ถ้ายังไม่เข้าใจคำนี้ = ยังไม่พร้อม

ตอบ "ใช่" ครบ 5 ข้อ → พอจะตัด

8.2 Decision Tree

🗺️ Flowchart ตอบคำถาม "ใช้ microservices ไหม?" — ตามลูกศรจากบนลงล่าง

ถ้า diagram ไม่ render — สรุปเป็นข้อความ:

  • เริ่ม project ใหม่ → Monolith first (เริ่มจาก monolith เสมอ)
  • มี monolith อยู่แล้ว → ถามต่อ "มีปัญหา scale / team / deploy จริง ๆ ไหม?"
    • ไม่มี → ปรับปรุง monolith ก่อน (ยังไม่ต้องตัด)
    • มี → ถามต่อ "ทีม + tooling (CI/CD, observability, K8s) พร้อมไหม?"
      • พร้อม → Strangler Pattern + DDD (ค่อย ๆ ตัดทีละ feature)
      • ไม่พร้อม → ลงทุนใน CI/CD, observability, K8s ก่อน

Part 9: ภาพรวมของ Tech Stack ที่จะเจอใน Microservices

นี่คือ landscape คร่าว ๆ — ทุกหัวข้อจะเจาะลึกในบทต่อ ๆ ไป

9.1 Communication

เริ่มจากการสื่อสารระหว่าง service — แบ่งเป็น synchronous (รอตอบกลับทันที เช่น REST, gRPC) และ asynchronous (ส่งแล้วไม่รอ ผ่าน message broker เช่น Kafka, RabbitMQ) นี่คือรายการเครื่องมือยอดนิยมของแต่ละแบบ:

text
Synchronous (request/response):
  - REST + JSON       (most common, easy)
  - gRPC + Protobuf   (binary, fast, contract-first)
  - GraphQL           (flexible query, BFF use)

Asynchronous (fire & forget / event):
  - Kafka             (event log, high throughput, replay)
  - RabbitMQ          (queue + routing, task)
  - NATS / JetStream  (lightweight, cloud-native)
  - Redis Streams     (เบา + ใช้ Redis ที่มีอยู่)
  - Pulsar            (multi-tenant, geo-replication)
  - AWS SQS/SNS, GCP Pub/Sub  (managed)

9.2 Infrastructure

ระบบ microservices ต้องการโครงสร้างพื้นฐานรองรับ — container (Docker), orchestration (Kubernetes), service mesh, API gateway, service discovery, config และ secret management นี่คือเครื่องมือมาตรฐานของแต่ละชั้น:

text
Container:          Docker
Orchestration:      Kubernetes (+ Helm, Argo CD)
Service Mesh:       Istio, Linkerd
API Gateway:        Kong, Spring Cloud Gateway, Envoy
Discovery:          Eureka, Consul, etcd, K8s DNS
Config:             Spring Cloud Config, Consul KV, K8s ConfigMap
Secret:             Vault, Sealed Secrets, KMS

9.3 Resilience + Observability

ในระบบกระจาย service ล่มเป็นเรื่องปกติ จึงต้องมีเครื่องมือด้าน resilience (circuit breaker, retry) และ observability (tracing, metrics, logs) เพื่อให้ระบบทนทานและมองเห็นปัญหาได้:

text
Resilience:         Resilience4j (Java), Hystrix (legacy), gobreaker (Go)
Tracing:            OpenTelemetry → Jaeger / Tempo
Metrics:            Prometheus + Grafana
Logs:               Loki / ELK / Datadog
APM:                Datadog, New Relic, Elastic APM

9.4 Data

หลักการสำคัญของ microservices คือแต่ละ service มีฐานข้อมูลของตัวเอง (per-service DB) — บวกกับ cache, search engine, CDC และ stream processing นี่คือเครื่องมือด้านข้อมูลที่ใช้บ่อย:

text
Per-service DB:     PostgreSQL, MySQL, MongoDB, ฯลฯ
Cache:              Redis, Memcached
Search:             Elasticsearch, OpenSearch, Meilisearch
CDC:                Debezium → Kafka
Stream processing:  Kafka Streams, Flink, ksqlDB

9.5 Pattern Library

text
Saga:               orchestration (Camunda, Temporal) / choreography
                    → เหมือนแผนสำรองหลายขั้น: ถ้าขั้นไหนพัง ย้อนขั้นก่อนหน้า (undo/compensate)
Outbox:             transactional outbox + CDC
                    → save event ลง DB พร้อม business ใน transaction เดียว แล้วค่อยส่งออก broker
CQRS:               command/query แยก
                    → แยก "หน้าร้านขาย" (เขียน) กับ "คลังสินค้า" (อ่าน) ออกจากกัน
Event Sourcing:     เก็บ event แทน state
                    → แทนที่จะเก็บ "balance = 1000" เก็บ "deposit 500, withdraw 200, deposit 700"
Idempotency:        Idempotency-Key header / consumer dedup
                    → ทำซ้ำกี่รอบก็ผลเดิม — ป้องกัน duplicate จาก retry

แต่ละหัวข้อมีบทของตัวเอง — ตอนนี้แค่จำชื่อก็พอ


Part 10: คำศัพท์สำคัญในเล่มนี้ (Glossary)

คำความหมายสั้น
Serviceหน่วย deploy ที่ independent — มี API + DB ของตัวเอง
MonolithApp เดียว deploy เดียว DB เดียว
Modular MonolithMonolith ที่แบ่ง module ภายในชัดเจน
Bounded Contextขอบเขตของ domain ที่มี vocabulary + model ของตัวเอง (จาก DDD)
Aggregateกลุ่มของ entity ที่มี "root" — เป็น unit ของ transaction
API Gatewayจุดเข้าระบบเดียวสำหรับ client → route ไปยัง service ที่ถูกต้อง
BFFBackend For Frontend — gateway เฉพาะของ client แต่ละชนิด
Service Discoveryกลไกที่ service หา IP/port ของ service อื่น
Sync / Asyncคุยแล้วรอ response ทันที vs ส่งแล้วไม่รอ
Message Brokerserver กลางสำหรับ async communication (Kafka, RabbitMQ)
Queueลำดับ message ที่ consumer ดึงไปประมวล — ปกติ 1 message อ่านได้ 1 ครั้ง
Topicช่องสำหรับ pub/sub — 1 message ถูก consume ได้หลาย consumer group
Producerคนส่ง message
Consumerคนรับ/ประมวล message
Consumer Groupกลุ่ม consumer ที่ load-balance งานกันใน Kafka
Partitionsub-channel ใน topic Kafka — ใช้ parallel + ordering
Offsetตำแหน่งของ consumer ใน partition Kafka
At-most-oncemessage อาจหาย แต่ไม่ซ้ำ
At-least-oncemessage ไม่หาย แต่อาจซ้ำ
Exactly-onceไม่หายไม่ซ้ำ (มีเงื่อนไข)
Idempotentทำซ้ำได้โดยผลลัพธ์ไม่เปลี่ยน
DLQ (Dead Letter Queue)คิวเก็บ message ที่ประมวลไม่สำเร็จ
Outbox Patternsave event ลง DB ใน transaction เดียวกับ business → ส่งออก broker ทีหลัง
Sagasequence ของ local transaction + compensation เมื่อ fail
CQRSแยก model อ่าน vs เขียน
Event Sourcingเก็บ "event ที่เกิด" แทน "state ปัจจุบัน"
Circuit Breakerตัดวงจรเมื่อ downstream ล่ม — กัน cascading failure
Bulkheadแยก resource pool — กันล้มทั้งระบบเมื่อ 1 ส่วนล้ม
Distributed Tracingตามรอย 1 request ที่ข้ามหลาย service
Correlation IDid ที่ตามไปทุก service สำหรับ trace
Service Meshinfra layer ที่จัดการ communication ระหว่าง service (Istio, Linkerd)
mTLSmutual TLS — ทั้ง client + server มี cert ยืนยันตัวตน
Eventual Consistencyระบบจะ consistent ในที่สุด (ไม่ใช่ทันที)
CDC (Change Data Capture)จับการเปลี่ยนแปลงใน DB แล้วเอาไปกระจายเป็น event
Polyglotใช้หลายภาษา/หลาย DB ในระบบเดียว

ไม่ต้องจำทุกคำตอนนี้ — เจอบ่อยจะจำเอง. กลับมาดูตารางนี้เมื่องง


Part 11: Checkpoint สำคัญของบทนี้

ตอบ 13 คำถามนี้ก่อนไปบทถัดไป — ถ้าตอบไม่ได้ ให้กลับไปอ่านส่วนที่เกี่ยว

  1. นิยามของ "microservices" ของ Sam Newman คืออะไร? คำสำคัญ 2 คำคือ?
  2. ความต่างระหว่าง "monolith" กับ "modular monolith" คืออะไร?
  3. ตั้ง startup ใหม่ ทีม 3 คน — ควรใช้ microservices ตั้งแต่วันแรกไหม? ทำไม?
  4. "8 Fallacies of Distributed Computing" คืออะไร? ยกตัวอย่าง 3 ข้อ
  5. "Distributed Monolith" คืออะไร? อาการเป็นยังไง? แก้ยังไง?
  6. "Strangler Fig Pattern" คือ migration อะไร? เริ่มจากไหน?
  7. ทำไม shared database ระหว่าง service ถึงเป็น anti-pattern?
  8. "At-least-once delivery" ต่างกับ "At-most-once" ยังไง? (ดู Glossary Part 10 — อธิบายลึกอีกทีบท 06) อะไรพบบ่อยกว่าใน production?
  9. ก่อนตัด service ใหม่ออกจาก monolith ต้องเช็คอะไรบ้าง? (อย่างน้อย 3 ข้อ)
  10. "Bounded context" คืออะไร? ทำไมสำคัญตอนตัด service?
  11. Prime Video ย้ายจาก microservices กลับเป็น monolith ทำไม? ประหยัด cost ยังไง?
  12. Modular monolith (Shopify, Spring Modulith) ต่างจาก monolith ทั่วไปยังไง?
  13. "Cargo cult architecture" คืออะไร? ยกตัวอย่าง

💡 เก็บคำตอบของคุณไว้ — กลับมาดูตอนจบเล่ม คุณจะเห็นพัฒนาการตัวเอง


Part 12: สรุปบทนี้

  • Microservices คือ "service ที่ deploy ได้อิสระ + ตัดตาม domain" — ไม่ใช่แค่ "service ขนาดเล็ก"
  • เริ่มจาก monolith first เสมอ — ยกเว้นรู้ domain ดีและพร้อมทุกด้าน
  • 🆕 "Monolith comeback" (2023-2026) — ทีมย่อยของ Prime Video, Shopify, 37signals ย้ายกลับ (ไม่ใช่ทั้งบริษัทเสมอไป — เช่น Prime Video เป็นแค่เครื่องมือ 1 ตัว). ลูกตุ้มแกว่งกลับเพราะ cloud cost + complexity ของ microservices มากเกินไปสำหรับหลายทีม
  • Modular monolith = default ที่ดีกว่าสำหรับ team < 100 คน — ใช้ tool บังคับ boundary (Packwerk, Spring Modulith ที่จะพูดในบท 17 ของ spring-boot/)
  • 8 Fallacies = ผิดทั้งหมด — ออกแบบโดยสมมติว่า network ล่มได้, latency มี, security ต้อง verify
  • Anti-pattern ที่อันตรายที่สุดคือ distributed monolith — ตัดแล้วแต่ยังคู่กันแน่น
  • Cargo cult = อย่าเลียนแบบ Netflix/Uber ถ้าไม่มี constraint เดียวกัน
  • Migration ใช้ strangler pattern — ตัดทีละ feature, leaf → core
  • Decomposition ที่ดี = ตาม bounded context (DDD) — ไม่ใช่ตามเทคโนโลยี
  • Observability + CI/CD ต้องมาก่อน — ไม่มี = อย่าทำ
  • คิด cost/benefit ให้จริง — infra + cognitive + reliability cost บางทีเกินประโยชน์
  • 2026 wisdom: "Microservices is not a goal. It's a consequence." — แตกเมื่อ pain ชัด ไม่ใช่เพราะ trend

บทถัดไป — เราจะลงลึกเรื่อง "ตัด service ยังไงให้ถูก" ด้วย Domain-Driven Design (DDD) — bounded context, aggregate, event storming, strangler implementation จริง


← สารบัญ | ➡️ บทที่ 01: Service Decomposition (DDD)