บทที่ 17 · Part 5 — Decisions & Delivery

Trade-offs & Decisions

Frame สำหรับเทียบทางเลือกในห้องประชุม, CAP/PACELC ตามความจริง, cost เป็น design axis, build-vs-buy และ ADR

ใครก็ลิสต์ทางเลือกได้ งานของ architect คือ เลือก, อธิบายการเลือกด้วยภาษาที่ธุรกิจเข้าใจ, และ ทิ้งบันทึกไว้ให้ทีมในอนาคตประเมินใหม่ได้ บทนี้คือวินัยของการเลือก

จบบทนี้คุณจะ

  • ใช้ frame 5 ขั้นเทียบทางเลือกบนกระดานได้ใน 20 นาที
  • พูดเรื่อง CAP/PACELC ได้ถูกต้อง โดยไม่ตกหลุมที่คนส่วนใหญ่ตก
  • สร้าง cost model หยาบๆ ได้ใน 1 ชั่วโมง และรู้ว่า cost per transaction เปลี่ยนบทสนทนาอย่างไร
  • แยก one-way door ออกจาก two-way door และจัดสรรเวลารีวิวให้ถูก
  • เขียน ADR 1 หน้าที่ใช้ได้จริง
  • จับ anti-pattern 10 ข้อได้จากประโยคที่คนพูด

[!TIP] ไม่มี best practice มีแต่ trade-off ในบริบท "Microservices เป็น best practice" ไม่ใช่คำกล่าวเกี่ยวกับสถาปัตยกรรม แต่เป็นคำกล่าวเกี่ยวกับงานที่แล้วของใครคนหนึ่ง

ทุกคุณสมบัติที่คุณได้มา คุณจ่ายด้วยอีกอย่าง — consistency จ่ายด้วย availability, ความยืดหยุ่นจ่ายด้วยความเรียบง่าย, performance จ่ายด้วยเงิน, การ decouple จ่ายด้วยความสามารถในการตามรอย, redundancy จ่ายด้วย consistency

เวลาใครพูดคำว่า "best practice" คำถามที่มีประโยชน์คือ "best สำหรับ quality attribute ตัวไหน และทีมที่ทำแบบนั้นจ่ายอะไรไป"

Frame 5 ขั้นที่ใช้ได้ในห้องประชุม

  1. ตั้งการตัดสินใจเป็นคำถามที่แคบ — ไม่ใช่ "ควรใช้ฐานข้อมูลอะไร" แต่เป็น "เก็บ transfer history ที่ไหน ให้ pattern #2 (list 20 รายการล่าสุดต่อ account, 100/s, p99 150 ms) และ pattern #7 (ประวัติ 7 ปี, 50/วัน) ถูก serve ทั้งคู่"
  2. ลิสต์เกณฑ์ที่สำคัญกับเคสนี้ และให้น้ำหนัก — ก่อนดูทางเลือก การให้น้ำหนักหลังจากมีตัวโปรดแล้วคือการหาเหตุผลมาสนับสนุน ไม่ใช่การตัดสินใจ
  3. ลิสต์ 3 ทางเลือก และหนึ่งในนั้นต้องเป็น "สิ่งที่ง่ายที่สุด" (ไม่ทำอะไร หรือขยายของที่มีอยู่) — ถ้าทางเลือกที่ง่ายไม่อยู่ในตาราง การเทียบนั้นไม่ซื่อสัตย์
  4. ให้คะแนน แล้วเขียนเหตุผล 1 บรรทัดต่อช่อง — เหตุผลคือผลลัพธ์จริง ตัวเลขเป็นแค่วิธีทำให้เห็นรูปร่าง
  5. เขียนไว้ว่าอะไรจะทำให้เปลี่ยนการตัดสินใจ — "ถ้า write volume เกิน 5,000/s ให้ทบทวน" ข้อนี้เปลี่ยนการตัดสินใจให้เป็นสิ่งที่ monitor ได้ และทำให้การทบทวน เป็นเรื่องปกติ ไม่ใช่การยอมรับความล้มเหลว

ตัวอย่างเดินจริง: เก็บ transfer history ที่ไหน

