Cloudflare mengumumkan K2 dalam public beta sebagai primitive baru di Developer Platform: durable event streaming yang menyimpan event sebagai log terurut di atas object storage R2. Cara kerjanya sederhana di permukaan. Producer mengirim batch event ke sebuah stream, K2 menyimpannya, lalu konsumen boleh membaca dengan ritme masing-masing, entah dibagi antar beberapa konsumen atau dikirim penuh ke semua konsumen. Yang menarik justru konsekuensi teknis dari keputusan membangun log di atas object storage, karena keputusan itu menentukan latensi, retensi, dan harga.
Masalah Inti: Producer dan Consumer Harus Seirama
Arsitektur RPC konvensional punya satu beban struktural. Producer dan konsumen harus cocok dalam dua dimensi sekaligus, skala dan waktu. Kalau producer mengirim data lebih cepat dari kemampuan konsumen memproses, event jatuh. Kalau konsumen atau layanan downstream sedang mati, event juga jatuh. Situasi memburuk ketika beberapa konsumen butuh data yang sama secara independen, karena setiap tambahan konsumen berarti tambahan mekanik distribusi.
solusi klasiknya adalah menyisipkan layanan di tengah yang menyerap tulis dan membiarkan banyak pembaca mengonsumsi sendiri. Di titik ini sebagian besar tim akan memasang Apache Kafka. Cloudflare memilih jalur lain, dan alasannya spesifik pada bentuk infrastruktur mereka.
Kenapa Bukan Kafka di Edge
Jaringan Cloudflare membentang di lebih dari 335 kota. Untuk layanan stateful, kondisi lapangan-nya tidak ramah ke perangkat lunak distributed klasik. Setiap mesin hanya dipotong dalam slice kecil, slice itu relatif fana, dan komunikasi antar node sering melewati internet publik. Sistem seperti Kafka dirancang untuk sekumpulan node yang stabil dengan jaringan cepat dan dapat diandalkan, bukan untuk topologi seperti itu.
Sebaliknya, ada dua hal yang justru melimpah di infrastruktur Cloudflare: kedekatan dengan user dan satu primitif state yang sudah kuat, yaitu R2. Di sinilah desain K2 mengunci arah, dan keputusan itu punya konsekuensi yang harus dipahami sebelum seseorang memakainya di produksi.
Log di Atas Object Storage: Append Tidak Ada
R2, seperti object store lain, tidak mendukung append, padahal append adalah operasi paling standar pada sebuah log. Karena itu K2 menulis file utuh yang disebut segment, cukup besar untuk menutupi biaya tulis dan baca tiap objek. Tulis pertama diakumulasi dulu di memori pada layanan edge, lalu digulung menjadi segment.
Dampaknya langsung terasa dan dinyatakan jujur di pengumuman resminya. Menulis ke object storage lebih lambat daripada ke disk lokal, dan sistem harus menunggu batch terkumpul sebelum menulis. Di rilis awal, ini menghasilkan latensi produce sekitar satu detik pada persentil 99. Angka itu bukan bug, melainkan harga dari desain yang memilih durability dan skala storage.
Sebagai ganti, K2 mewarisi dua hal dari R2. Pertama, durabilitas penyimpanan yang disebut mencapai 11 angka sembilan. Kedua, API yang strongly consistent. Dengan replikasi dan konsensus dilempar ke lapisan storage, lapisan aplikasi menjadi jauh lebih sederhana. Untuk tim yang dulu mengoperasikan Kafka cluster, penyederhanaan ini biasanya berarti pengurangan pekerjaan operasional yang nyata.
Retensi Panjang sebagai Fitur, Bukan Sampah Menumpuk
Karena log bertumpu pada object storage, menyimpan event lebih lama tidak lagi mahal secara proporsional. Stream contoh pada pengumuman dibuat dengan nilai retention_seconds 604800, yang berarti 7 hari. Retensi panjang membuka opsi yang sebelumnya tidak ekonomis: replay ulang untuk processing baru, audit trail, dan fan-out ke banyak konsumen tanpa producer harus mengirim dua kali.
API: Stream, Subscription, dan Kontrak Ack
Stream bisa dibuat lewat CLI cf, Wrangler, dashboard, atau API. Perintahnya seperti ini.
cf k2 streams create --name app_events --http-enabled
Responsnya berisi id, nama, retensi, endpoint dengan bentuk https://id.k2.cloudflarestorage.com, status HTTP beserta flag authentication, dan status worker_binding. Untuk pengiriman dari dalam Worker, binding dipakai seperti objek biasa.
const result = await env.EVENTS.send([{ content: new TextEncoder().encode(JSON.stringify({ event: "page_view", timestamp: Date.now() })), headers: { "content-type": "application/json" } }]);
Yang penting dicermati adalah bentuk hasilnya. Kalau result.success bernilai false, ada result.error.retryable yang menentukan apakah pengirim sebaiknya mengembalikan status 502 dan meminta pengiriman ulang, atau menyerah. Ini kontrak eksplisit, bukan tebakan.
Untuk pembacaan, konsepnya adalah subscription. Satu subscription membagi pekerjaan antar konsumen, sehingga baca bisa paralel dan menandingi beban yang tidak sanggup ditanggung satu server. Pembuatan subscription lewat HTTP API mengirim nama dan titik mulai, misalnya tipe earliest. Setelah itu konsumen menarik batch.
curl -X POST "https://id.k2.cloudflarestorage.com/subscriptions/id/consume" -H "Authorization: Bearer token" --data '{ "worker_id": "analytics-1", "max_records": 100 }'
Respons consume berisi batch_id, leased_until_ms, dan daftar record. Di sini ada tiga aksi yang menentukan nasib batch. Ack menandai batch sudah diproses dan tidak akan dikirim ulang. Nack berarti gagal diproses dan minta dikirim lagi. Extend lease dipakai saat konsumen butuh waktu tambahan sebelum batas lease habis.
K2, Queues, dan Basin Pipelines: Batas Pemilihannya
Ketiganya terlihat mirip karena sama-sama menerima event, menyimpannya secara durable, lalu mengirim ke konsumen. Bedanya ada pada granularitas dan tujuan.
| Primitif | Dibuat untuk | Unit kerja | Catatan |
|---|---|---|---|
| Queues | Satu item pekerjaan mahal atau lama yang harus selesai asinkron | Pesan tunggal | Retry per pesan, cocok untuk antrean kerja individual seperti request pemrosesan gambar |
| K2 | Perpindahan data skala besar, retensi panjang, fan-out | Batch | Produksi dan konsumsi batch, efisien tapi tanpa retry tingkat pesan dan latensi producer lebih tinggi |
| Basin Pipelines | Ingesti event yang hasilnya ditulis ke object storage atau tabel Iceberg | Event JSON | Pilih K2 kalau butuh pemrosesan custom atau tujuan tulis lain |
Pola seleksi paling praktisnya begini. Kalau konsumen perlu tahu bahwa satu tugas spesifik gagal dan perlu diulang sendiri, Queues. Kalau yang bergerak adalah aliran event besar yang dibaca banyak pipeline berbeda, K2.
Beta, Batas, dan Antisipasi Harga
K2 hari ini tersedia untuk akun dengan langganan Workers Paid, dengan batas beta berupa maksimal 10GB storage terpakai dan 30 MB/s produce per stream. Tim menyatakan bisa minta kenaikan batas lewat Discord atau formulir. Selama beta, pemakaian tidak ditagih.
Untuk fase berbayar, harga yang diantisipasi diumumkan terang-terangan dan semuanya berbasis volume data, bukan per request.
| Komponen | Antisipasi harga |
|---|---|
| Data Produced | 0,04 dolar per GB |
| Data Consumed | 0,04 dolar per GB |
| Data Retained | 0,02 dolar per GB per bulan |
Model harga ini penting untuk perhitungan arsitektur. Konsumen yang menarik data berkali-kali akan dikenai biaya consume tiap tarikan, jadi desain fan-out harus sadar bahwa membaca ulang bukan gratis. Sebaliknya, menumpuk data yang tidak dibaca hanya kena 0,02 dolar per GB per bulan, dan itu relatif murah dibanding biaya compute.
Roadmap yang Layak Dipantau
Pengumuman menyebut beberapa arah berikutnya: paralelisme tulis lebih tinggi sampai stream multi-GB per detik, message keys dengan jaminan urutan berbasis key, konsumen Worker berbasis push, tier Express dengan latensi produce dan end-to-end lebih rendah, serta dukungan drop-in untuk klien Apache Kafka.
Bullet terakhir itu yang paling menentukan adopsi. Kalau klien Kafka bisa diarahkan ke K2 tanpa rewrite, migrasi menjadi soal konfigurasi, bukan proyek. Untuk tim yang ingin keluar dari kebiasaan mengoperasikan cluster Kafka tapi tidak mau menulis ulang consumer, roadmap ini alasan yang cukup untuk menunggu satu rilis lagi.
Kapan Arsitektur Ini Masuk Akal
K2 cocok untuk event aplikasi, telemetri, audit log, analytic ingestion, dan buffer untuk pipeline stream processing. Tiga syarat sebelum memakainya sebaiknya dijawab lebih dulu. Pertama, apakah latensi produce satu detik di p99 bisa diterima, karena kasus use seperti sinkronisasi data realtime dalam transaksi masih belum masuk. Kedua, apakah konsumen sudah dirancang batch-oriented, karena model ack per batch tidak ramah untuk pekerjaan satu-satu yang harus retry sendiri. Ketiga, apakah workers Paid sudah dipakai, karena beta masih menutup akses untuk paket di bawahnya.
Bagus juga membandingkan dengan solusi yang lebih dekat ke database. Untuk aplikasi kecil yang butuh broadcast event antar komponen, mekanisme LISTEN dan NOTIFY di PostgreSQL atau cache seperti Redis sering lebih murah dan lebih cepat, meski skalanya terbatas. Artikel tentang event streaming realtime dengan LISTEN dan NOTIFY PostgreSQL membahas jalur ringan itu, dan tulisan mengenai Redis sebagai antrean dan strukturnya menjelaskan batas-batas yang biasanya muncul saat data mulai menumpuk.
Pelajaran Desain yang Lebih Besar
K2 adalah contoh baik soal memilih primitif penyimpanan sebagai fondasi, lalu memindahkan kompleksitas ke lapisan yang sudah solved. Cloudflare tidak mencoba bikin konsensus baru di edge. Mereka meminjam consistency dan durability dari R2, lalu membayar dengan latensi write. Trade-off itu diumumkan, tidak disembunyikan, dan itu yang membuat pengumuman teknis ini bisa dipakai untuk mengambil keputusan.
Untuk developer Indonesia, sinyal yang lebih relevan bukan K2 sendiri, tapi arah industrinya. Buffer data durable makin bergeser jadi layanan yang disewa per GB, bukan kluster yang dioperasikan sendiri. Selama model harganya berbasis volume dan API-nya batch, beban ada pada desain konsumen, bukan pada provisioner.
Soal Urutan dan Partisi: Yang Sudah Ada dan Yang Belum
Di deskripsi teknisnya, K2 disebut sebagai log yang partitioned, yaitu log terurut yang dipecah ke beberapa partisi supaya tulis dan baca bisa paralel. Namun jaminan urutan berbasis key belum masuk ke versi hari ini. Roadmap mencantumkan message keys dan key-based ordering guarantees sebagai pekerjaan berikutnya, yang berarti saat ini urutan yang dijamin berada di level partisi, bukan di level entitas seperti satu user atau satu order.
Perbedaan ini terdengar kecil tapi menentukan kebenaran data. Banyak pipeline event butuh dua event dengan key yang sama diproses berurutan, misalnya order dibuat lalu order dibayar. Tanpa key-based ordering, konsumen harus membangun penataan sendiri, biasanya dengan stempel waktu dan state per entitas, dan itu persis sumber bug yang paling mahal di sistem event: data dari masa depan bocor ke keputusan masa lalu. Jadi kalau aplikasinya sensitif urutan per entitas, tahan dulu satu rilis, atau pastikan konsumen bisa idempoten dan mampu menata ulang sendiri.
Checklist Sebelum Memindahkan Beban ke K2
Daftar ini bisa dipakai sebagai penanda sebelum memutuskan memakai K2 di produksi, sekaligus sebagai alat cek bahwa desain sudah benar.
| Pertanyaan | Tanda siap | Kalau belum |
|---|---|---|
| Bisakah menanggung latensi produce sekitar satu detik di p99? | Pengiriman event berada di jalur non-transaksional seperti telemetri atau audit | Pakai antrean pesan tunggal atau tulis langsung ke database |
| Sudah idempoten di level konsumen? | Batch bisa ditarik ulang tanpa efek samping ganda | Tambahkan kunci idempotensi sebelum ack, jangan setelahnya |
| Butuh beberapa pembaca independen atas data yang sama? | Minimal dua konsumen dengan laju berbeda | Queues mungkin lebih sederhana dan lebih murah |
| Perlu urutan per entitas? | Belum, atau sudah ditata di konsumen | Tunggu dukungan message keys di roadmap |
| Sudah punya Workers Paid? | Sudah, dan beta terbuka untuk akun | Akses beta belum tersedia |
Dari tabel itu, satu baris paling sering diabaikan: idempotensi. Karena K2 mengirim batch dan menolak retry tingkat pesan, tanggung jawab atas duplikasi berpindah ke konsumen. Tim yang membawa mentalitas antrean pesan tunggal akan terkejut di bagian ini.
Versi Singkatnya
K2 adalah jawaban Cloudflare atas kebutuhan yang sama dengan Kafka, tapi dibangun dari bahan yang mereka punya: object storage yang kuat dan jaringan edge yang luas. Yang dijual bukan kecepatan, melainkan durability, retensi panjang, dan fan-out murah dengan nol kluster yang harus diurus. Harganya dibayar di latensi tulis dan di model konsumsi berbasis volume. Selama use case cocok dengan profil itu, primitive seperti ini jauh lebih hemat energi daripada menjalankan sistem distributed sendiri.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