เมื่อคุณสร้าง API ขึ้นมาให้ผู้ใช้งาน (Consumer) ใช้ ไม่ว่าจะเป็น Mobile App, Third-party Developer หรือ Frontend ของคุณเอง สิ่งที่หลีกเลี่ยงไม่ได้คือ API จะต้องเปลี่ยนแปลงตามเวลา ฟีเจอร์ใหม่ถูกเพิ่ม โครงสร้างข้อมูลถูกปรับ และบางครั้ง Breaking Changes ก็เกิดขึ้น คำถามคือ จะจัดการ Version ของ API อย่างไรให้ไม่ทำลาย Consumer ที่มีอยู่เดิม
บทความนี้จะพาคุณเรียนรู้กลยุทธ์ API Versioning ทั้งหมด ตั้งแต่ URL Path, Header, Content Negotiation ไปจนถึง Deprecation Policy และ API Evolution โดยไม่ต้องเปลี่ยน Version เลย พร้อมตัวอย่างจากบริษัทชั้นนำอย่าง Stripe, GitHub และ Twilio ถ้าหากคุณกำลังสร้าง Backend ด้วย Elixir และ Phoenix Framework บทความนี้จะช่วยให้คุณออกแบบ API ได้ดียิ่งขึ้น
ทำไม API Versioning ถึงสำคัญ?
API เป็นสัญญา (Contract) ระหว่างผู้ให้บริการกับผู้ใช้บริการ เมื่อคุณเผยแพร่ API ออกไปแล้ว มี Consumer จำนวนมากที่พัฒนา Application บน API ของคุณ การเปลี่ยนแปลง API โดยไม่มีแผนจัดการ Version อาจทำให้ Consumer เหล่านั้นเสียหายทันที
ปัญหาที่เกิดขึ้นเมื่อไม่มี Versioning
- Breaking Changes ทำลาย Consumer: เปลี่ยนชื่อ Field จาก
user_nameเป็นusernameทำให้ Consumer ทุกคนที่ใช้user_nameพัง - ไม่สามารถ Evolve API: กลัวจะ Break Consumer จน API ไม่ได้รับการปรับปรุง
- ไม่มี Migration Path: Consumer ไม่รู้ว่าจะย้ายไปใช้ API ใหม่อย่างไร
- สูญเสียความเชื่อมั่น: Developer ไม่อยากใช้ API ที่เปลี่ยนแปลงโดยไม่แจ้งล่วงหน้า
Breaking Changes vs Non-breaking Changes
| ประเภท | ตัวอย่าง | ผลกระทบ |
|---|---|---|
| Breaking Change | ลบ Field ที่มีอยู่ | Consumer ที่ใช้ Field นั้นพัง |
| Breaking Change | เปลี่ยนชื่อ Field | Consumer ต้องแก้ Code |
| Breaking Change | เปลี่ยน Data Type (string เป็น int) | Parsing ผิดพลาด |
| Breaking Change | เปลี่ยน URL/Endpoint | Request ไม่ถึงปลายทาง |
| Breaking Change | เพิ่ม Required Parameter | Request เดิมส่งไม่ผ่าน |
| Non-breaking | เพิ่ม Field ใหม่ใน Response | Consumer เดิมไม่ได้รับผลกระทบ |
| Non-breaking | เพิ่ม Optional Parameter | Request เดิมยังทำงานได้ |
| Non-breaking | เพิ่ม Endpoint ใหม่ | ไม่กระทบ Endpoint เดิม |
| Non-breaking | เพิ่ม Enum Value ใหม่ | ไม่กระทบ Value เดิม |
กลยุทธ์ API Versioning
1. URL Path Versioning
วิธีที่นิยมมากที่สุด โดยใส่ Version Number ไว้ใน URL Path
# URL Path Versioning
GET /api/v1/users
GET /api/v2/users
GET /api/v3/users
# ตัวอย่างใน Express.js (Node.js)
const express = require('express');
const app = express();
// Version 1
app.get('/api/v1/users', (req, res) => {
res.json({ users: [{ user_name: 'Bom', email: 'bom@example.com' }] });
});
// Version 2 — เปลี่ยนจาก user_name เป็น username
app.get('/api/v2/users', (req, res) => {
res.json({ users: [{ username: 'Bom', email: 'bom@example.com', created_at: '2026-01-01' }] });
});
# ตัวอย่างใน Flask (Python)
from flask import Flask, Blueprint
app = Flask(__name__)
v1 = Blueprint('v1', __name__, url_prefix='/api/v1')
v2 = Blueprint('v2', __name__, url_prefix='/api/v2')
@v1.route('/users')
def get_users_v1():
return {"users": [{"user_name": "Bom"}]}
@v2.route('/users')
def get_users_v2():
return {"users": [{"username": "Bom", "created_at": "2026-01-01"}]}
ข้อดี: เข้าใจง่าย เห็น Version ชัดเจน Cache-friendly แต่ละ Version มี URL แยก ทดสอบง่าย
ข้อเสีย: URL เปลี่ยน ทำให้ Consumer ต้องเปลี่ยน URL ที่เรียก อาจมี Code ซ้ำระหว่าง Version
บริษัทที่ใช้: Google, Twitter, Facebook, Stripe
2. Query Parameter Versioning
ใส่ Version เป็น Query Parameter
# Query Parameter Versioning
GET /api/users?version=1
GET /api/users?v=2
GET /api/users?api-version=2026-04-10
# ตัวอย่าง
app.get('/api/users', (req, res) => {
const version = req.query.v || '1'; // Default to v1
if (version === '2') {
return res.json({ users: [{ username: 'Bom' }] });
}
// Default: v1
res.json({ users: [{ user_name: 'Bom' }] });
});
ข้อดี: URL หลักไม่เปลี่ยน ง่ายต่อการ Default Version ให้ถ้าไม่ระบุ
ข้อเสีย: Query Param อาจหายไปเมื่อ Copy URL ทำให้เกิด Routing ที่ซับซ้อน Cache อาจมีปัญหา
บริษัทที่ใช้: Amazon Web Services, Azure
3. Header Versioning (Custom Header)
ใส่ Version ใน HTTP Header
# Custom Header Versioning
GET /api/users
Accept-Version: v1
GET /api/users
X-API-Version: 2
# ตัวอย่าง Express.js
app.get('/api/users', (req, res) => {
const version = req.headers['accept-version'] || 'v1';
if (version === 'v2') {
return res.json({ users: [{ username: 'Bom' }] });
}
res.json({ users: [{ user_name: 'Bom' }] });
});
# ตัวอย่าง Python/FastAPI
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/api/users")
async def get_users(accept_version: str = Header("v1")):
if accept_version == "v2":
return {"users": [{"username": "Bom"}]}
return {"users": [{"user_name": "Bom"}]}
ข้อดี: URL สะอาด ไม่เปลี่ยน เหมาะสำหรับ API ที่ต้องการแยก Version Logic ออกจาก URL
ข้อเสีย: ยากต่อการทดสอบผ่าน Browser ต้องใช้เครื่องมือเฉพาะ (Postman, curl) Developer อาจลืมใส่ Header
บริษัทที่ใช้: GitHub (ก่อนหน้านี้), Azure DevOps
4. Content Negotiation (Accept Header)
ใช้ Media Type ใน Accept Header เพื่อระบุ Version
# Content Negotiation
GET /api/users
Accept: application/vnd.myapi.v1+json
GET /api/users
Accept: application/vnd.myapi.v2+json
# GitHub API Style
GET /api/users
Accept: application/vnd.github.v3+json
# ตัวอย่าง
app.get('/api/users', (req, res) => {
const accept = req.headers['accept'] || '';
if (accept.includes('vnd.myapi.v2')) {
res.type('application/vnd.myapi.v2+json');
return res.json({ users: [{ username: 'Bom' }] });
}
res.type('application/vnd.myapi.v1+json');
res.json({ users: [{ user_name: 'Bom' }] });
});
ข้อดี: เป็นไปตาม REST Principles อย่างแท้จริง URL ไม่เปลี่ยน Representation เดียวกันหลาย Format ได้
ข้อเสีย: ซับซ้อนที่สุด Developer ต้องเข้าใจ Media Type ยากต่อการทดสอบ
บริษัทที่ใช้: GitHub (ปัจจุบัน)
เปรียบเทียบกลยุทธ์ Versioning
| เกณฑ์ | URL Path | Query Param | Header | Content Negotiation |
|---|---|---|---|---|
| ความง่ายในการใช้ | สูงมาก | สูง | ปานกลาง | ต่ำ |
| ความง่ายในการทดสอบ | สูงมาก | สูง | ต่ำ | ต่ำ |
| URL สะอาด | ไม่ | ไม่ | ใช่ | ใช่ |
| RESTful | ปานกลาง | ต่ำ | สูง | สูงมาก |
| Cache-friendly | สูง | ปานกลาง | ต่ำ | ต่ำ |
| ความนิยม | สูงมาก | ปานกลาง | ต่ำ | ต่ำ |
Semantic Versioning สำหรับ API
Semantic Versioning (SemVer) ใช้รูปแบบ MAJOR.MINOR.PATCH สำหรับ API อาจปรับใช้เฉพาะ MAJOR Version ใน URL Path และใช้ MINOR/PATCH สำหรับ Non-breaking Changes
# Semantic Versioning สำหรับ API
# MAJOR — Breaking Changes (ต้องเปลี่ยน Version ใน URL)
# MINOR — เพิ่มฟีเจอร์ใหม่ (Backward Compatible)
# PATCH — แก้ Bug (Backward Compatible)
# URL ใช้เฉพาะ MAJOR
GET /api/v1/users # v1.0.0 → v1.5.3 ทั้งหมดอยู่ที่ /v1/
GET /api/v2/users # v2.0.0 เมื่อมี Breaking Change
# Date-based Versioning (Stripe Style)
GET /api/users
Stripe-Version: 2026-04-10
# ข้อดี: ชัดเจนว่า API เวอร์ชันไหน ณ วันที่ไหน
# Stripe ให้ Consumer "pin" ไว้ที่ Version ที่ต้องการ
Deprecation Policy — การยกเลิก API Version เก่า
เมื่อออก API Version ใหม่ ไม่ควรปิด Version เก่าทันที ต้องมี Deprecation Period ที่ให้ Consumer มีเวลาย้ายไปใช้ Version ใหม่
Sunset Header
# HTTP Response Header บอก Consumer ว่า API จะถูกปิดเมื่อไหร่
HTTP/1.1 200 OK
Sunset: Sat, 01 Jan 2027 00:00:00 GMT
Deprecation: true
Link: <https://api.example.com/v2/users>; rel="successor-version"
# ตัวอย่าง Express.js Middleware
function deprecationMiddleware(sunsetDate, successorUrl) {
return (req, res, next) => {
res.set('Sunset', new Date(sunsetDate).toUTCString());
res.set('Deprecation', 'true');
res.set('Link', `<${successorUrl}>; rel="successor-version"`);
next();
};
}
// ใช้กับ v1 routes ทั้งหมด
app.use('/api/v1', deprecationMiddleware('2027-01-01', '/api/v2'));
Deprecation Notice ใน Response Body
# เพิ่ม Warning ใน Response
{
"data": [...],
"meta": {
"deprecation": {
"message": "API v1 จะถูกปิดให้บริการวันที่ 1 มกราคม 2027",
"sunset_date": "2027-01-01",
"migration_guide": "https://docs.example.com/migration/v1-to-v2",
"successor": "https://api.example.com/v2/users"
}
}
}
แนวทาง Deprecation ที่ดี
- แจ้งล่วงหน้าอย่างน้อย 6-12 เดือน ก่อนปิด Version เก่า
- ส่ง Email/Notification ให้ Consumer ทุกคนที่ยังใช้ Version เก่าอยู่
- ให้ Migration Guide ที่ละเอียดและชัดเจน
- ติดตาม Usage ว่ายังมี Consumer ใช้ Version เก่าอยู่หรือไม่
- ค่อยๆ ลดประสิทธิภาพ เช่น Rate Limit ต่ำลงสำหรับ Version เก่า
API Evolution โดยไม่ต้อง Versioning
บาง API สามารถ Evolve ได้โดยไม่ต้องเปลี่ยน Version เลย ถ้าปฏิบัติตามหลัก Additive Changes และ Backward Compatibility
หลัก Additive Change
# เพิ่ม Field ใหม่ได้ (Non-breaking)
# Before:
{ "name": "Bom", "email": "bom@example.com" }
# After: เพิ่ม field ใหม่
{ "name": "Bom", "email": "bom@example.com", "avatar_url": "https://..." }
# Consumer เดิมที่ไม่ได้ใช้ avatar_url จะไม่ได้รับผลกระทบ
# เพิ่ม Optional Parameter ได้ (Non-breaking)
# Before:
GET /api/users?page=1
# After: เพิ่ม filter parameter
GET /api/users?page=1&role=admin
# Request เดิมที่ไม่ส่ง role ยังทำงานได้ปกติ
# เพิ่ม Endpoint ใหม่ได้ (Non-breaking)
GET /api/users # เดิม
GET /api/users/stats # ใหม่ — ไม่กระทบเดิม
Tolerant Reader Pattern
ออกแบบ Consumer ให้อ่านเฉพาะ Field ที่ตัวเองต้องการ และ Ignore Field ที่ไม่รู้จัก
# Consumer ที่ดี (Tolerant Reader)
const response = await fetch('/api/users/1');
const user = await response.json();
// ใช้เฉพาะ field ที่ต้องการ ไม่สนใจ field อื่น
const name = user.name;
const email = user.email;
// ถ้า API เพิ่ม field ใหม่ Consumer ไม่พัง
# Consumer ที่ไม่ดี (Strict Validation)
// Validate ว่า Response ต้องมีเฉพาะ field ที่คาดไว้
// ถ้า API เพิ่ม field ใหม่ Validation จะ Fail
Expand/Contract Pattern
เทคนิคเปลี่ยนชื่อ Field โดยไม่ Breaking
# Phase 1: Expand — เพิ่ม field ใหม่ (ส่งทั้งเก่าและใหม่)
{
"user_name": "Bom", // เก่า (deprecated)
"username": "Bom", // ใหม่
"email": "bom@example.com"
}
# Phase 2: Announce — แจ้ง Consumer ให้เปลี่ยนไปใช้ username
# Phase 3: Contract — ลบ field เก่าออก (หลังจาก Consumer ย้ายหมดแล้ว)
{
"username": "Bom",
"email": "bom@example.com"
}
Consumer-Driven Contract Testing (Pact)
Consumer-Driven Contract Testing เป็นวิธีทดสอบว่า API ยังตรงกับสิ่งที่ Consumer คาดหวังอยู่หรือไม่ โดยใช้เครื่องมืออย่าง Pact
# Pact — Consumer-Driven Contract Testing
# Consumer Side: กำหนดว่า API ที่ต้องการหน้าตาเป็นอย่างไร
// consumer.test.js (JavaScript)
const { Pact } = require('@pact-foundation/pact');
const provider = new Pact({
consumer: 'MyFrontend',
provider: 'UserAPI',
});
describe('User API Contract', () => {
it('returns user by id', async () => {
await provider.addInteraction({
state: 'user with id 1 exists',
uponReceiving: 'a request for user 1',
withRequest: {
method: 'GET',
path: '/api/v1/users/1',
},
willRespondWith: {
status: 200,
body: {
id: 1,
username: Matchers.string('Bom'),
email: Matchers.email(),
},
},
});
});
});
# Provider Side: ตรวจสอบว่า API ยังตรงกับ Contract
// provider.test.js
const { Verifier } = require('@pact-foundation/pact');
new Verifier({
providerBaseUrl: 'http://localhost:3000',
pactUrls: ['./pacts/myfrontend-userapi.json'],
}).verifyProvider();
API Gateway สำหรับ Version Routing
API Gateway เช่น Kong, AWS API Gateway หรือ Nginx สามารถจัดการ Version Routing ให้ได้อัตโนมัติ โดย Consumer เรียก URL เดียว แต่ Gateway จะ Route ไปยัง Backend ที่ถูก Version
# Nginx Configuration สำหรับ Version Routing
upstream api_v1 {
server backend-v1:3000;
}
upstream api_v2 {
server backend-v2:3000;
}
server {
listen 80;
# URL Path Versioning
location /api/v1/ {
proxy_pass http://api_v1/;
# เพิ่ม Deprecation Header
add_header Sunset "Sat, 01 Jan 2027 00:00:00 GMT";
add_header Deprecation "true";
}
location /api/v2/ {
proxy_pass http://api_v2/;
}
# Header-based Versioning
location /api/ {
if ($http_accept_version = "v1") {
proxy_pass http://api_v1;
}
proxy_pass http://api_v2; # Default to latest
}
}
# AWS API Gateway — สร้าง Stage สำหรับแต่ละ Version
# v1 → Stage: v1 → Lambda/ECS v1
# v2 → Stage: v2 → Lambda/ECS v2
OpenAPI/Swagger สำหรับ API Versioning
OpenAPI Specification (Swagger) ช่วยให้คุณสร้างเอกสาร API ที่ชัดเจนสำหรับแต่ละ Version ทำให้ Consumer เห็นความแตกต่างระหว่าง Version ได้ง่าย
# openapi-v1.yaml
openapi: 3.0.3
info:
title: My API
version: "1.0.0"
description: |
API Version 1
**Deprecated**: จะถูกปิดวันที่ 1 มกราคม 2027
Migration Guide: https://docs.example.com/migration
paths:
/api/v1/users:
get:
summary: List Users (v1)
deprecated: true # ทำเครื่องหมายว่า Deprecated
responses:
'200':
content:
application/json:
schema:
type: object
properties:
users:
type: array
items:
properties:
user_name:
type: string
deprecated: true
# openapi-v2.yaml
openapi: 3.0.3
info:
title: My API
version: "2.0.0"
paths:
/api/v2/users:
get:
summary: List Users (v2)
responses:
'200':
content:
application/json:
schema:
type: object
properties:
users:
type: array
items:
properties:
username:
type: string
created_at:
type: string
format: date-time
GraphQL Schema Evolution vs REST Versioning
GraphQL มีแนวทางที่แตกต่างจาก REST ในการจัดการ Version ของ API เนื่องจาก GraphQL ให้ Consumer เลือกเฉพาะ Field ที่ต้องการ ทำให้การเพิ่ม Field ใหม่ไม่กระทบ Consumer เลย
# GraphQL — ไม่ต้อง Version เพราะ Consumer เลือก Field เอง
# Schema Evolution
type User {
id: ID!
username: String!
email: String!
avatarUrl: String # เพิ่มใหม่ — ไม่กระทบ Consumer เดิม
userName: String @deprecated(reason: "Use 'username' instead")
}
# Consumer เดิมที่ใช้ userName ยังทำงานได้
query {
user(id: 1) {
userName # Deprecated แต่ยังใช้ได้
email
}
}
# Consumer ใหม่ใช้ username
query {
user(id: 1) {
username # Field ใหม่
email
avatarUrl # Field ใหม่
}
}
# ข้อดีของ GraphQL สำหรับ Evolution:
# 1. ไม่ต้อง Version URL
# 2. @deprecated Directive แจ้งเตือน Consumer
# 3. Consumer เลือก Field เอง — เพิ่ม/ลบ Field ง่าย
# 4. Schema Introspection ช่วยให้เห็น Deprecation
# ข้อเสียของ GraphQL:
# 1. ไม่สามารถ Break Field ที่มีอยู่ได้ (ต้อง Deprecate แล้วรอลบ)
# 2. Schema อาจบวมขึ้นเรื่อยๆ (Deprecated Field สะสม)
# 3. ซับซ้อนกว่า REST สำหรับ Use Case ง่ายๆ
API Lifecycle Management
การจัดการ API Lifecycle ที่ดีครอบคลุมตั้งแต่การออกแบบ API ใหม่ไปจนถึงการปลดระวาง Version เก่า
ขั้นตอน API Lifecycle
- Design: ออกแบบ API ด้วย OpenAPI Spec ก่อนเขียน Code ใช้ Design-first Approach
- Development: พัฒนา API ตาม Spec พร้อม Contract Testing
- Testing: ทดสอบทั้ง Unit, Integration และ Contract Test
- Release: เผยแพร่ API พร้อม Documentation ที่ครบถ้วน
- Maintenance: ดูแล API ปัจจุบัน แก้ Bug เพิ่ม Non-breaking Features
- Deprecation: แจ้ง Consumer เมื่อจะออก Version ใหม่และยกเลิก Version เก่า
- Retirement: ปิด Version เก่าหลังจาก Deprecation Period สิ้นสุด
API Changelog
# CHANGELOG.md สำหรับ API
## [v2.0.0] - 2026-04-10
### Breaking Changes
- เปลี่ยน `user_name` เป็น `username` ใน /users endpoint
- ลบ `legacy_id` field ออกจาก Response
### Added
- เพิ่ม `created_at` field ใน /users response
- เพิ่ม /users/stats endpoint ใหม่
### Migration Guide
- แทนที่ `user_name` ด้วย `username` ใน Code ของคุณ
- ใช้ `id` แทน `legacy_id`
## [v1.5.0] - 2026-03-15
### Added
- เพิ่ม `avatar_url` field ใน /users response (Non-breaking)
- เพิ่ม `role` query parameter สำหรับ Filter
## [v1.4.2] - 2026-03-01
### Fixed
- แก้ Bug Pagination ที่ส่ง Duplicate Results
ตัวอย่างจากบริษัทชั้นนำ
Stripe — Date-based Versioning
Stripe ใช้วิธี Versioning ที่ไม่เหมือนใคร โดยใช้ วันที่ เป็น Version Number
- Consumer ระบุ Version ผ่าน Header
Stripe-Version: 2026-04-10 - หรือตั้งค่า Default Version ใน Dashboard
- API จะทำงานตาม Behavior ของ Version ที่ระบุ
- ระบบภายในใช้ "Version Changelog" ที่บันทึกทุกการเปลี่ยนแปลง
- มี Backward Compatibility Layer ที่แปลง Request/Response ระหว่าง Version
GitHub — Accept Header + URL Path
- ใช้
Accept: application/vnd.github.v3+jsonสำหรับระบุ Version - มี URL Path Version สำหรับ Major Change เท่านั้น
- Deprecation Notice ผ่าน Header และ Blog Post
- ให้เวลา 12 เดือนก่อนปิด Version เก่า
Twilio — URL Path + Sunset Policy
- ใช้ URL Path Versioning เช่น
/2010-04-01/Accounts - มี Sunset Policy ที่ชัดเจน ให้เวลาอย่างน้อย 24 เดือน
- ส่ง Email แจ้ง Consumer ทุกรอบ
- มี Migration Toolkit ช่วย Consumer ย้ายอัตโนมัติ
Best Practices สำหรับ API Versioning
- เลือกกลยุทธ์เดียวแล้วใช้ให้สม่ำเสมอ: อย่าผสมหลายวิธี เช่น บาง Endpoint ใช้ URL Path บางอันใช้ Header
- เริ่มต้นด้วย v1: ตั้งแต่วันแรกที่เปิดให้ใช้ Public API อย่ารอจนมีปัญหาแล้วค่อยเริ่ม Version
- ออกแบบให้ Backward Compatible เสมอ: พยายาม Additive Changes ให้มากที่สุด ลด Breaking Change ให้น้อยที่สุด
- มี Deprecation Policy ที่ชัดเจน: กำหนด Timeline ล่วงหน้า แจ้ง Consumer อย่างเพียงพอ
- ใช้ Contract Testing: ป้องกัน Breaking Change ก่อน Deploy
- สร้าง Migration Guide: ทุกครั้งที่ออก Version ใหม่ ต้องมี Guide ที่ละเอียดสำหรับ Consumer
- ใช้ OpenAPI Spec: เอกสาร API ที่เป็น Machine-readable ช่วยให้ Consumer Generate Client Code ได้
- Monitor API Usage: ติดตามว่า Consumer แต่ละคนใช้ Version ไหน ก่อนปิด Version เก่า
- Default Version: กำหนด Default Version สำหรับ Consumer ที่ไม่ระบุ Version
- Document ทุก Breaking Change: เขียน Changelog ที่ชัดเจนสำหรับทุก Version
สรุป
API Versioning เป็นทักษะที่จำเป็นสำหรับ Backend Developer ทุกคนในปี 2026 ไม่ว่าจะเลือกใช้ URL Path, Header หรือ Content Negotiation สิ่งสำคัญที่สุดคือต้องมี Strategy ที่ชัดเจนตั้งแต่แรก มี Deprecation Policy ที่เป็นธรรมกับ Consumer และพยายาม Evolve API ด้วย Additive Changes ให้มากที่สุดก่อนที่จะสร้าง Breaking Change
จากตัวอย่างของ Stripe, GitHub และ Twilio เราเห็นว่าบริษัทชั้นนำให้ความสำคัญกับ Developer Experience อย่างมาก การมี Migration Guide ที่ละเอียด, Sunset Header ที่ชัดเจน และ Deprecation Period ที่ยาวนานเพียงพอ ทำให้ Consumer เชื่อมั่นและยินดีที่จะใช้ API ของคุณต่อไป
สำหรับผู้ที่ต้องการศึกษา Backend Framework เพิ่มเติม แนะนำให้อ่านบทความ Elixir และ Phoenix Framework สำหรับการสร้าง Real-time Web App ที่มีประสิทธิภาพสูง หรือบทความ สอน Git Version Control สำหรับการจัดการ Source Code อย่างเป็นระบบ