เกณฑ์ (น้ำหนัก)A · Postgres เดิม partition ตามเดือนB · Postgres hot + archive บน object storageC · Cassandra สำหรับประวัติทั้งหมด
Serve pattern #2 (w3)3 index บน (account_id, created_at)3 เหมือนกันสำหรับ hot data3 partition key ตรงตามธรรมชาติ
Serve pattern #7 (w1)2 ได้ แต่ทำให้ OLTP box บวม3 นี่คือสิ่งที่ cold storage มีไว้ทำ3 ได้สบาย
อยู่ใน transaction เดียวกับ ledger (w3)3 transaction เดียวกัน ฟรี3 hot path ไม่เปลี่ยน0 ต้องมี saga หรือ dual write
ต้นทุน operational (w2)3 ไม่มีอะไรใหม่ต้องรัน2 archive job 1 ตัว + เส้นทาง query1 cluster ใหม่, ทักษะใหม่, on-call ใหม่
ค่า infra ที่ 5 ปี (w2)1 8 TB บน premium storage3 ถูกกว่าราว 100 เท่าสำหรับ cold2 ถูกกว่าต่อ byte แต่ node มากกว่า
Headroom ถึง 20× (w1)1 จะต้อง shard2 เหมือนกัน แต่ช้ากว่า3 ออกแบบมาเพื่อสิ่งนี้
รวมถ่วงน้ำหนัก283322

วิธีนำเสนอผลลัพธ์นั้น

"เราเลือก B: เก็บ 90 วันใน Postgres และ archive ข้อมูลที่เก่ากว่านั้นลง object storage เป็น Parquet พร้อมเส้นทาง query แบบ on-demand มัน serve access pattern ได้ทั้ง 2 อัน, รักษาการเขียน ledger ไว้ใน transaction เดียว, และถูกกว่าราว 100 เท่าสำหรับภาระ retention 7 ปี

เรายอมรับว่า query ข้อมูลที่ archive แล้วใช้เวลาระดับวินาทีไม่ใช่มิลลิวินาที ซึ่งตรงกับ SLA ที่ระบุไว้สำหรับ pattern นั้น

เราจะทบทวนถ้าปริมาณ transfer เกิน 5,000/s ต่อเนื่อง หรือถ้าทีม ops ต้องเข้าถึงข้อมูลเก่าในระดับต่ำกว่าวินาที

Cassandra ได้คะแนนต่ำสุดเพราะมันจะทำลายการเขียน ledger แบบ atomic — นั่นคือต้นทุนด้านความถูกต้องที่เราไม่ยอมจ่ายเพื่อ scale ที่เรายังไม่มี"

สังเกตว่าย่อหน้านั้นทำ 4 อย่าง: บอกสิ่งที่เลือก, เหตุผล, ต้นทุนที่ยอมรับ, trigger ที่จะทบทวน, และ ทำไมตัวที่แพ้จึงแพ้ — 4 ประโยค นั่นคือ deliverable

CAP, PACELC และสิ่งที่เกิดขึ้นจริง

CAP: เมื่อ network เกิด partition (P) คุณต้องเลือกระหว่าง consistency (C) กับ availability (A) — นั่นคือทั้งทฤษฎีบท และมันถูกใช้ผิดบ่อยมาก

สิ่งที่ CAP **ไม่ได้** พูด

  • ไม่ได้พูดว่า "เลือก 2 จาก 3" — partition ไม่ใช่ทางเลือก เพราะ network มันล้มเอง คุณกำลังเลือกระหว่าง C กับ A ตอนที่เกิด partition เท่านั้น
  • C ใน CAP คือ linearizability ไม่ใช่ C ใน ACID — คนละแนวคิดที่ใช้ตัวอักษรเดียวกัน
  • ไม่ได้พูดอะไรเลยเกี่ยวกับ latency ตอนทำงานปกติ — ซึ่งเป็นสถานะที่ระบบของคุณอยู่ 99.99% ของชีวิต นั่นคือช่องว่างที่ PACELC มาเติม
  • มันเป็นเรื่องต่อ operation ไม่ใช่ต่อระบบ — ฐานข้อมูลตัวเดียวกัน serve การอ่านยอดเงินแบบ linearizable และการอ่าน feed แบบ eventual ได้พร้อมกัน การพูดว่า "ระบบเราเป็น AP" มักเป็นสัญญาณว่าไม่มีใครดูให้ละเอียด

