1. Home
  2. Learn
  3. OpenAPI
  4. API Versioning ควรใช้ path, header หรือ date-based แบบไหนดี
OpenAPI

API Versioning ควรใช้ path, header หรือ date-based แบบไหนดี

อธิบายข้อดีข้อเสียของการทำ API versioning แบบ path, header และ date-based ว่าแต่ละแบบเหมาะกับสถานการณ์ใด และควรตัดสินใจอย่างไรไม่ให้ contract ของระบบโตแล้วดูแลยาก

API Versioning ควรใช้ path, header หรือ date-based แบบไหนดี

พอระบบเริ่มมี API ที่มี consumer มากกว่าหนึ่งกลุ่ม คำถามเรื่อง versioning จะหนีไม่พ้นเร็วหรือช้าแค่ไหนเท่านั้น

  • ถ้าต้องเปลี่ยน response shape จะทำยังไง
  • ถ้าต้องแก้ field สำคัญที่ client ใช้อยู่ จะปล่อยยังไงไม่ให้พัง
  • ถ้ามี mobile app, frontend, partner integration และ internal tools ใช้ API ชุดเดียวกัน ควรเปลี่ยน contract ยังไง
  • ถ้าระบบยังเล็ก เราควรทำ versioning ตั้งแต่แรกไหม
  • ถ้าจำเป็นต้อง break จริง ควรใส่ version ไว้ตรง path, header หรือใช้วันที่แทนดี

ปัญหานี้สำคัญเพราะ API versioning ไม่ใช่แค่เรื่อง naming หรือ URL style แต่มันสะท้อนวิธีที่ทีมมอง contract ของระบบ

ถ้าทีมไม่มีแนวคิดชัดเจน มักเกิดอาการแบบนี้

  • เปลี่ยน contract แบบเงียบ ๆ
  • route เดิมเริ่มมีพฤติกรรมไม่เหมือนเดิม
  • frontend ใหม่ใช้ได้ แต่ mobile เก่าพัง
  • partner integration ตามไม่ทัน
  • backend มี if/else พะรุงพะรังเพื่อรองรับหลายพฤติกรรมใน endpoint เดียว
  • สุดท้าย versioning ถูกเพิ่มเข้ามาทีหลังในจังหวะที่ระบบเริ่มพันกันแล้ว

บทความนี้อธิบายว่า API versioning มีไว้เพื่ออะไร ข้อดีข้อเสียของแบบ path, header และ date-based คืออะไร และควรเลือกอย่างไรให้เหมาะกับระบบจริง

TL;DR

ถ้าจะสรุปให้สั้นที่สุด

ไม่มีรูปแบบไหนดีที่สุดสำหรับทุกระบบ

แต่โดยทั่วไป

  • Path versioning เข้าใจง่าย เหมาะกับ public APIs และทีมที่ต้องการความชัดสูง
  • Header versioning ยืดหยุ่นกว่า แต่ซ่อน complexity และ debug ยากกว่า
  • Date-based versioning เหมาะกับ APIs ที่ evolve ต่อเนื่องและต้องการสื่อ “generation” ของ contract มากกว่าเลขเวอร์ชันแบบตายตัว

ถ้าระบบของคุณยังไม่ซับซ้อนมากและมี consumer หลายกลุ่ม path versioning มักเป็นจุดเริ่มต้นที่ปลอดภัยที่สุด

API Versioning มีไว้ทำอะไร

แก่นจริงของ versioning ไม่ใช่การตั้งชื่อ /v1 หรือ /v2 แต่คือการจัดการการเปลี่ยนแปลงของ contract โดยไม่ทำให้ consumer เดิมพังโดยไม่ตั้งใจ

พูดให้ตรงกว่านั้น API versioning มีไว้ตอบคำถามว่า

  • ถ้า contract เปลี่ยน เราจะรักษาความเข้ากันได้ย้อนหลังยังไง
  • ถ้าจำเป็นต้อง break เราจะให้ consumer ย้ายยังไง
  • จะรู้ได้อย่างไรว่า request นี้กำลังเรียก behavior ชุดไหน
  • ระบบหนึ่งสามารถรองรับหลาย generation ของ contract พร้อมกันได้อย่างไร

