ข้ามไปยังเนื้อหา

Versioning Strategies

เมื่อการเปลี่ยนแปลงจะทำให้ client ที่มีอยู่พัง คุณจำเป็นต้องมี versioning strategy เพื่อให้ client เก่าและใหม่อยู่ร่วมกันได้ มีสามที่ทั่วไปที่นิยมใช้สำหรับวางเวอร์ชัน

อันดับแรก ตัดสินใจก่อนว่าคุณจำเป็นต้องมีเวอร์ชันใหม่จริงหรือไม่ การเปลี่ยนแปลงแบบ non-breaking (เพิ่มเติม) ไม่เคยต้องการเวอร์ชันใหม่:

  • การเพิ่ม endpoint ใหม่ หรือ field ใหม่ที่เป็น optional
  • การเพิ่ม query parameter ใหม่ที่เป็น optional
  • การเพิ่มค่าใหม่เข้าไปใน enum ที่เป็น output-only (หาก client ได้รับการบอกให้ยอมรับค่าที่ไม่รู้จักได้)

การเปลี่ยนแปลงแบบ breaking ต้องการเวอร์ชันใหม่: การลบหรือเปลี่ยนชื่อ field, การเปลี่ยน type, การทำให้ field ที่เป็น optional กลายเป็น required, หรือการเปลี่ยนความหมายของ response

  • URI versioningGET /v1/articles มองเห็นได้ชัดเจนที่สุดและ route กับ cache ได้ง่ายที่สุด; เวอร์ชันอยู่ตรงนั้นใน URL เลย ข้อเสีย: resource เดียวกันจะอยู่ที่ URI สองที่ในเวอร์ชันต่างกัน
  • Header versioning — header แบบ custom หรือมาตรฐาน เช่น API-Version: 2 ทำให้ URI สะอาด แต่เวอร์ชันมองไม่เห็นใน log และลองผ่าน browser ได้ยากกว่า
  • Media-type versioning — เจรจาผ่าน Accept: application/vnd.example.article+json;version=2 เป็นวิธีที่ RESTful ที่สุด (เวอร์ชันเป็นส่วนหนึ่งของ representation) แต่ใช้งานยุ่งยากที่สุด
GET /v1/articles # URI versioning
GET /articles # header versioning
API-Version: 2
GET /articles # media-type versioning
Accept: application/vnd.example.article+json;version=2

สำหรับทีมส่วนใหญ่ URI versioning ชนะด้วยความเป็นปฏิบัตินิยม คือชัดเจน เป็นมิตรกับ cache และทดสอบง่ายมาก ไม่ว่าคุณจะเลือกแบบไหน ให้ทำเวอร์ชัน ทั้ง API ในระดับหยาบ (v1, v2) ไม่ใช่ทำเวอร์ชันแต่ละ endpoint แยกกัน — เวอร์ชันรายต่อ endpoint จะทำให้ support matrix บานปลาย

Strategyข้อดีข้อเสียเหมาะกับ
URI versioning (/v1/)ชัดเจน, cache ง่าย, test ง่ายresource มีสอง URIส่วนใหญ่ — practical choice
Header versioning (API-Version: 2)URI สะอาดมองไม่เห็นใน log, debug ยากInternal API ที่ control client
Media-type (Accept: ...;version=2)RESTful ที่สุดซับซ้อน, tooling support น้อยRarely used in practice

Version เฉพาะ Endpoint แทน API ทั้งหมด อาการ:

  • /v1/users แต่ /v2/orders ใน API เดียวกัน
  • client ต้อง track version ของแต่ละ endpoint แยกกัน
  • version ทั้ง API พร้อมกัน: /v1/users และ /v1/orders/v2/users และ /v2/orders

ไม่ Deprecate อย่าง Graceful อาการ:

  • ปิด /v1/ โดยไม่แจ้งล่วงหน้า — client พังทันที
  • ไม่มี migration guide หรือ timeline ชัดเจน
  • ใช้ Deprecation และ Sunset header: Sunset: Sat, 31 Dec 2024 23:59:59 GMT

💡 ตัวอย่างจากของจริง

Stripe API:

  • versioning ผ่าน Stripe-Version header — ไม่เปลี่ยน URI
  • account ถูก lock ที่ version ที่สร้าง — ไม่ break เมื่อ Stripe release version ใหม่

GitHub API:

  • URI versioning: /v3/ (REST), /graphql (GraphQL v4)
  • deprecation notice ล่วงหน้า 12 เดือน พร้อม Deprecation header
ข้อใดเป็น breaking change ที่สมควรมีเวอร์ชันใหม่?
versioning strategy แบบใดที่ใส่เวอร์ชันลงใน path โดยตรง?
คุณควรทำเวอร์ชันที่ระดับความละเอียดใด?