PACELC เป็นสูตรที่มีประโยชน์กว่า: ถ้ามี Partition ให้เลือก A หรือ C; Else (ตอนทำงานปกติ) ให้เลือก Latency หรือ Consistency

ระบบพฤติกรรมตอน partitionพฤติกรรมตอนทำงานปกติ
Relational DB แบบ single-primaryPC — write หยุดแทนที่จะแยกทางกันEC — synchronous commit รอ replica
Cassandra ที่ QUORUMPA/PC ปรับได้ด้วย consistency levelEL — แลก consistency กับ latency ได้ต่อ query
DynamoDBPC สำหรับ strongly consistent read, PA สำหรับ eventualEL — eventual read ถูกกว่าและเร็วกว่า
Google SpannerPC — ปฏิเสธแทนที่จะแยกทางกันEC — จ่าย latency จริงเพื่อ global consistency (TrueTime)

อ้างอิง: CAP Twelve Years Later — Eric Brewer อธิบายเองว่าทฤษฎีบทของเขาถูกอ่านผิดอย่างไร · PACELC ของ Daniel Abadi

ตาราง trade-off ที่คุณจะใช้บ่อยที่สุด

ถ้าคุณต้องการ…คุณจะจ่ายด้วย…ทางออกที่ใช้กันบ่อย
Strong consistencylatency และ availability ตอน partitionทำให้เฉพาะ decision path เป็น strong และให้ display path เป็น eventual
Read latency ต่ำความเก่าของข้อมูลระบุ ขอบเขตความเก่าไว้ใน SLO บวก read-your-writes ให้ actor
Write throughput สูงความยืดหยุ่นของ query, join, บางทีรวมถึง orderingเขียนลง append store ที่เร็ว แล้วสร้าง read model แบบ async
ความเป็นอิสระของ serviceความสามารถตามรอย และการเสีย database transactionoutbox + saga + correlation ID + ที่เดียวที่เห็น flow ทั้งหมด
ไม่ให้ข้อมูลหาย (RPO 0)write latency (synchronous replication)ยอมรับมัน — สำหรับเงินไม่มีทางออก และไม่ควรไปหา
ส่งของเร็วdesign debt ที่สะสมเรียกชื่อหนี้นั้นออกมาพร้อม trigger ที่จะจ่ายคืน ไม่ใช่ "เดี๋ยวมาเก็บ"
ต้นทุนต่ำลงheadroom และวันหยุดของใครคนหนึ่งright-size ตาม พีคที่วัดได้ ไม่ใช่ตามความกลัว
ชิ้นส่วนน้อยลงเพดานการ scale บางอย่างมักเป็นการแลกที่ถูกต้อง — เอาไปเลย แล้วทบทวนที่ trigger ที่บันทึกไว้

Cost เป็น design axis ระดับหนึ่ง

Architect ที่คุยเรื่องต้นทุนไม่ได้ คือ architect ที่ธุรกิจเลิกฟัง

เงินบน cloud ไปอยู่ที่ไหนจริงๆ

หมวดความจริงที่มักเกิด
Computeมักเป็นบรรทัดใหญ่สุด และมัก over-provision 3–10 เท่าเพราะไม่มีใครวัด · right-size ตาม p95 utilization ที่วัดได้, autoscaling ที่มีพื้นสมเหตุสมผล, committed-use discount สำหรับ baseline ที่นิ่ง
Managed databaseแพงต่อ GB และต่อ IOPS · การลดปริมาณข้อมูล (archive) และลดจำนวน index มักประหยัดได้มากกว่าการลดขนาด instance
Network egressบรรทัดที่ทำให้ทุกคนตกใจ — ข้อมูลที่ออกจาก cloud และมักรวมถึงข้อมูลที่ข้าม zone/region ถูกคิดเงิน · service mesh ที่คุยกันข้าม AZ เยอะอาจแพงกว่า compute ที่มันประสานงาน
Observabilitylog และ metric ingestion ถูกมิเตอร์ · debug log ที่ละเอียดในระดับ scale แพงกว่า application ได้จริง · sample, structure, ตั้ง retention ต่อ stream, ทิ้งสิ่งที่ไม่มีใคร query
Non-production ที่เปิดทิ้งdev/test/staging รัน 24/7 ให้ทีมที่ทำงาน 40 ชั่วโมงต่อสัปดาห์ — scheduled shutdown คือเงินฟรี
คนต้นทุนที่ใหญ่ที่สุดในแทบทุกระบบ · สถาปัตยกรรมที่ต้องมีผู้เชี่ยวชาญ 3 คนดูแลแพงกว่าอันที่ไม่ต้องมีเลย แม้ใบแจ้งหนี้จะน้อยกว่า — พูดข้อนี้ออกมาดังๆ ในห้องรีวิว มันคือข้อโต้แย้งที่ชนะความซับซ้อนที่ไม่จำเป็น