Versioning จึงเป็นเรื่องของ compatibility, release governance และ lifecycle ของ API มากกว่าความสวยของ URL

ก่อนเลือกวิธี versioning ต้องถามอะไรบ้าง

ก่อนเถียงกันว่า /v1 ดีกว่า header หรือไม่ ควรถามให้ชัดก่อนว่าระบบของคุณเป็นแบบไหน

  • มี consumer กี่กลุ่ม
  • มี public API หรือใช้กันภายในอย่างเดียว
  • มี mobile app ที่อัปเดตช้าหรือไม่
  • มี partner integration ที่ควบคุมไม่ได้หรือไม่
  • ทีมมีวินัยเรื่อง backward compatibility ดีแค่ไหน
  • ระบบมี breaking changes บ่อยเพราะ requirement ยังไม่นิ่งหรือไม่
  • infrastructure, gateway, cache, observability และ docs พร้อมรองรับ versioning แบบไหน

คำตอบของคำถามพวกนี้สำคัญกว่าความนิยมของ pattern ใด pattern หนึ่ง

Path Versioning คืออะไร

Path versioning คือการใส่ version ลงใน URL โดยตรง เช่น

/v1/payments
/v2/payments

หรือ

/api/v1/orders
/api/v2/orders

แนวทางนี้เป็นแบบที่เห็นบ่อยที่สุด เพราะตรงไปตรงมาและมองเห็นได้ทันทีว่า request นี้เรียก contract ชุดไหน

ข้อดีของ Path Versioning

ข้อดีที่ชัดที่สุดคือ ความชัดเจน

เวลาคนเห็น request, log, dashboard, tracing หรือ docs ก็รู้ทันทีว่ากำลังใช้ version ไหนอยู่ ไม่ต้องเดาจาก header หรือ config แฝง

มันยังดีต่อเรื่องเหล่านี้ด้วย

  • route mapping อ่านง่าย
  • docs แยกชัด
  • debug ง่าย
  • reverse proxy และ caching เข้าใจง่าย
  • support และ partner คุยกันง่าย
  • test routing และ monitoring ตาม version ได้ตรงไปตรงมา

สำหรับระบบที่มี external consumers จำนวนมาก ความชัดนี้มีค่ามากกว่าที่ดูเผิน ๆ

ข้อเสียของ Path Versioning

ข้อเสียคือมันทำให้ version ไปโผล่ใน URL ชัดเจน ซึ่งบางคนมองว่า “pollute resource identity” หรือทำให้ route ซ้ำเยอะ

อีกปัญหาคือถ้าทีมใช้ versioning แบบหยาบเกินไป ทุกครั้งที่เปลี่ยนนิดเดียวก็แตก /v2, /v3, /v4 ไปเรื่อย ๆ สุดท้าย backend จะต้องแบก route หลายชุดพร้อมกันโดยไม่จำเป็น

ดังนั้นปัญหาของ path versioning ไม่ได้อยู่ที่ path เอง แต่อยู่ที่การใช้ versioning เกินความจำเป็นหรือไม่มี deprecation discipline

Header Versioning คืออะไร

Header versioning คือการคง path เดิมไว้ แต่ใช้ header เพื่อระบุ version เช่น

GET /payments
X-API-Version: 2

หรือใช้ media type versioning เช่น

Accept: application/vnd.example.v2+json

แนวคิดนี้พยายามแยก “resource path” ออกจาก “representation version” และทำให้ URL ดูสะอาดขึ้น

ข้อดีของ Header Versioning

จุดแข็งคือความยืดหยุ่น

คุณสามารถคง path เดิมไว้ได้ เช่น /payments แต่เปลี่ยน contract ตาม header ซึ่งทำให้ในเชิง conceptual บางคนรู้สึกว่า API สะอาดกว่า เพราะ resource identity ไม่ผูกกับ version โดยตรง

มันยังมีประโยชน์ในบางระบบที่อยาก

  • ควบคุมหลาย representation ของ resource เดียวกัน
  • ซ่อน versioning จาก URL
  • ใช้ gateway หรือ negotiation layer ช่วยตัดสิน contract
  • ทำ gradual migration บางแบบโดยไม่ต้องแตกเส้นทางชัดเจน

ข้อเสียของ Header Versioning

ข้อเสียหลักคือ มองไม่เห็นง่าย

