Semua bab sebelumnya berdiri di atas satu asumsi tersirat: deployment berhasil dan model baru memang lebih baik. Bab ini membahas saat asumsi itu gagal — model versi baru di-deploy, metrik produksi merosot, dan setiap menit berarti keputusan yang salah terus dibuat. Kemampuan membatalkan rilis dengan cepat dan terkendali bukan tanda kegagalan tim; ia adalah ukuran kematangan operasional. Pete Hodgson, praktisi continuous delivery, merangkumnya dalam satu kalimat yang sering dikutip: tim yang baik bukan yang tidak pernah gagal, melainkan yang bisa membatalkan kegagalannya dalam hitungan menit. Chapter penutup section ini mensimulasikan siklus lengkap update — deploy, deteksi, rollback — lalu merangkum keseluruhan MLOps.

Strategi Update #

StrategiCara kerjaSaat cocok
big-bangversi baru langsung melayani seluruh trafficperubahan kecil, risiko rendah, sistem non-kritis
gradual (canary/berperingkat)versi baru diuji pada sebagian traffic duluperubahan perilaku signifikan, pengguna banyak
rollback siapversi lama tetap termuat; alihkan rute saat bermasalahprasyarat kedua strategi di atas

Pembahasan lengkap jalur bertahap ada di chapter Continuous Deployment . Di sini fokusnya adalah sisi yang jarang dibahas: apa yang membuat rollback cepat. Jawabannya satu frasa — warm standby: versi lama tetap termuat di memori (atau siap dimuat dalam hitungan detik), sehingga rollback hanya mengubah rute traffic, bukan memuat ulang model. Kontras dengan cold standby: berkas versi lama ada di penyimpanan tetapi tidak termuat — rollback berarti menunggu proses memuat, validasi, dan pemanasan ulang, dan selama itu sistem terus melayani dengan model yang bermasalah.

Alur keputusan pasca-deploy membentuk lingkar berikut:

Data Migration dan Komunikasi #

Rollback model jarang berdiri sendiri. Dua hal biasanya ikut dipertaruhkan. Pertama, data migration: bila v2 menyimpan prediksi dengan skema baru atau format output berbeda, rollback ke v1 bisa menemukan data yang tidak lagi cocok skema pembacanya. Praktik amannya dua arah: skema baru harus kompatibel mundur (v1 membaca tetapi mengabaikan field baru), dan data selama masa v2 disimpan sedemikian rupa agar bisa dibaca ulang. Kedua, komunikasi perubahan: pengguna internal dan eksternal perlu tahu bahwa perilaku sistem berubah — dan saat rollback terjadi, bahwa ia berubah kembali. Catatan perubahan (changelog) per versi dan notifikasi pemangku kepentingan adalah bagian operasional yang sama pentingnya dengan kode.

Contoh Teruji: Update dengan Rollback Otomatis #

Berkas update_rollback.py menyiapkan v1 yang sehat dan v2 yang dilatih pada data bergeser. v2 di-deploy penuh, monitoring mengukur akurasi nyata per jendela pada arus data produksi, dan dua pelanggaran berturut-turut memicu rollback otomatis ke v1 yang tetap termuat:

python
"""Simulasi update model dengan rollback otomatis.

v2 dilatih pada data yang bergeser dan di-deploy menggantikan v1.
Monitoring per jendela mengukur akurasi nyata dari prediksi v2 pada
arus data produksi. Dua jendela berturut-turut di bawah ambang
memicu rollback otomatis ke v1 yang tetap siap sebagai warm standby.
"""

import numpy as np

AMBANG_AKURASI = 0.85
PELANGGARAN_PERLU = 2
N_PER_JENDELA = 300


def buat_data(seed, geser=0.0):
    """Dua gumpalan Gaussian; geser memindahkan distribusi data latih."""
    rng = np.random.default_rng(seed)
    kelas0 = rng.normal(loc=[-1.0 + geser, 0.0], scale=0.7, size=(120, 2))
    kelas1 = rng.normal(loc=[1.0 + geser, 0.4], scale=0.7, size=(120, 2))
    X = np.vstack([kelas0, kelas1])
    y = np.array([0] * 120 + [1] * 120)
    urut = rng.permutation(len(y))
    return X[urut], y[urut]


def latih(X, y, epoch=300):
    w = np.zeros(3)
    for _ in range(epoch):
        skor = np.clip(X @ w[1:] + w[0], -30, 30)
        p = 1.0 / (1.0 + np.exp(-skor))
        galat = p - y
        w[1:] -= (X.T @ galat) / len(y)
        w[0] -= galat.mean()
    return w


def akurasi(w, X, y):
    return float((((X @ w[1:] + w[0] >= 0).astype(int)) == y).mean())