Unit economics — ตัวเลขที่ทำให้คุณน่าเชื่อถือ

คำนวณ COST PER BUSINESS EVENT แล้วติดตามมันตามเวลา

  ค่า infra ต่อเดือน / จำนวน transaction ต่อเดือน = ต้นทุนต่อ transaction

ตัวอย่าง: infra 300,000 บาท/เดือน, 15,000,000 transaction
  = 0.02 บาท ต่อ transaction

ตอนนี้ทุกข้อเสนอเชิง design ประเมินได้ในหน่วยเดียวกัน:
 - "cache ตัวนี้ลดขนาด DB และประหยัดราว 0.003 บาท/txn ที่ปริมาณปัจจุบัน"
 - "fraud service ใหม่เพิ่มราว 0.008 บาท/txn คุ้มกับ fraud ที่ลดลงที่คาดไว้ไหม"
   <-- คำถามที่ฝ่ายธุรกิจตอบได้
 - "ต้นทุนต่อ transaction เพิ่ม 40% ไตรมาสนี้ ขณะที่ปริมาณเพิ่ม 10%"
   <-- นั่นคือปัญหาเชิงสถาปัตยกรรม และตอนนี้มันมองเห็นได้

Metric ตัวเดียวนี้เปลี่ยนวิธีที่ผู้บริหารมองงานสถาปัตยกรรม

จาก cost centre ที่มาขอเงิน เป็น function ที่บริหารตัวเลขที่พวกเขาสนใจ — สร้าง dashboard นี้

Build vs buy vs partner

พิจารณาBuildBuy / SaaSPartner (ธนาคารหรือผู้ให้บริการที่มีใบอนุญาต)
เหมาะเมื่อมันคือสิ่งที่ทำให้คุณต่าง หรือไม่มี product ไหนเข้ากับ constraint ของคุณเป็นปัญหา commodity ที่แก้แล้ว (auth, email, SMS, monitoring, feature flag)ความสามารถนั้นต้องมีใบอนุญาต, สมาชิกภาพใน scheme, หรือสถานะทางกฎหมายที่คุณไม่มี
ต้นทุนจริงbuild + operate + on-call + upgrade ตลอดไป — ประมาณเป็น 3 เท่าของที่คุณประเมินไว้ค่า license + integration + ต้นทุนของ outage ของเขา + ต้นทุนการย้ายในอนาคตค่าธรรมเนียม + integration + change window ของเขา + roadmap ของเขากลายเป็นของคุณ
ความเสี่ยงหลักopportunity cost — คุณไม่ได้สร้าง productlock-in; data residency; SLA ของเขาไม่ใช่ SLO ของคุณ; เขาถูกซื้อกิจการconcentration risk; อำนาจต่อรองจำกัด; คุณรับ availability ของเขามาเป็นของคุณ
การบรรเทาtimebox; ทำให้เล็ก; ซื่อสัตย์ว่าใครจะ maintain มันในปีที่ 3ห่อไว้หลัง interface ของคุณเอง (adapter) ให้เปลี่ยนได้; เป็นเจ้าของการ export ข้อมูลของตัวเองออกแบบเผื่อ 2 provider ตั้งแต่วันแรก แม้จะเปิดตัวด้วยรายเดียว — abstraction เหนือ rail ราคาถูกวันนี้ และมีค่ามหาศาลวันหน้า

Third-party dependency ในธุรกิจที่ถูกกำกับดูแลคือสถาปัตยกรรม **และ** governance

