Versioning API untuk aplikasi mobile: kembangkan endpoint dengan aman
Penjelasan versioning API untuk aplikasi mobile dengan rencana rollout sederhana, perubahan kompatibel mundur, dan langkah deprecate agar versi aplikasi lama tetap berfungsi.

Mengapa perubahan API bisa merusak pengalaman pengguna mobile
Aplikasi mobile tidak diperbarui secara bersamaan. Bahkan jika Anda merilis perbaikan hari ini, banyak pengguna akan tetap memakai versi lama selama beberapa hari atau minggu. Beberapa mematikan pembaruan otomatis. Beberapa ruang penyimpanannya penuh. Beberapa jarang membuka aplikasi. Waktu review di app store dan staged release menambah keterlambatan.
Kesenjangan ini penting karena backend biasanya berubah lebih cepat daripada klien mobile. Jika server mengubah endpoint dan aplikasi lama masih memanggilnya, aplikasi bisa rusak meskipun tidak ada yang berubah di ponsel pengguna.
Kerusakan jarang muncul sebagai pesan error yang jelas. Biasanya terlihat sebagai masalah produk sehari-hari:
- Login atau pendaftaran gagal setelah rilis backend
- Daftar terlihat kosong karena field diganti nama atau dipindahkan
- Aplikasi crash saat membaca nilai yang hilang
- Pembayaran gagal karena validasi lebih ketat
- Fitur menghilang diam-diam karena bentuk respons berubah
Tujuan versioning sederhana: terus kirim perbaikan server tanpa memaksa semua orang memperbarui segera. Perlakukan API Anda seperti kontrak jangka panjang. Versi aplikasi baru harus bekerja dengan perilaku server baru, dan versi lama harus tetap bekerja cukup lama untuk siklus pembaruan nyata.
Untuk sebagian besar aplikasi konsumer, harapkan mendukung beberapa versi aplikasi secara bersamaan. Aplikasi internal kadang bisa bergerak lebih cepat, tetapi jarang instan. Merencanakan overlap membuat rollout bertahap lebih tenang daripada mengubah setiap rilis backend menjadi lonjakan dukungan.
Apa arti “kompatibel” untuk kontrak API
Kontrak API adalah janji antara aplikasi mobile dan server Anda: URL yang dipanggil, input yang diterima, bentuk respons, dan arti tiap field. Ketika aplikasi mengandalkan janji itu dan server mengubahnya, pengguna merasakannya sebagai crash, data yang hilang, atau fitur yang berhenti bekerja.
Perubahan kompatibel ketika versi aplikasi lama tetap bisa menggunakan API tanpa perubahan kode. Dalam praktiknya, itu berarti server masih mengerti apa yang dikirim aplikasi lama dan masih mengembalikan respons yang bisa diparse oleh aplikasi lama.
Cara cepat membedakan perubahan yang aman dan berisiko:
- Breaking changes: menghapus atau mengganti nama field, mengubah tipe (angka menjadi string), menjadikan field opsional menjadi wajib, mengubah format error, memperketat validasi sehingga aplikasi lama tidak memenuhi.
- Perubahan yang biasanya aman: menambah field opsional baru, menambah endpoint baru, menerima format request lama dan baru, menambah nilai enum (jika aplikasi menganggap nilai tak dikenal sebagai “lainnya”).
Kompatibilitas juga butuh rencana end-of-life. Menghentikan perilaku lama boleh saja, tetapi harus terjadwal (misalnya, “pertahankan v1 selama 90 hari setelah v2 dirilis”) supaya Anda bisa berkembang tanpa mengejutkan pengguna.
Pendekatan versioning umum dan trade-off
Versioning soal memberi build lama kontrak yang stabil sambil Anda maju. Ada beberapa pendekatan umum, dan masing-masing menaruh kompleksitas di tempat berbeda.
URL versioning
Meletakkan versi di path (mis. /v1/ dan /v2/) paling mudah dilihat dan debug. Ini juga bekerja baik dengan caching, logging, dan routing karena versi menjadi bagian dari URL. Kelemahannya: tim bisa berakhir memelihara handler paralel lebih lama dari perkiraan, meski perbedaannya kecil.
Header-based versioning
Dengan header versioning, klien mengirim versi lewat header (mis. Accept atau header kustom). URL tetap bersih, dan Anda bisa mengembangkan API tanpa mengubah setiap path. Kelemahannya adalah visibilitas: proxy, log, dan manusia sering melewatkan versi kecuali Anda hati-hati, dan klien mobile harus menyetel header pada setiap permintaan.
Query parameter versioning
Query versioning (mis. ?v=2) tampak sederhana, tetapi berantakan. Parameter tersalin ke bookmark, alat analytics, dan script, dan Anda bisa berakhir dengan beberapa “versi” yang tersebar tanpa kepemilikan jelas.
Jika ingin perbandingan singkat:
- URL versioning: paling mudah diperiksa, tapi bisa menciptakan API paralel yang hidup lama
- Header versioning: URL bersih, tapi lebih susah troubleshooting
- Query versioning: cepat dimulai, mudah disalahgunakan
Feature flag adalah alat berbeda. Mereka memungkinkan mengubah perilaku di balik kontrak yang sama (mis. algoritma ranking baru) tanpa membuat versi API baru. Mereka tidak menggantikan versioning ketika bentuk request atau response harus berubah.
Pilih satu pendekatan dan patuhi. Konsistensi lebih penting daripada pilihan “sempurna”.
Aturan praktis untuk perubahan kompatibel mundur
Pola pikir paling aman: klien lama harus tetap bekerja walau mereka tidak pernah tahu fitur baru Anda. Itu biasanya berarti menambah, bukan mengubah yang sudah ada.
Utamakan perubahan aditif: field baru, endpoint baru, parameter opsional baru. Ketika menambah sesuatu, buatlah benar-benar opsional dari sisi server. Jika aplikasi lama tidak mengirimnya, server harus berperilaku seperti sebelumnya.
Beberapa kebiasaan yang mencegah kebanyakan breakage:
- Tambahkan field, tapi jangan ubah tipe atau makna field yang ada.
- Anggap input yang hilang sebagai normal dan gunakan default yang masuk akal.
- Abaikan field request yang tidak dikenal sehingga klien lama dan baru bisa hidup berdampingan.
- Pertahankan format error stabil. Kalau harus mengubahnya, versi payload error.
- Jika perilaku harus berubah, perkenalkan endpoint baru atau versi baru daripada mengubah diam-diam.
Hindari mengubah arti field yang sudah ada tanpa menaikkan versi. Misalnya, jika status=1 dulu berarti “paid” lalu Anda ubah menjadi “authorized”, aplikasi lama akan membuat keputusan yang salah dan Anda mungkin baru tahu ketika pengguna komplain.
Rename dan penghapusan butuh rencana. Pola teraman: pertahankan field lama dan tambah field baru berdampingan untuk sementara. Isi keduanya di respons, terima keduanya di request, dan catat siapa yang masih menggunakan field lama. Hapus field lama hanya setelah jendela deprecate berakhir.
Kebiasaan kecil tapi kuat: ketika memperkenalkan aturan bisnis wajib baru, jangan buat klien bertanggung jawab sejak hari pertama. Terapkan aturan di server dengan default dulu, lalu kemudian minta klien mengirim nilai baru setelah kebanyakan pengguna terbarui.
Tetapkan kebijakan versioning dan deprecate sederhana
Versioning bekerja terbaik ketika aturannya membosankan dan tertulis. Buat kebijakan singkat supaya tim produk, mobile, dan backend benar-benar mengikutinya.
Mulailah dengan jangka dukungan. Tentukan berapa lama Anda akan mempertahankan versi API lama setelah versi baru dirilis (mis. 6–12 bulan), plus pengecualian (isu keamanan, perubahan legal).
Selanjutnya, definisikan bagaimana Anda memperingatkan klien sebelum memutus mereka. Pilih satu sinyal deprecate dan gunakan di mana-mana. Opsi umum termasuk header respons seperti Deprecation: true dengan tanggal pensiun, atau field JSON seperti "deprecation": {"will_stop_working_on": "2026-04-01"} pada respons tertentu. Yang penting konsistensi: klien bisa mendeteksi, dasbor bisa melaporkan, dan tim dukungan bisa menjelaskannya.
Tetapkan versi aplikasi minimum yang didukung, dan jelaskan bagaimana penegakan dilakukan. Hindari pemblokiran mendadak. Pendekatan praktis:
- Kembalikan peringatan lunak (mis. field yang memicu prompt pembaruan di aplikasi).
- Tegakkan hanya setelah tenggat yang dikomunikasikan.
Jika Anda memblokir permintaan, kembalikan payload error yang jelas dengan pesan yang ramah pengguna dan kode yang bisa dibaca mesin.
Terakhir, tentukan siapa yang boleh menyetujui breaking change dan dokumentasi apa yang dibutuhkan. Buat sederhana:
- Satu pemilik menyetujui breaking change.
- Catatan perubahan singkat menjelaskan apa yang berubah, siapa yang terdampak, dan jalur migrasi.
- Rencana tes mencakup setidaknya satu versi aplikasi lama.
- Tanggal pensiun ditetapkan saat deprecate dimulai.
Rencana rollout langkah demi langkah yang menjaga aplikasi lama tetap berfungsi
Pengguna mobile tidak semua memperbarui pada hari pertama. Pendekatan paling aman: kirim API baru sambil membiarkan yang lama tidak berubah, lalu pindahkan lalu lintas secara bertahap.
Pertama, definisikan apa yang berubah di v2 dan kunci perilaku v1. Perlakukan v1 seperti janji: field sama, arti sama, kode error sama. Jika v2 butuh bentuk respons berbeda, jangan ubah v1 untuk menyesuaikannya.
Selanjutnya, jalankan v2 secara paralel. Itu bisa berarti route terpisah (mis. /v1/... dan /v2/...) atau handler terpisah di balik gateway yang sama. Simpan logika bersama di satu tempat, tapi pisahkan kontrak sehingga refactor v2 tidak mengubah v1 secara tidak sengaja.
Kemudian perbarui aplikasi mobile agar memprioritaskan v2. Bangun fallback sederhana: jika v2 mengembalikan “not supported” (atau error yang diketahui), coba ulang ke v1. Ini membantu selama staged release dan saat jaringan nyata berperilaku tidak menentu.
Setelah merilis aplikasi, pantau adopsi dan error. Pemeriksaan berguna meliputi:
- Volume permintaan v1 vs v2 menurut versi aplikasi
- Tingkat error dan latency untuk v2
- Kegagalan parsing respons
- Crash yang terkait layar jaringan
Setelah v2 stabil, tambahkan peringatan deprecate yang jelas untuk v1 dan komunikasikan timeline. Pensiunkan v1 hanya ketika penggunaan turun di bawah ambang yang bisa Anda terima (mis. di bawah 1–2% selama beberapa minggu).
Contoh: Anda mengubah GET /orders untuk mendukung filtering dan status baru. v2 menambah status_details sementara v1 tetap sama. Aplikasi baru memanggil v2, tetapi jika menghadapi edge case, fallback ke v1 sehingga daftar order tetap ditampilkan.
Tips implementasi di sisi server
Kebanyakan kegagalan rollout terjadi karena penanganan versi tersebar di controller, helper, dan kode database. Simpan keputusan “versi apa permintaan ini?” di satu tempat, dan buat sisa logika lebih dapat diprediksi.
Taruh routing versi di balik satu gate
Pilih satu sinyal (segmen URL, header, atau nomor build app) dan normalisasi lebih awal. Route ke handler yang tepat di satu modul atau middleware sehingga setiap permintaan mengikuti jalur yang sama.
Pola praktis:
- Parse versi sekali saja (dan log).
- Petakan versi ke handler (v1, v2, ...) dalam satu registry.
- Jaga utilitas bersama bersifat version-agnostic (parsing tanggal, pengecekan auth), bukan logika bentuk respons.
Hati-hati saat berbagi kode antar versi. Memperbaiki bug v2 di “kode bersama” bisa mengubah perilaku v1 tanpa sengaja. Jika logika memengaruhi field output atau aturan validasi, versi-kan logika itu atau tutupi dengan tes khusus versi.
Pertahankan kompatibilitas perubahan data selama rollout
Migrasi database harus bekerja untuk kedua versi sekaligus. Tambah kolom dulu, backfill bila perlu, dan baru kemudian hapus atau perketat constraint. Hindari mengganti nama atau mengubah makna di tengah rollout. Jika perlu mengubah format, pertimbangkan menulis kedua format untuk sementara sampai kebanyakan klien mobile pindah.
Buat error dapat diprediksi. Aplikasi lama sering menganggap error tak dikenal sebagai “ada yang salah”. Gunakan status code konsisten, identifier error yang stabil, dan pesan singkat yang membantu klien memutuskan tindakan (retry, re-auth, tampilkan prompt update).
Akhirnya, lindungi terhadap field yang hilang yang tidak dikirim aplikasi lama. Pakai default aman dan validasi dengan detail error yang jelas dan stabil.
Pertimbangan sisi mobile yang memengaruhi versioning
Karena pengguna bisa tetap di build lama selama berminggu-minggu, versioning harus mengasumsikan banyak versi klien akan mengakses server secara bersamaan.
Kemenangan besar adalah toleransi di sisi klien. Jika aplikasi crash atau gagal parsing saat server menambahkan field, Anda akan merasakan bug rollout sebagai masalah “acak”.
- Abaikan field JSON yang tidak dikenal.
- Anggap field yang hilang sebagai hal normal dan gunakan default.
- Tangani null dengan aman (field bisa jadi nullable selama migrasi).
- Jangan bergantung pada urutan array kecuali kontrak menjamin itu.
- Jaga penanganan error ramah pengguna (state retry lebih baik daripada layar kosong).
Perilaku jaringan juga penting. Selama rollout Anda bisa sebentar punya versi server campuran di balik load balancer atau cache, dan jaringan mobile memperbesar masalah kecil.
Pilih aturan timeout dan retry yang jelas: timeout singkat untuk panggilan read, sedikit lebih lama untuk upload, dan retry terbatas dengan backoff. Buat idempotensi standar untuk panggilan create atau payment supaya retry tidak menggandakan pengiriman.
Perubahan auth adalah cara tercepat mengunci aplikasi lama. Jika Anda mengubah format token, scope yang dibutuhkan, atau aturan sesi, pertahankan jendela overlap di mana token lama dan baru masih bekerja. Jika harus merotasi kunci atau klaim, rencanakan migrasi bertahap, bukan pemutusan di hari yang sama.
Kirim metadata aplikasi dengan setiap permintaan (mis. versi aplikasi dan platform). Ini memudahkan mengembalikan peringatan terarah tanpa memecah seluruh API.
Monitoring dan rollout bertahap tanpa kejutan
Rollout bertahap hanya bekerja jika Anda bisa melihat apa yang dilakukan tiap versi aplikasi. Tujuan sederhana: tahu siapa yang masih di endpoint lama, dan tangkap masalah sebelum menyebar ke semua orang.
Mulai dengan melacak penggunaan menurut versi API setiap hari. Jangan hanya menghitung total permintaan. Lacak device aktif, dan pecah untuk endpoint penting seperti login, profile, dan payments. Ini memberi tahu apakah versi lama masih “hidup” meski traffic total kecil.
Kemudian pantau error dipisah menurut versi dan tipe. Lonjakan 4xx sering berarti mismatch kontrak (field wajib berubah, nilai enum bergeser, aturan auth diperketat). Lonjakan 5xx biasanya menunjukkan regresi server (deploy buruk, query lambat, dependency gagal). Melihat keduanya per versi membantu memilih perbaikan yang tepat dengan cepat.
Gunakan staged rollout di app store untuk membatasi blast radius. Tingkatkan eksposur bertahap dan pantau dasbor yang sama setelah tiap langkah (mis. 5%, 25%, 50%). Jika versi terbaru bermasalah, hentikan rollout sebelum menjadi outage penuh.
Tulis trigger rollback terlebih dahulu, bukan memutuskan saat insiden. Trigger umum termasuk:
- tingkat error melewati ambang tetap selama 15–30 menit
- tingkat sukses login turun (atau kegagalan refresh token naik)
- naiknya kegagalan pembayaran (atau timeout checkout meningkat)
- lonjakan tiket dukungan terkait versi tertentu
- peningkatan latency pada endpoint kritis
Simpan playbook insiden singkat untuk outage terkait versi: siapa yang dipanggil, bagaimana menonaktifkan flag berisiko, rilis server mana yang di-rollback, dan bagaimana memperpanjang jendela deprecate jika klien lama masih aktif.
Contoh: mengembangkan endpoint saat rilis nyata
Checkout adalah perubahan nyata klasik. Anda mulai dengan alur sederhana, lalu menambah langkah pembayaran baru (mis. otentikasi yang lebih kuat) dan mengganti nama field agar sesuai istilah bisnis.
Misalnya aplikasi Anda memanggil POST /checkout.
Apa yang tetap di v1 vs apa yang berubah di v2
Di v1, pertahankan request dan perilaku yang ada agar versi aplikasi lama bisa menyelesaikan pembayaran tanpa kejutan. Di v2, perkenalkan alur baru dan nama yang lebih rapi.
- v1 tetap:
amount,currency,card_token, dan respons tunggal sepertistatus=paid|failed. - v2 menambah:
payment_method_id(menggantikancard_token) dan fieldnext_actionsupaya aplikasi bisa menangani langkah tambahan (verify, retry, redirect). - v2 mengganti nama:
amountmenjaditotal_amountdancurrencymenjadibilling_currency.
Aplikasi lama tetap bekerja karena server menerapkan default aman. Jika request v1 tidak mengenal next_action, server menyelesaikan pembayaran bila memungkinkan dan mengembalikan hasil gaya v1. Jika langkah baru wajib, v1 mendapat kode error yang jelas dan stabil seperti requires_update daripada kegagalan generik yang membingungkan.
Adopsi, pensiun, dan rollback
Lacak adopsi menurut versi: proporsi panggilan checkout yang menuju v2, tingkat error, dan berapa banyak pengguna masih menggunakan build yang hanya mendukung v1. Ketika penggunaan v2 konsisten tinggi (mis. 95%+ selama beberapa minggu) dan penggunaan v1 rendah, tetapkan tanggal pensiun v1 dan komunikasikan (catatan rilis, pesan in-app).
Jika terjadi masalah setelah peluncuran, rollback harus membosankan:
- Arahkan lebih banyak lalu lintas kembali ke perilaku v1.
- Nonaktifkan langkah pembayaran baru dengan flag di server.
- Terus terima kedua set field, dan log konversi yang Anda lakukan.
Kesalahan umum yang menyebabkan breakage diam-diam
Kebanyakan kegagalan API mobile tidak berisik. Permintaan sukses, aplikasi tetap berjalan, tapi pengguna melihat data hilang, total salah, atau tombol yang tidak berfungsi. Masalah ini sulit dideteksi karena sering mengenai versi aplikasi lama selama rollout bertahap.
Penyebab umum:
- Mengubah atau menghapus field (atau tipenya) tanpa rencana versi yang jelas.
- Menjadikan field request baru wajib segera, sehingga aplikasi lama mulai ditolak.
- Mengirim migrasi database yang mengasumsikan hanya ada aplikasi baru.
- Mencabut v1 berdasar instalasi, bukan penggunaan aktif.
- Lupa background job dan webhook yang masih mengirim payload lama.
Contoh konkret: field respons total tadinya string ("12.50") lalu diubah menjadi number (12.5). Aplikasi baru baik-baik saja. Aplikasi lama mungkin menganggapnya nol, menyembunyikannya, atau crash di layar tertentu. Kecuali Anda memantau error klien menurut versi aplikasi, ini bisa lolos.
Daftar periksa cepat dan langkah selanjutnya
Versioning lebih sedikit soal penamaan endpoint yang cerdik dan lebih soal mengulang pemeriksaan keselamatan yang sama setiap rilis.
Pemeriksaan cepat sebelum rilis
- Pertahankan perubahan aditif. Jangan hapus atau ganti nama field yang dibaca aplikasi lama.
- Sediakan default aman sehingga field baru yang hilang berperilaku seperti alur lama.
- Pertahankan respons error stabil (status + bentuk + makna).
- Perlakukan enum dengan hati-hati dan jangan ubah arti nilai yang ada.
- Putar ulang beberapa request nyata dari versi aplikasi lama dan pastikan respons masih bisa diparse.
Pemeriksaan cepat selama rollout dan sebelum pensiun
- Lacak adopsi menurut versi aplikasi. Anda ingin kurva yang jelas dari v1 ke v2, bukan garis datar.
- Pantau tingkat error menurut versi. Lonjakan sering berarti parsing atau validasi merusak klien lama.
- Perbaiki endpoint yang paling sering gagal dulu, lalu perluas rollout.
- Pensiunkan hanya saat penggunaan aktif benar-benar rendah, dan komunikasikan tanggalnya.
- Hapus kode fallback terakhir, setelah jendela pensiun berakhir.
Tulis kebijakan versioning dan deprecate Anda dalam satu halaman, lalu ubah daftar periksa menjadi gate rilis yang tim Anda ikuti setiap kali.
Jika Anda membangun alat internal atau aplikasi pelanggan dengan platform no-code, tetap berguna untuk memperlakukan API sebagai kontrak dengan jendela deprecate yang jelas. Untuk tim yang menggunakan AppMaster (appmaster.io), menjaga v1 dan v2 berdampingan sering lebih mudah karena Anda bisa menghasilkan backend dan klien saat kebutuhan berubah sambil mempertahankan kontrak lama selama rollout.
FAQ
Pengguna mobile tidak semuanya memperbarui aplikasi pada waktu yang sama, jadi build aplikasi lama terus memanggil backend Anda setelah Anda menerapkan perubahan. Jika Anda mengubah endpoint, validasi, atau bentuk respons, build lama tidak bisa menyesuaikan dan akan gagal dengan cara yang terlihat sebagai layar kosong, crash, atau pembayaran yang tidak berhasil.
“Kompatibel” berarti aplikasi lama tetap bisa mengirimkan permintaan yang sama dan mendapat respons yang bisa diparse dan digunakan dengan benar, tanpa perubahan kode. Pola pikir yang aman adalah menganggap API sebagai kontrak: Anda boleh menambah kemampuan baru, tapi jangan mengubah arti atau perilaku field yang sudah ada bagi klien saat ini.
Perubahan dianggap breaking ketika mengubah sesuatu yang menjadi ketergantungan aplikasi lama—misalnya menghapus atau mengganti nama field, mengubah tipe field, memperketat validasi sehingga permintaan lama gagal, atau mengubah format payload error. Jika aplikasi lama tidak dapat memparse respons atau tidak memenuhi aturan permintaan, itu adalah breaking walau server terlihat “berfungsi”.
URL versioning biasanya menjadi default termudah karena versi terlihat jelas di log, alat debugging, dan routing—sulit untuk lupa mengirimnya. Header-based versioning juga bisa bekerja, tetapi lebih mudah terlewat saat troubleshooting dan setiap permintaan klien harus menyertakan header itu dengan benar.
Pilih jangka dukungan yang sesuai dengan perilaku pembaruan aplikasi mobile nyata, lalu patuhi itu; banyak tim memilih berbulan-bulan, bukan hari. Intinya adalah menetapkan tanggal pensiun yang dipublikasikan dan mengukur penggunaan aktif agar Anda tidak menebak kapan aman mematikan versi lama.
Gunakan satu sinyal deprecate yang konsisten agar klien dan dasbor dapat mendeteksinya dengan andal, misalnya header respons yang stabil atau field JSON kecil yang berisi tanggal pensiun. Buat sederhana dan dapat diprediksi sehingga tim dukungan dan produk bisa menjelaskannya tanpa menggali implementasi.
Utamakan perubahan yang bersifat aditif: tambahkan field opsional baru atau endpoint baru, dan biarkan field lama tetap berfungsi dengan arti yang sama. Saat perlu mengganti nama, jalankan kedua field berdampingan untuk sementara dan isi keduanya sehingga aplikasi lama tidak kehilangan data sementara aplikasi baru berpindah ke field baru.
Rancang migrasi sehingga kedua versi API bisa beroperasi bersamaan: tambahkan kolom terlebih dahulu, lakukan backfill bila perlu, dan baru kemudian perketat constraint atau hapus field lama. Hindari mengganti nama atau mengubah makna data di tengah rollout karena satu versi aplikasi bisa menulis data yang tidak bisa dibaca versi lain.
Buat aplikasi lebih toleran: abaikan field JSON yang tidak dikenal, anggap field yang hilang sebagai hal normal dengan default yang aman, dan tangani null tanpa crash. Ini mengurangi bug “acak” saat server menambahkan field atau saat respons bervariasi selama staged deploys.
Lacak penggunaan dan error berdasarkan versi API dan versi aplikasi, terutama pada login dan pembayaran, dan perlebar staged rollout hanya ketika data stabil. Rencana rollout yang aman mengunci perilaku v1, menjalankan v2 secara paralel, dan memindahkan klien secara bertahap dengan strategi fallback yang jelas sampai adopsi cukup tinggi untuk mengakhiri v1 dengan percaya diri.