def main():
    # arus data produksi: distribusi seperti saat v1 dilatih
    X_prod, y_prod = buat_data(seed=99)
    # v1: data normal; v2: data latih bergeser (update yang buruk)
    v1 = latih(*buat_data(seed=42), epoch=300)
    v2 = latih(*buat_data(seed=44, geser=1.5), epoch=300)

    print("== pra-deploy: evaluasi kedua versi ==")
    print(f"  v1 akurasi pada data produksi : {akurasi(v1, X_prod, y_prod):.3f}")
    print(f"  v2 akurasi pada data produksi : {akurasi(v2, X_prod, y_prod):.3f}")
    print(f"  ambang rollback               : {AMBANG_AKURASI}")
    print("  v2 di-deploy penuh; v1 tetap dimuat (warm standby)\n")

    rng = np.random.default_rng(7)
    model_aktif, nama_aktif = v2, "v2"
    pelanggaran = 0
    print("== monitoring pasca-deploy ==")
    for t in range(1, 6):
        idx = rng.choice(len(y_prod), size=N_PER_JENDELA, replace=True)
        ak = akurasi(model_aktif, X_prod[idx], y_prod[idx])
        if ak >= AMBANG_AKURASI:
            pelanggaran = 0
            print(f"  jendela {t} [{nama_aktif}]: akurasi {ak:.3f} — OK")
        else:
            pelanggaran += 1
            print(f"  jendela {t} [{nama_aktif}]: akurasi {ak:.3f} — "
                  f"DI BAWAH AMBANG (pelanggaran {pelanggaran})")
            if (pelanggaran >= PELANGGARAN_PERLU
                    and model_aktif is v2):
                model_aktif, nama_aktif = v1, "v1"
                pelanggaran = 0
                print(f"    -> ROLLBACK OTOMATIS: traffic dialihkan ke v1 "
                      f"(warm standby, tanpa pelatihan ulang)")

    print("\n== status akhir ==")
    print(f"model aktif : {nama_aktif}")
    print(f"v2 dicabut dari serving; penyebabnya perlu diperiksa "
          "sebelum update berikutnya")


if __name__ == "__main__":
    main()

Output yang Dihasilkan:

text
== pra-deploy: evaluasi kedua versi ==
  v1 akurasi pada data produksi : 0.921
  v2 akurasi pada data produksi : 0.629
  ambang rollback               : 0.85
  v2 di-deploy penuh; v1 tetap dimuat (warm standby)

== monitoring pasca-deploy ==
  jendela 1 [v2]: akurasi 0.647 — DI BAWAH AMBANG (pelanggaran 1)
  jendela 2 [v2]: akurasi 0.640 — DI BAWAH AMBANG (pelanggaran 2)
    -> ROLLBACK OTOMATIS: traffic dialihkan ke v1 (warm standby, tanpa pelatihan ulang)
  jendela 3 [v1]: akurasi 0.917 — OK
  jendela 4 [v1]: akurasi 0.937 — OK
  jendela 5 [v1]: akurasi 0.903 — OK

== status akhir ==
model aktif : v1
v2 dicabut dari serving; penyebabnya perlu diperiksa sebelum update berikutnya

Mari kita telaah kode di atas baris per baris:

  1. Baris 44-47 (v1 dan v2): kedua model dilatih dan keduanya tetap di memori — v1 sebagai warm standby, v2 sebagai kandidat. Baris inilah perbedaan teknis konkret antara warm dan cold standby: tidak ada pemanggilan muat_versi di tengah insiden.
  2. Baris 49-53 (pra-deploy): kedua versi dievaluasi pada data produksi sebelum deploy. Angka v2 (0.629) sebenarnya sudah memberi peringatan — dalam praktik, angka seperti ini menahan v2 di gerbang registry dari chapter Model Registry dan deployment tidak boleh terjadi; simulasi ini sengaja meloloskannya untuk memperlihatkan jalur pemulihan.
  3. Baris 59-61 (monitoring): setiap jendela mengambil 300 sampel dari arus produksi dengan rng.choice(replace=True) — request nyata bisa berulang, jadi sampling dengan pengembalian lebih mirip kenyataan. Akurasi dihitung dari prediksi model yang sedang aktif.
  4. Baris 62-75 (keputusan per jendela): pelanggaran dihitung beruntun; dua pelanggaran berturut-turut pada v2 memicu pengalihan model_aktif ke v1 — satu baris penugasan, karena v1 sudah termuat. Jendela 3-5 setelahnya dievaluasi dengan v1 dan kembali sehat: 0.917, 0.937, 0.903.
  5. Baris 76-79 (status akhir): penutup mencatat v2 dicabut dan penyebabnya perlu diperiksa — rollback memulihkan layanan, tetapi tidak menghapus kewajiban memahami kegagalan. Data latih v2 yang bergeser (masalah drift dari chapter Data dan Model Drift ) tetap harus ditelusuri sebelum update berikutnya.

Kronologi keluaran memperlihatkan bentuk kurva insiden yang sehat: dua jendela bermasalah (0.647, 0.640), rollback, lalu pemulihan. Total jendela waktu pengguna menerima prediksi buruk: dua dari lima — dan pada sistem nyata dengan ambang serta monitoring yang sama, angka itu adalah selisih antara insiden sepuluh menit dan insiden semalam.

Sintesis: Siklus MLOps #

Sepuluh chapter section ini kini membentuk satu lingkaran utuh. Experiment Management mencatat setiap percobaan; Model Versioning memberi artifact identitas permanen; Model Registry menjadi sumber kebenaran status versi; Pipeline Training Otomatis menjalankan semuanya tanpa menunggu manusia; Continuous Integration menguji setiap perubahan; Continuous Deployment merilisnya dengan eksposur terkendali; Data dan Model Drift dan Monitoring Kinerja Model mengawasi dunia yang terus berubah; Reproducibility dan Audit menjaga jejak yang bisa diverifikasi; dan rollback menutup lingkaran dengan jaminan bahwa kegagalan bisa dibatalkan cepat. Model produksi yang dikelola siklus ini bukan lagi artefak sekali jadi — ia menjadi sistem yang terus belajar, terukur, dan bisa dipulihkan.

Dengan fondasi operasional selesai, Course bergerak ke wilayah yang semakin menekan: keamanan, etika, dan keandalan — tempat model berhadapan dengan penyalahgunaan, privasi, dan konsekuensi sosial dari keputusannya.