เวลา debug จาก log, browser, curl, dashboards หรือ support tickets คนมักเห็น path ก่อน header เสมอ ถ้า version อยู่ใน header ความเข้าใจจะกระโดดช้ากว่า

มันยังสร้าง friction ในจุดอื่นด้วย เช่น

  • docs และ examples ต้องอธิบายเพิ่ม
  • frontend หรือ partner ต้องจำ header พิเศษ
  • caching/proxy setup ต้องระวังมากขึ้น
  • log บางระบบอาจไม่แสดง header สำคัญครบ
  • support ตามปัญหายากกว่าเมื่อ consumer ส่ง header ผิดหรือไม่ส่ง

พูดง่าย ๆ คือ header versioning ยืดหยุ่นจริง แต่ต้นทุนด้าน operational clarity สูงกว่า

Date-based Versioning คืออะไร

Date-based versioning ใช้วันที่เป็นตัวระบุ generation ของ API เช่น

X-API-Version: 2026-04-18

หรือบางระบบใช้ในรูปแบบ config/contract label ที่ชัดเจนว่า request นี้อยู่ใต้ contract set ใดที่เริ่มใช้ในวันหนึ่ง

แนวคิดนี้พบได้ใน APIs ที่ evolve ต่อเนื่องและอยากทำให้ “version” สื่อถึงช่วงเวลาของ contract มากกว่าเลขลำดับแบบ v1, v2

ข้อดีของ Date-based Versioning

จุดแข็งของ date-based versioning คือมันบอกได้ชัดว่า consumer ผูกกับ contract generation เมื่อไร

ในระบบที่มีการเปลี่ยนแบบ incremental ต่อเนื่อง การใช้วันที่ช่วยให้ทีมคิดแบบนี้ได้

  • consumer นี้ล็อกอยู่กับ behavior ณ วันที่ใด
  • contract ใหม่เริ่มใช้เมื่อไร
  • deprecation window ควรวัดจากวันไหน

วิธีนี้มักเข้ากับ APIs ที่ปล่อยการเปลี่ยนแปลงแบบต่อเนื่องและมี release governance ค่อนข้างดี

ข้อเสียของ Date-based Versioning

ข้อเสียคือมันเข้าใจยากกว่าสำหรับทีมทั่วไปและ partner บางกลุ่ม เพราะ 2026-04-18 ไม่ได้บอกโดยสัญชาตญาณว่าเปลี่ยนอะไรจาก 2025-11-01

อีกทั้งถ้าทีมไม่มีวินัยเรื่อง changelog, migration notes และ compatibility policy ที่ดี วันที่จะกลายเป็นเพียง label ที่ดูเป็นระบบ แต่ช่วยตัดสินใจจริงได้น้อย

พูดอีกแบบคือ date-based versioning ต้องการ maturity ด้าน release communication มากกว่าการใช้ /v1 แบบธรรมดา

แล้วแบบไหนเหมาะกับระบบประเภทไหน

ถ้าเป็น public API หรือ partner-facing API

ส่วนใหญ่ path versioning จะปลอดภัยกว่า เพราะสื่อสารง่ายและ debug ง่าย โดยเฉพาะเมื่อมี consumer ที่ไม่ได้อยู่ในทีมเดียวกัน

ตัวอย่างเช่น

  • /v1/payments
  • /v1/orders
  • /v2/orders

นี่ช่วยให้เอกสาร, support และ rollout plan ตรงกันมาก

ถ้าเป็น internal API ที่ทีมควบคุม consumer ได้เกือบหมด

header versioning อาจใช้ได้ ถ้าทีมมีมาตรฐาน logging, tracing และ docs ที่ดีพอ เพราะ complexity เชิง operation ยังพอคุมได้

ถ้าเป็น platform API ที่ evolve ต่อเนื่องและมี contract governance ดีมาก

date-based versioning อาจเหมาะ โดยเฉพาะเมื่อทีมต้องการสื่อว่า contract นี้ผูกกับ snapshot ของเวลา ไม่ใช่แค่เลข major version

จริง ๆ แล้วต้อง version ทุกครั้งที่เปลี่ยนไหม

ไม่จำเป็น

