Multi-cloud artinya memakai lebih dari satu cloud provider. Biasanya maksudnya memilih provider terbaik untuk tiap kebutuhan, bukan menjalankan semuanya di semua provider sekaligus. Bayangin belanja untuk warungmu. Sayur dibeli di pasar, gas di agen, kemasan di toko grosir: tiap barang dari tempat yang paling cocok, dan itu wajar. Lain cerita kalau kamu membangun dua dapur lengkap di dua rumah, supaya kalau satu dapur kebakaran kamu tetap bisa masak. Bisa, tapi semuanya dua kali: belanja, bersih-bersih, dan resepnya harus jalan di dua kompor yang berbeda. Pelajaran ini tentang membedakan keduanya untuk catatan-api, dan kenapa jawabannya biasanya: jangan bangun dapur kedua.
🧪 Tebakan cepat: lampiran catatan-api diunduh 2.000 GB sebulan dari bucket S3. Dengan harga contoh 100 GB pertama gratis lalu $0,09 per GB, egress-nya $171. Kalau bucket-nya pindah ke Cloudflare R2, berapa biaya egress-nya? Tebak dulu, jawabannya ada di bagian "Egress: biaya yang sering terlupa".
catatan-api sudah multi-vendor
Lihat lagi apa yang sudah dibangun di track ini:
| Bagian | Provider | Kenapa di sana |
|---|---|---|
API catatan-api di web-1, web-2 |
VPS sewaan | murah, kontrol penuh |
DNS, CDN, Worker catatan-edge |
Cloudflare | edge dekat pengunjung |
Frontend catatan-web (Next.js) |
Vercel | deploy Next.js tanpa repot |
Bucket catatan-lampiran, Lambda catatan-ekspor |
AWS, ap-southeast-3 Jakarta |
object storage dan FaaS |
| Repo dan CI/CD | GitHub | Actions di samping kode |
Ini sudah "multi-cloud" dalam arti pertama: tiap kebutuhan dapat provider yang paling cocok (best-of-breed). Tiap bagian jalan di satu tempat saja. Yang mahal adalah arti kedua: aktif-aktif, yaitu API dan database yang sama jalan di dua cloud sekaligus.
Lock-in vs kompleksitas
Vendor lock-in adalah keadaan ketika pindah dari satu provider jadi mahal, karena kode dan data-mu terikat pada layanan khas provider itu. Contohnya handler Lambda yang membaca event API Gateway, atau Worker yang memakai KV dan Durable Objects: gak ada padanannya yang identik di tempat lain.
Lawannya kompleksitas. Tiap provider tambahan membawa paket lengkapnya sendiri, dan angka di Lab menunjukkan apa yang berlipat kalau catatan-api dibuat aktif-aktif di AWS dan Google Cloud:
| Yang harus diurus | Satu cloud | Aktif-aktif dua cloud |
|---|---|---|
| Sistem izin (IAM) dan akun tagihan | 1 | 2 |
| Dashboard monitoring dan alert | 1 | 2 |
| Provider di Terraform | 1 | 2 |
| Database | 1 Postgres | 2 Postgres + replikasi lintas cloud |
| Biaya tambahan per bulan (contoh) | $0 | $126 (compute $48 + Postgres $60 + replikasi $18) |
Untuk tim dua orang, menggandakan semua itu biasanya lebih berbahaya daripada lock-in yang mau dihindari: lebih banyak konfigurasi berarti lebih banyak tempat untuk salah.
Egress: biaya yang sering terlupa
Data yang keluar dari cloud dibayar per GB (pelajaran Cloud Computing Basics), termasuk data yang mengalir ke cloud lain. Data yang masuk biasanya gratis, jadi yang menagih adalah provider pengirim. Tagihan bulanan contoh untuk lampiran catatan-api: 500 GB tersimpan, 2.000 GB diunduh pengguna, dan 300 GB dibaca Lambda catatan-ekspor di AWS untuk ditempel ke PDF:
| Bucket di | Simpan 500 GB | Diunduh 2.000 GB | Dibaca Lambda 300 GB | Total |
|---|---|---|---|---|
| S3 Jakarta | $12,50 | $171 (100 GB gratis) | $0 (region yang sama) | $183,50 |
| Cloudflare R2 | $7,50 | $0 | $0 | $7,50 |
| Google Cloud Storage Jakarta | $11,50 | $240 | $36 (lintas cloud) | $287,50 |
R2 gak memungut biaya egress sama sekali, jadi jawabannya $0. Itu jawaban tebakannya. Harga di tabel ini contoh untuk berhitung, bukan harga terkini; biaya per operasi (per upload, per download) juga diabaikan karena kecil di sini.
Kolom ketiga adalah risiko lintas cloud: kalau API di AWS menarik gambar besar dari Google Cloud Storage di tiap request, kamu membayar biaya transfer di tiap request dan menunggu latency jaringan antar-cloud, yang lebih lambat daripada jaringan di dalam satu region.
Bagian yang portable
Kamu bisa mengurangi lock-in tanpa menjalankan dua cloud, dengan memilih bagian yang mudah dipindah:
- Container: image Docker yang sama jalan di VPS, di AWS, atau di Google Cloud.
- Terraform: alatnya sama di semua provider, tapi resource-nya tidak.
aws_s3_bucketharus ditulis ulang jadigoogle_storage_bucketkalau pindah ke Google. Terraform memudahkan pindah, gak membuatnya otomatis. - API S3-compatible: R2, Google Cloud Storage, DigitalOcean Spaces, dan MinIO menerima panggilan API S3, jadi SDK yang sama cukup diganti
endpoint-nya. - Postgres standar: SQL biasa jalan di Postgres mana pun. Fitur khas satu layanan terkelola yang mengikat.
Lapisan abstraksi membuat pindah provider cuma urusan satu file:
// storage.ts: kode lain cuma mengenal interface ini
import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl as presign } from "@aws-sdk/s3-request-presigner";
export interface StorageProvider {
upload(key: string, data: Uint8Array): Promise<void>;
download(key: string): Promise<Uint8Array>;
delete(key: string): Promise<void>;
getSignedUrl(key: string, expiresIn: number): Promise<string>;
}
// Satu class untuk semua penyedia yang bicara API S3
export class S3CompatibleStorage implements StorageProvider {
constructor(private s3: S3Client, private bucket: string) {}
async upload(key: string, data: Uint8Array) {
await this.s3.send(new PutObjectCommand({ Bucket: this.bucket, Key: key, Body: data }));
}
async download(key: string) {
const res = await this.s3.send(new GetObjectCommand({ Bucket: this.bucket, Key: key }));
return res.Body!.transformToByteArray();
}
async delete(key: string) {
await this.s3.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
}
getSignedUrl(key: string, expiresIn: number) {
return presign(this.s3, new GetObjectCommand({ Bucket: this.bucket, Key: key }), { expiresIn });
}
}
// Yang beda antar penyedia cuma config S3Client:
const s3 = new S3Client({ region: "ap-southeast-3" }); // S3 Jakarta
// R2: new S3Client({ region: "auto", endpoint: `https://${accountId}.r2.cloudflarestorage.com`, credentials })
export const lampiran: StorageProvider = new S3CompatibleStorage(s3, "catatan-lampiran");
- Route dan job cuma memanggil
lampiran.upload(...)danlampiran.getSignedUrl(...), gak pernahS3Clientlangsung. - Pindah dari S3 ke R2 cukup mengganti config
S3Client(atau menambah class implementasi baru sepertiR2Storage), dan kode pemanggilnya tetap. - Kompatibel bukan berarti identik: lifecycle rule, kelas penyimpanan, dan fitur baru di SDK bisa berbeda per penyedia. Uji dulu sebelum pindah.
Kapan dua cloud benar-benar perlu
Mulai dari kebutuhan, bukan dari strategi. Ini yang dipakai pemandu keputusan di Lab:
| Kebutuhan | Jawaban yang biasanya cukup |
|---|---|
| Lampiran diunduh terabyte per bulan | pindahkan lampiran ke penyimpanan tanpa egress (R2) atau di belakang CDN: satu vendor tambahan untuk satu kebutuhan |
| Klien mewajibkan data disimpan di Indonesia | pilih region Jakarta di satu provider (AWS ap-southeast-3, Google asia-southeast2). Ini soal region, bukan jumlah cloud. R2 gak menjamin data tinggal di Indonesia |
| Harus tetap jalan walau satu provider mati total | satu-satunya alasan kuat untuk aktif-aktif dua cloud, dan cuma kalau tim cukup besar untuk merawatnya. Mulai dari dua region di satu provider |
| Takut terkunci | pakai bagian yang portable (container, Terraform, API S3, Postgres) dan lapisan abstraksi |
| Tim cuma dua orang | satu provider utama, sesedikit mungkin vendor tambahan |
⚠️ Jebakan yang sering ketemu
- Aktif-aktif "biar aman" tanpa kebutuhan nyata. Biaya dan jumlah hal yang dirawat berlipat, sementara outage total satu provider jauh lebih jarang daripada salah konfigurasi.
- Lupa egress lintas cloud. Compute di satu cloud yang membaca data besar dari cloud lain membayar transfer di tiap request.
- Mengira Terraform membuat infrastruktur portable. Resource-nya tetap milik satu provider.
- Menganggap S3-compatible sama persis dengan S3. Uji fitur yang kamu pakai di penyedia baru sebelum memindahkan data.
TL;DR: Multi-cloud berarti memakai lebih dari satu cloud provider, dan versi yang sehat adalah memilih provider terbaik untuk tiap kebutuhan (best-of-breed), seperti catatan-api dengan VPS, Cloudflare, Vercel, dan AWS. Menjalankan workload yang sama aktif-aktif di dua cloud menggandakan IAM, tagihan, monitoring, Terraform, dan database (di Lab +$126 per bulan) dan biasanya gak sepadan untuk tim kecil. Egress dibayar provider pengirim: lampiran 2.000 GB di S3 $171 per bulan, di R2 $0, dan data yang ditarik lintas cloud membawa biaya transfer serta latency. Kurangi lock-in dengan bagian yang portable (container, Terraform, API S3-compatible, Postgres) dan lapisan abstraksi seperti StorageProvider, sehingga pindah dari S3 ke R2 cukup mengganti implementasinya, kode pemanggil tetap. Data residency diselesaikan dengan region, bukan dengan cloud kedua.