เมื่อคุณพึ่งผู้ให้บริการภายนอกสำหรับความสามารถที่ลูกค้าเห็น design ต้องตอบได้ว่า:

  • availability ตามสัญญาของเขาเท่าไหร่ และมันมีผลต่อ SLO ของเราอย่างไร
  • ระหว่าง maintenance window ของเขา เราจะเข้าคิว, degrade, หรือปฏิเสธ
  • failover ไป provider รายที่ 2 คืออะไร และเคยทดสอบแล้วหรือยัง
  • ข้อมูลอะไรออกจากสภาพแวดล้อมของเรา ภายใต้ข้อตกลงอะไร
  • ใครได้รับแจ้งเมื่อเขามี incident และเรารู้ได้อย่างไร (status page ที่ต้องจำไปเปิดดูเองไม่ใช่กลไกตรวจจับ — subscribe แบบ programmatic)

การเลือกหรือเปลี่ยน provider ที่แตะเงินหรือข้อมูลลูกค้าไม่ใช่การตัดสินใจของฝ่ายวิศวกรรมเพียงลำพัง เตรียมการประเมินทางเทคนิคและทางเลือกไว้ ส่วนการผูกพันต้องมีเจ้าของที่รับผิดชอบ (procurement, risk, compliance, legal) — เขียนข้อนี้ไว้ใน design doc ไม่ใช่สมมติว่ามีคนอื่นจัดการแล้ว

One-way door และ two-way door

Two-way door (ย้อนกลับได้)One-way door (ย้อนยาก)
ตัวอย่างการเลือก library, ขอบเขต service ภายใน, cache TTL, API ภายใน, instance typepublic API contract, event schema ที่ consumer พึ่ง, partition key, รูปแบบ ID, การแทนค่าเงิน/จำนวน, สัญญา vendor, อะไรที่เก็บข้อมูลลูกค้า
กระบวนการตัดสินเร็วในทีม ลองเลย วัดผล ผิดก็เปลี่ยนช้าลง เขียนเป็นเอกสาร ให้คนที่จะอยู่กับมันรีวิว ทำ prototype ถ้าทำได้
Failure modeanalysis paralysis กับเรื่องที่ไม่สำคัญการตัดสินใจ 30 นาทีที่มีต้นทุน 2 ปี

ทีมส่วนใหญ่ทำกลับกันเป๊ะ

เถียงเรื่อง framework เป็นสัปดาห์ (two-way) แต่ใช้ 15 นาทีกับ event schema ที่ consumer 11 รายจะพึ่งพาไป 5 ปี (one-way)

การแทรกแซงที่มีค่าที่สุดของ architect บ่อยครั้งคือแค่พูดออกมาดังๆ ว่า "อันนี้เป็น one-way door เรามาใช้เวลากับมันจริงๆ กันเถอะ"

ADR — 1 หน้า ถาวร

# ADR-014: ใช้ immutable double-entry ledger สำหรับยอดเงิน wallet

Status:   Accepted            (Proposed | Accepted | Superseded by ADR-nnn)
Date:     2026-08-07
Deciders: <ชื่อ/ตำแหน่ง>       Consulted: <finance, risk>

## Context
ยอดเงิน wallet ปัจจุบันเป็นคอลัมน์ที่แก้ได้ ใน 6 เดือนที่ผ่านมามี 3 incident
ที่อธิบายยอดเงินไม่ได้ และไม่มีทางไล่ที่มาว่ามันมาถึงตัวเลขนั้นได้อย่างไร
Internal audit ขอให้แสดงที่มาของยอดใดก็ได้ ปริมาณ ~500k txn/วัน
คาดว่าจะเป็น 2M/วัน ภายใน 18 เดือน

## Decision
เก็บการเคลื่อนย้ายเงินทั้งหมดเป็น immutable double-entry ledger entry
ที่รวมกันได้ 0 ต่อ transaction · derive ยอดเงิน · มี snapshot table
พร้อม watermark สำหรับ read performance · บังคับ unique idempotency key
ต่อ transaction ที่ระดับฐานข้อมูล

## Consequences
+ ยอดเงินใดก็อธิบายและตรวจสอบได้ครบ
+ การแก้ไขกลายเป็น reversal entry ที่มองเห็นได้ (ตอบข้อกำหนด audit)
+ กำจัด write contention บนแถวเดียวของ account ที่ร้อน
+ zero-sum monitor แบบต่อเนื่องตรวจจับ bug ได้ทั้งคลาสตั้งแต่ต้น
- การอ่านยอดกลายเป็น snapshot + delta ไม่ใช่การอ่านคอลัมน์เดียว
- storage โตราว 5 เท่าต่อ transaction (วัดได้: ~2 KB เทียบ ~0.4 KB)
- ต้อง migrate ยอดเงินเดิม โดยมี opening-balance entry ต่อ account
  ต้องมี finance sign-off กับตัวเลขตอน cutover