นี่คือจุดที่สำคัญมาก เพราะหลายทีมพอเริ่มคุยเรื่อง versioning ก็เผลอคิดว่าทุกการเปลี่ยนต้องแตก /v2 ทันที ซึ่งไม่จริง

ถ้าการเปลี่ยนเป็น backward-compatible เช่น

  • เพิ่ม optional field ใน response
  • เพิ่ม endpoint ใหม่
  • เพิ่ม optional parameter
  • เพิ่ม behavior ที่ consumer เดิมยังไปต่อได้

ส่วนใหญ่ไม่จำเป็นต้องแตก version ใหม่

Versioning ควรใช้เมื่อมี breaking change ที่รักษา backward compatibility ได้ไม่คุ้ม หรือทำไม่ได้จริง มากกว่า

ถ้าจะเลี่ยงการแตก version ควรทำอย่างไร

ในหลายกรณี การออกแบบให้เปลี่ยนแบบ additive ก่อนจะคุ้มกว่า เช่น

  • เพิ่ม field ใหม่โดยคง field เดิมไว้ก่อน
  • mark field เดิมว่า deprecated
  • ให้เวลาย้าย
  • track consumer adoption
  • ค่อยลบในรุ่นถัดไป

แนวทางนี้ช่วยลดจำนวน version ที่ระบบต้องแบก และยังให้ consumer มีทางย้ายอย่างมีระเบียบ

ตัวอย่างเปรียบเทียบ

สมมติเดิมมี API แบบนี้

POST /payments

แล้วทีมต้องเปลี่ยน request shape แบบ break

แบบ Path Versioning

POST /v1/payments
POST /v2/payments

ข้อดีคือชัดมากว่าใครใช้ contract ไหน

แบบ Header Versioning

POST /payments
X-API-Version: 1

หรือ

POST /payments
X-API-Version: 2

ข้อดีคือ path ไม่เปลี่ยน แต่ต้องให้ทุก consumer ส่ง version ถูกต้อง

แบบ Date-based Versioning

POST /payments
X-API-Version: 2026-04-18

ข้อดีคือสื่อ generation ของ contract ได้ แต่ต้องมี release notes ที่ดีมาก

Path versioning กับ caching / routing / observability

เหตุผลที่หลายทีมยังเลือก path versioning ไม่ใช่เพราะมันสวยที่สุด แต่เพราะมันเข้ากับ operation จริงได้ง่าย

เช่น

  • routing rules แยกง่าย
  • metrics ต่อ version แยกง่าย
  • dashboards ต่อ version แยกง่าย
  • log search ง่าย
  • canary rollout หรือ deprecation notice ชัด
  • tracing อ่านง่าย

พอระบบเริ่มมีหลายทีมหรือมี incident จริง ความชัดระดับนี้ช่วยได้เยอะมาก

Header versioning กับ runtime complexity

Header versioning มักดู elegant ตอนออกแบบ แต่ความยุ่งจะค่อย ๆ โผล่ใน runtime เช่น

  • client บางตัวลืมส่ง header
  • gateway หรือ CDN cache ไม่แยก variant ถูกต้อง
  • support อ่าน log แล้วไม่รู้ว่ากำลังดู version ไหน
  • tooling บางตัวไม่แสดง header สำคัญ
  • tests ต้องครอบคลุม combination เพิ่มขึ้น

นี่ไม่ได้แปลว่ามันไม่ดี แต่แปลว่ามันต้องการ operational discipline มากกว่า

Date-based versioning กับ lifecycle management

date-based versioning จะทำงานได้ดีเมื่อทีมตอบคำถามพวกนี้ได้ชัด

  • version วันที่นี้รับประกัน backward compatibility แค่ไหน
  • support กี่เดือน
  • deprecate เมื่อไร
  • migration guide อยู่ตรงไหน
  • consumer จะรู้ได้อย่างไรว่าควรย้ายไปวันไหน

ถ้าตอบคำถามพวกนี้ไม่ได้ การใช้วันที่จะกลายเป็นแค่ป้ายชื่อที่ดูเป็นระบบ แต่ไม่ช่วยการ migrate จริงเท่าไร

อย่าสับสนระหว่าง “versioning” กับ “routing style”

บางครั้งปัญหาจริงไม่ได้อยู่ที่เลือก path หรือ header แต่เกิดจากทีมยังไม่ชัดว่าอะไรคือ breaking change และเมื่อไรควรแตก version

