API Versioning — API

API Versioning memastikan perubahan API tidak merusak client yang sudah ada. Strategi versioning: 1. URL Versioning (paling populer): GET /api/v1/users GET…

API versioning adalah cara mengubah API tanpa merusak client yang sudah memakainya. Bayangin toko yang ganti nomor telepon. Toko yang baik gak langsung mematikan nomor lama. Nomor lama tetap aktif beberapa bulan dengan pesan "nomor ini berhenti 1 April, simpan nomor baru", baru setelah itu dimatikan. Sebaliknya, menambah nomor WhatsApp gak mengganggu siapa pun: yang lama tetap jalan.

🧪 Tebakan cepat: di satu rilis, kamu menambah field currency: "IDR" ke jawaban GET /books/1, dan mengganti price dari angka 89000 jadi teks "89000". Mana yang merusak aplikasi lama? Tebak dulu, jawabannya ada di bagian "Breaking change atau aman?".

Breaking change atau aman?

Aplikasi Toko Buku versi lama sudah terpasang di ribuan HP dan gak bisa kamu ubah. Kodenya ditulis untuk jawaban v1 {"id": 1, "title": "Laskar Pelangi", "author_id": 1, "price": 89000, "stock": 12}:

function renderBook(book) {
  const harga = "Rp " + book.price.toLocaleString("id-ID");
  const total = book.price + 10000; // + ongkir
  const status = book.stock > 0 ? "tersedia" : "habis";
  return book.title + " | " + harga + " | total " + total + " | " + status;
}

Dengan v1, hasilnya Laskar Pelangi | Rp 89.000 | total 99000 | tersedia. Sekarang jalankan kode yang sama pada jawaban yang sudah diubah:

Perubahan Hasil di aplikasi lama Jenis
tambah "currency": "IDR" Laskar Pelangi | Rp 89.000 | total 99000 | tersedia aman
price jadi "89000" Laskar Pelangi | Rp 89000 | total 8900010000 | tersedia breaking
title diganti name undefined | Rp 89.000 | total 99000 | tersedia breaking
stock diganti in_stock: true Laskar Pelangi | Rp 89.000 | total 99000 | habis breaking
POST /books wajib isbn request lama dijawab 422 breaking

Menambah currency aman, karena kode lama gak pernah membacanya. Mengganti price jadi teks yang merusak: "89000" + 10000 di JavaScript menyambung teks jadi "8900010000". Itu jawaban tebakannya.

Aturannya:

Breaking change gak boleh dirilis di versi yang sama. Ia butuh versi baru.

Tiga cara menulis versi

Cara Request client v2 Catatan
URL GET /v2/books/1 paling populer: jelas, gampang di-cache dan di-route, bisa dicoba di browser
Header GET /books/1 + Api-Version: 2 URL tetap bersih; jawabannya wajib Vary: Api-Version supaya cache gak tertukar
Media type GET /books/1 + Accept: application/vnd.tokobuku.v2+json versi menempel di format; perlu Vary: Accept

Query parameter (/books/1?version=2) juga dipakai, tapi gampang terlupa. Untuk header dan media type, client yang gak mengirim versi harus tetap dapat v1, karena aplikasi lama gak tahu header itu.

v1 dan v2 berdampingan

Versi lama tetap dijawab persis seperti dulu, dan bentuk baru tinggal di versi baru:

app.get("/v1/books/:id", (req, res) => {
  const book = books.find((b) => b.id === Number(req.params.id));
  res.json({ id: book.id, title: book.title, author_id: book.author_id, price: book.price, stock: book.stock });
});

app.get("/v2/books/:id", (req, res) => {
  const book = books.find((b) => b.id === Number(req.params.id));
  res.json({ id: book.id, name: book.title, author_id: book.author_id, price: book.price, in_stock: book.stock > 0 });
});

Latihan memakai pola yang sama untuk users. v1 menjawab [{"name": "Budi"}], v2 membungkus data dan mengganti nama field-nya:

app.get("/api/v1/users", (req, res) => {
  res.json([{ name: "Budi" }]);
});

app.get("/api/v2/users", (req, res) => {
  res.json({ data: [{ full_name: "Budi", registered: true }], version: 2 });
});

Mengumumkan pensiun: Deprecation dan Sunset

Versi lama gak hidup selamanya, tapi dimatikan dengan pemberitahuan. Jawaban v1 mulai membawa header:

HTTP/1.1 200 OK
Content-Type: application/json
Deprecation: @1790812800
Sunset: Thu, 01 Apr 2027 00:00:00 GMT
Link: <https://api.tokobuku.test/docs/migrasi-v2>; rel="deprecation"

Urutannya: umumkan jauh-jauh hari (6 sampai 12 bulan), pasang header-nya, tulis panduan migrasi, pantau siapa yang masih memanggil v1, lalu matikan setelah tanggal Sunset (misalnya menjawab 410 Gone).

🤔 Nomor versi: semantic versioning

Nomor seperti v2.3.1 dibaca MAJOR.MINOR.PATCH:

URL API biasanya cuma membawa major (/v2), karena minor dan patch gak merusak siapa pun.

⚠️ Jebakan yang sering ketemu

TL;DR: Perubahan yang aman: menambah field, endpoint, atau parameter opsional. Breaking change: menghapus atau mengganti nama field, mengubah tipenya, mewajibkan input baru; itu butuh versi baru. Versi ditulis di URL (/v1/books, paling populer), di header (Api-Version: 2, plus Vary), atau di media type (Accept: application/vnd.tokobuku.v2+json), dan request tanpa versi tetap v1. v1 dan v2 berjalan berdampingan dari data yang sama. Versi lama dipensiunkan dengan Deprecation, Sunset, dan panduan migrasi. Di v2.3.1, 2 adalah major version, yang naik saat ada breaking change.

Yang akan kamu pelajari