## Options considered
1. คงคอลัมน์ที่แก้ได้ไว้ แล้วเพิ่มตาราง audit log
   ปฏิเสธ: audit log กับยอดเงินขัดกันได้ และยอดเงินยังเป็น authority
   จึงไม่ได้แก้ปัญหา
2. ใช้ ledger database เฉพาะทาง
   ปฏิเสธในรอบนี้: เพิ่ม operational dependency; ปริมาณของเรายังไม่ต้องการ
   ทบทวนเมื่อเกิน ~5,000 txn/s
3. Immutable double-entry ใน Postgres ที่มีอยู่  <-- เลือกอันนี้

## Revisit if
- write rate ต่อเนื่องเกิน 5,000 entry/s หรือ
- p99 ของการอ่านยอดเกิน 50 ms หลัง tune snapshot แล้ว หรือ
- ข้อกำหนด retention เปลี่ยนจนทำให้ hot storage เกิน ~4 TB

ทำไม ADR คุ้มค่า 20 นาที

6 เดือนถัดมามีคนถามว่า "ทำไมมันซับซ้อนขนาดนี้" ถ้าไม่มี ADR คำตอบที่ซื่อสัตย์คือ "ไม่มีใครจำได้" และผลที่น่าจะเกิดคือการเขียนใหม่ที่ไปค้นพบ constraint ชุดเดิมด้วยความเจ็บปวดแบบเดิม

ถ้ามี ADR คุณได้คำตอบจริง รวมถึงทางเลือกที่ถูกปฏิเสธและเหตุผล ซึ่งเป็นส่วนที่ป้องกันการวนลูป

ADR ยังทำให้การ onboard เร็วขึ้นมาก และให้คำตอบที่ป้องกันได้เวลา auditor ถามว่าทำไมมี control นี้

เก็บไว้ใน repository ข้างโค้ด, ใส่หมายเลข, append-only — การ supersede ADR หมายถึงเขียนฉบับใหม่ที่อ้างถึงฉบับเดิม ไม่ใช่แก้ประวัติ (Michael Nygard · adr.github.io)

Anti-pattern และ design smell

Smellเสียงที่ได้ยินปัญหาที่ซ่อนอยู่ทำอะไร
Resume-driven design"เราควรใช้ Kafka กับ Kubernetes กับ service mesh"เลือกเทคโนโลยีก่อนมี requirementถาม "requirement ข้อไหน" 3 ครั้ง ถ้าไม่มีคำตอบ มันก็ไม่ใช่ requirement
Distributed monolith"เรามี 12 service แต่ทั้งหมด deploy พร้อมกันและใช้ฐานข้อมูลเดียวกัน"จ่ายค่าความกระจายไปแล้วแต่ไม่ได้ประโยชน์อะไรกลับมารวมกลับ หรือแยกข้อมูลให้จริงจัง — อันนี้แย่ที่สุดของทั้ง 2โลก และพบบ่อยมาก
Premature scaling"มาออกแบบเผื่อผู้ใช้ 1 ล้านคน"ความซับซ้อนวันนี้เพื่อโหลดที่อาจไม่มาถึง · product จริงตายเพราะส่งของช้าออกแบบเผื่อ 10× ของวันนี้ เขียนเส้นทางถึง 100× ไว้ แล้วส่งของ
Shared mutable database"ทีม reporting อ่านตารางเราตรงๆ"schema ของคุณกลายเป็น public API ที่คุณแก้ไม่ได้ให้ view, replica, export หรือ event stream — interface ที่คุณ version ได้
God service"ทุกอย่างเรียก core service"single point of failure, คอขวดของ deployment, ทีมเดียวบล็อกทุกคนแยกตามความเป็นเจ้าของข้อมูล; ย้าย read path ไปมี model ของตัวเอง
Chatty boundaries"มันเรียก 40 ครั้งเพื่อ render หน้าเดียว"latency และความน่าจะเป็นที่จะล้มคูณกันต่อการเรียกbatch endpoint, aggregate ที่ edge (BFF), หรือ ทบทวนขอบเขต — 40 ครั้งหมายถึงรอยต่ออยู่ผิดที่
Big-bang rewrite"เราจะสร้าง v2 ขนานกันแล้วสลับปีหน้า"2 ระบบที่ต้องดูแล, เป้าที่เคลื่อนที่, และ cutover ที่ไม่มีการซ้อม · อัตราล้มเหลวสูงมากในประวัติศาสตร์Strangler fig: route ทีละส่วน, ให้ทั้ง 2รันอยู่, migrate ทีละนิด, พร้อม release เสมอ
Speculative abstraction"เราทำให้ pluggable ไว้เผื่อเปลี่ยน provider"abstraction ที่ออกแบบก่อนมี implementation ที่ 2 มักเป็น abstraction ที่ผิดรอเคสจริงอันที่ 2 · ข้อยกเว้น: dependency ที่ถูกกำกับ (payment rail, KYC provider) ที่การมี provider ที่ 2 เป็น requirement ที่รู้อยู่แล้ว — ที่นั่นให้สร้างรอยต่อไว้ก่อนอย่างตั้งใจ
Retry everything"เราใส่ retry แล้ว ตอนนี้ resilient แล้ว"retry ที่ไม่มี idempotency, budget และ jitter ขยายความล้มเหลวดูบทที่ 12 — retry เป็นตัวคูณโหลดก่อนที่จะเป็นเครื่องมือ resilience
Alert on everything"เรามี alert 400 ตัว"alert fatigue — ตัวจริงถูก mutealert ที่ อาการที่ผู้ใช้รู้สึก และที่ SLO burn rate · ที่เหลือเป็น dashboard