ถ้าทีมยังปล่อย breaking changes เข้า version เดิมเรื่อย ๆ ไม่ว่าใช้ /v1 หรือ X-API-Version ก็ยังพังได้เหมือนกัน

ดังนั้นก่อนเลือก style ต้องมีอย่างน้อย

  • นิยาม breaking change
  • deprecation policy
  • migration path
  • release communication
  • contract checks ใน CI

style ของ versioning เป็นเพียงเครื่องมือ ไม่ใช่คำตอบทั้งหมด

Versioning เกี่ยวกับ OpenAPI Validation ยังไง

ถ้าระบบใช้ OpenAPI validation จริง การแยก version จะชัดขึ้นมาก เพราะแต่ละ contract มี schema ของตัวเอง และ runtime/test สามารถ enforce ได้ตรง version

ตัวอย่างเช่น

  • /v1/payments ใช้ schema ชุดหนึ่ง
  • /v2/payments ใช้อีกชุดหนึ่ง

หรือถ้าใช้ header/date-based ก็ยังต้อง map request ไปยัง schema ที่ถูกต้องอยู่ดี

ดังนั้น versioning ที่ดีควรไปด้วยกันกับ contract validation ไม่ใช่แยกขาดจากกัน

Versioning เกี่ยวกับ Payment/Webhook flow ยังไง

ระบบที่มี payment, webhook และ order state machine ต้องระวัง versioning มากเป็นพิเศษ เพราะ breaking change ไม่ได้กระทบแค่ request/response หน้าเดียว แต่มักกระทบ flow ทั้งเส้น

เช่น

  • เปลี่ยน shape ของ payment create request
  • เปลี่ยนสถานะที่ response คืน
  • เปลี่ยน event payload ของ webhook
  • เปลี่ยนความหมายของ status ใน order lifecycle

ถ้าจุดพวกนี้เปลี่ยนโดยไม่มีกลยุทธ์ versioning ชัด ฝั่ง webhook consumer, worker และ reconciliation logic อาจเริ่มไม่ตรงกัน

ตัวอย่าง OpenAPI แบบ Path Versioning

openapi: 3.0.3
info:
  title: Payments API
  version: 2.0.0

paths:
  /v1/payments:
    post:
      summary: Create payment (v1)
      responses:
        "201":
          description: Created

  /v2/payments:
    post:
      summary: Create payment (v2)
      responses:
        "201":
          description: Created

แนวทางนี้แม้จะดูซ้ำ แต่ช่วยให้แต่ละ contract ถูกมองแยกกันชัดเจน

ตัวอย่าง Express/Node.js แบบเริ่มต้น

ตัวอย่างนี้สาธิตแนวคิด path versioning เพราะเป็นแบบที่ตรงไปตรงมาและเข้าใจง่ายที่สุดสำหรับหลายระบบ

const express = require("express");

const app = express();
app.use(express.json());

app.post("/v1/payments", (req, res) => {
  const body = req.body;

  if (typeof body.amount !== "number") {
    return res.status(400).json({
      error: "amount must be a number"
    });
  }

  return res.status(201).json({
    success: true,
    paymentId: "pay_v1_123",
    status: "created"
  });
});

app.post("/v2/payments", (req, res) => {
  const body = req.body;

  if (typeof body.amount !== "number") {
    return res.status(400).json({
      error: "amount must be a number"
    });
  }

  if (typeof body.orderId !== "string" || !body.orderId.trim()) {
    return res.status(400).json({
      error: "orderId is required"
    });
  }

  return res.status(201).json({
    success: true,
    paymentId: "pay_v2_456",
    paymentStatus: "created"
  });
});

app.listen(3000, () => {
  console.log("Server listening on port 3000");
});

โค้ดนี้ไม่ได้พยายามบอกว่า path versioning เป็นคำตอบเดียว แต่แสดงให้เห็นว่าพอ contract ของ v1 กับ v2 แยกกันชัด การ reasoning เรื่อง compatibility, docs และ testing จะง่ายขึ้นมาก

ถ้าเริ่มใหม่วันนี้ ควรเลือกอะไร

ถ้าพูดแบบใช้ได้จริงกับทีมส่วนใหญ่

  • ถ้ามี external consumers, partner, mobile app หรือหลายทีมเกี่ยวข้อง ให้เริ่มที่ path versioning
  • ถ้าเป็น internal platform ที่มี observability และ tooling แข็งมาก จะพิจารณา header versioning ได้
  • ถ้าองค์กรมี API governance mature และชอบ contract generations มากกว่าเลขเวอร์ชัน ค่อยพิจารณา date-based versioning

สำหรับทีมส่วนใหญ่ path versioning ไม่ใช่เพราะมันหรูที่สุด แต่เพราะมันทำให้เรื่องยากหลายอย่างง่ายขึ้นในชีวิตจริง

สิ่งที่ควรหลีกเลี่ยง

สิ่งที่มักทำให้ versioning พัง ไม่ได้เกิดจากการเลือก style ผิดอย่างเดียว แต่เกิดจากพฤติกรรมพวกนี้

  • เปลี่ยน contract แบบ break ใน version เดิม
  • แตก version ใหม่โดยไม่มี deprecation plan
  • ปล่อยให้แต่ละ version drift โดยไม่มี docs และ tests ที่ชัด
  • ใช้ versioning เพื่อหนี requirement ที่ยังไม่นิ่ง
  • บอกว่ามี v2 แต่ยังไม่มี migration guide หรือ timeline ปิด v1

versioning ที่ดีต้องคู่กับ release discipline เสมอ

รีวิวแนวทางนี้แบบ production-minded

Correctness

versioning ที่ดีช่วยให้ consumer รู้ชัดว่ากำลังใช้ contract ไหน และช่วยลดการแตกของ integration เมื่อระบบต้อง evolve

Security

เมื่อ version ชัด การ enforce policy, auth behavior และ contract validation ต่อรุ่นจะชัดขึ้นด้วย และลดความเสี่ยงที่ behavior สำคัญเปลี่ยนแบบเงียบ ๆ

Efficiency

path versioning มักคุ้มที่สุดสำหรับหลายทีมเพราะ debug, route, docs และ support ง่าย ส่วน header/date-based อาจคุ้มเมื่อองค์กรมี maturity สูงพอ

Error handling

ถ้า versioning ชัด error ที่เกิดจาก wrong contract หรือ migration mismatch จะวิเคราะห์ง่ายขึ้นมาก โดยเฉพาะเมื่อ log, metrics และ dashboards แยกตาม version ได้

Checklist สั้น ๆ ก่อนเลือก API Versioning Strategy

  • รู้หรือยังว่าอะไรคือ breaking change ของระบบ
  • มี consumer กี่กลุ่ม และควบคุมได้แค่ไหน
  • มี deprecation policy ชัดหรือยัง
  • docs, validation และ tests แยกตาม version ได้หรือไม่
  • gateway, cache และ observability รองรับ strategy นี้ไหม
  • ทีม support/debug จะดูออกไหมว่า request นี้ใช้ version ไหน
  • มี migration path ชัดสำหรับ consumer หรือไม่
  • route สำคัญ เช่น payment, webhook, order flow ถูกประเมินผลกระทบหรือยัง
  • ทีมพร้อมแบก version เก่ากี่รุ่นพร้อมกัน
  • strategy ที่เลือกทำให้ชีวิต runtime ง่ายขึ้นหรือยากขึ้น

บทความที่ควรอ่านต่อ

สรุป

API versioning ไม่ใช่เรื่องเลือก syntax ที่เท่ที่สุด แต่คือการเลือกวิธีจัดการการเปลี่ยนแปลงของ contract ให้เหมาะกับ consumer, release process และความพร้อมของทีม

ถ้าระบบของคุณต้องการความชัดสูงและมี consumer หลายกลุ่ม path versioning มักเป็นทางเลือกที่ปลอดภัยกว่า
ถ้าทีมของคุณควบคุม ecosystem ได้ดีและพร้อมแบก complexity เชิง operation มากขึ้น ค่อยพิจารณา header หรือ date-based versioning

สรุปสั้นที่สุดคือ

เลือก versioning แบบที่ทำให้ contract ชัดขึ้นตอน production ไม่ใช่แค่ดูสวยขึ้นตอนออกแบบ

💬 Chat (ตอบเร็ว)