อ้างอิง: Strangler Fig Application · Sacrificial Architecture — ฉบับหลังเป็นการมองใหม่ที่มีประโยชน์: การสร้างของที่คุณตั้งใจจะทิ้งเป็นเรื่องชอบธรรม ถ้าคุณพูดออกมาดังๆ และวางแผนไว้

Lab 17 — ตัดสิน ป้องกัน และบันทึก

ส่วน A (35 นาที) หยิบการตัดสินใจที่ยังเปิดอยู่จริงจากงานของคุณ ทำ frame ให้ครบ: คำถามที่แคบ, เกณฑ์ที่ถ่วงน้ำหนัก, 3 ทางเลือกรวมทางที่ง่ายที่สุด, ช่องคะแนนที่มีเหตุผล 1 บรรทัด, และ trigger ที่จะทบทวน

กฎ: คุณต้องใส่ทางเลือกที่คุณเองไม่ชอบ และให้คะแนนมันอย่างเป็นธรรม

ส่วน B (25 นาที) เขียน ADR ตาม template ข้างบน ข้อจำกัด: 1 หน้า ถ้าไม่พอ แปลว่าการตัดสินใจของคุณจริงๆ เป็นหลายการตัดสินใจ — แยกมัน

ส่วน C (30 นาที) สลับกับอีกกลุ่มแล้วเล่นบท devil's advocate หน้าที่ของ reviewer คือหา: เกณฑ์ที่ขาดไป, น้ำหนักที่ถูกเลือกเพื่อให้ตัวโปรดชนะ, ทางเลือกที่ถูกทำให้อ่อนแอเกินจริง, และ consequence ที่ตกหายไป

ทุกกลุ่มจะมีอย่างน้อย 2 ข้อ — นั่นคือประเด็น นี่คือสิ่งที่ review ที่ดีทำ และการทำให้กันคือวิธีที่ทักษะนี้ถ่ายทอด

สรุปบทนี้

ตั้งคำถามให้แคบ ถ่วงน้ำหนักเกณฑ์ก่อนดูทางเลือก และต้องมีทางที่ง่ายที่สุดในตาราง · เขียน trigger ที่จะทบทวนไว้ทุกครั้ง · CAP เป็นเรื่องต่อ operation ไม่ใช่ต่อระบบ · cost per transaction เปลี่ยนสถานะของงานสถาปัตยกรรมในสายตาผู้บริหาร · ใช้เวลารีวิวกับ one-way door ไม่ใช่ two-way door · และ ADR 1 หน้าที่บอกว่า ทางเลือกที่แพ้แพ้เพราะอะไร คือสิ่งที่ป้องกันการเขียนใหม่ในอีก 2 ปี