KlikApa dibangun sepenuhnya di Cloudflare — Workers untuk compute, D1 untuk database, R2 untuk storage. Biaya infrastruktur? Di bawah $10/bulan bahkan dengan ratusan pelanggan. Panduan ini menjelaskan kenapa stack ini begitu efektif untuk SaaS dan bagaimana Anda bisa menggunakannya untuk produk Anda sendiri.

Kenapa Cloudflare untuk SaaS?

Tradisional, founder SaaS memilih AWS, GCP, atau Vercel + PlanetScale/Supabase. Stack ini bekerja, tapi biayanya bertambah seiring skala. Cloudflare menawarkan model yang berbeda:

KomponenTradisionalCloudflare
Compute$20-100/bulan (EC2, Lambda)$0.30/juta request (Workers)
Database$15-50/bulan (RDS, PlanetScale)Gratis hingga batas tertentu, lalu ~$1/juta write (D1)
Storage$0.023/GB + egress (S3)$0.015/GB, tanpa egress (R2)
CDN$20/bulan (CloudFront)Gratis dan built-in
SSLGratis (Let's Encrypt)Gratis dan otomatis

Total biaya untuk MVP dengan 10.000 pengguna aktif: kurang dari $10/bulan. Itu termasuk Workers Paid plan ($5/bulan). Untuk context, setup serupa di AWS bisa mencapai $50-200/bulan.

Arsitektur yang Kami Gunakan di KlikApa

KlikApa memiliki tiga komponen utama:

1. Tracking Script (Client-Side)

Script vanilla JS yang di-embed di situs pelanggan. Ukurannya di bawah 1KB dan menggunakan navigator.sendBeacon() untuk mengirim event tanpa memblokir rendering halaman.

Script menangkap:

2. Ingestion Worker (Edge)

Worker yang menerima event dari tracking script, memvalidasinya, dan menyimpan ke D1. Berjalan di edge — artinya request diproses di lokasi terdekat dengan pengunjung, bukan di server pusat.

Worker yang sama juga menangani webhook dari Stripe dan Lemon Squeezy — menerima notifikasi pembayaran dan mengaitkannya dengan session pengunjung untuk atribusi revenue.

3. Dashboard Worker + Pages

Dashboard KlikApa sendiri adalah aplikasi yang dihosting di Cloudflare Pages dengan API endpoints yang berjalan di Workers. Query D1 untuk menampilkan data journey, funnel, dan atribusi ke pelanggan.

Skema Database di D1

D1 menggunakan SQLite, jadi skema relasional standar bekerja sempurna. Berikut inti skema yang kami gunakan:

-- Tabel utama untuk event
CREATE TABLE events (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  tenant_id TEXT NOT NULL,
  session_id TEXT NOT NULL,
  visitor_id TEXT,
  timestamp INTEGER NOT NULL,
  event_type TEXT NOT NULL,
  path TEXT,
  utm_source TEXT,
  utm_medium TEXT,
  utm_campaign TEXT,
  revenue REAL,
  props TEXT, -- JSON string
  referrer TEXT
);

-- Index untuk query cepat
CREATE INDEX idx_events_tenant_session
  ON events(tenant_id, session_id, timestamp);

CREATE INDEX idx_events_tenant_type
  ON events(tenant_id, event_type, timestamp);

-- Tabel sessions untuk agregasi
CREATE TABLE sessions (
  id TEXT PRIMARY KEY,
  tenant_id TEXT NOT NULL,
  visitor_id TEXT,
  started_at INTEGER,
  utm_source TEXT,
  utm_medium TEXT,
  utm_campaign TEXT,
  referrer TEXT,
  event_count INTEGER DEFAULT 1,
  converted INTEGER DEFAULT 0
);

Index yang benar adalah kunci performa D1. Dengan index pada (tenant_id, session_id, timestamp), query untuk merekonstruksi user journey selesai dalam milidetik bahkan dengan jutaan event.

Multi-Tenancy: Dua Pendekatan

Untuk SaaS multi-tenant, ada dua pola yang terbukti bekerja:

Pendekatan A: Shared Database dengan tenant_id

Satu database D1 untuk semua pelanggan. Setiap tabel memiliki kolom tenant_id dan semua query menyertakan filter WHERE tenant_id = ?.

Kelebihan: Sederhana, satu database yang diatur, mudah untuk cross-tenant analytics (untuk Anda sebagai platform owner).

Kekurangan: Isolasi data bergantung pada disiplin query. Satu query tanpa filter tenant_id bisa bocor data.

Pendekatan B: Database Per Pelanggan

Setiap pelanggan mendapat database D1 sendiri. Cloudflare memungkinkan pembuatan dan binding database secara programatik.

Kelebihan: Isolasi data sempurna, tidak ada risiko kebocoran, performa per-tenant terisolasi.

Kekurangan: Lebih kompleks di setup, cross-tenant analytics memerlukan agregasi manual.

Untuk KlikApa, kami menggunakan Pendekatan A karena kesederhanaan. Filter tenant_id di-abstraksi ke dalam middleware sehingga tidak mungkin terlupa.

Query yang Paling Penting

User Journey

Rekonstruksi jalur pengunjung dari satu session:

SELECT path, event_type, timestamp, props
FROM events
WHERE tenant_id = ? AND session_id = ?
ORDER BY timestamp ASC;

Untuk melihat jalur paling umum di semua session:

SELECT path, COUNT(*) AS hits
FROM events
WHERE tenant_id = ?
  AND timestamp > ?
GROUP BY path
ORDER BY hits DESC
LIMIT 20;

Atribusi Revenue

Total revenue per sumber UTM:

SELECT utm_source, utm_medium,
       SUM(revenue) AS total_revenue,
       COUNT(DISTINCT session_id) AS sessions
FROM events
WHERE tenant_id = ?
  AND revenue IS NOT NULL
  AND timestamp > ?
GROUP BY utm_source, utm_medium
ORDER BY total_revenue DESC;

Funnel Konversi

Menghitung berapa banyak session yang melewati setiap langkah funnel:

WITH funnel AS (
  SELECT session_id,
    MAX(CASE WHEN path = '/pricing' THEN 1 ELSE 0 END) AS step1,
    MAX(CASE WHEN event_type = 'signup' THEN 1 ELSE 0 END) AS step2,
    MAX(CASE WHEN event_type = 'purchase' THEN 1 ELSE 0 END) AS step3
  FROM events
  WHERE tenant_id = ? AND timestamp > ?
  GROUP BY session_id
)
SELECT
  SUM(step1) AS saw_pricing,
  SUM(step2) AS signed_up,
  SUM(step3) AS purchased
FROM funnel;

Performa di Dunia Nyata

Dengan skema dan index di atas, berikut performa yang kami ukur di produksi:

OperasiLatency (p50)Latency (p99)
INSERT event (ingestion)2ms8ms
Query user journey (1 session)3ms12ms
Query revenue attribution (30 hari)15ms45ms
Query funnel (30 hari)20ms60ms
Query top paths (30 hari)25ms80ms

Untuk hingga 1 juta event per tenant, performa ini lebih dari cukup. Untuk volume lebih tinggi, Anda bisa menambah pre-aggregation via Cron Triggers yang menjalankan query ringkasan setiap jam dan menyimpan hasilnya di tabel terpisah.

Rekomendasi untuk Mulai

  1. Gunakan Hono sebagai framework. Hono ringan (~14KB), TypeScript-native, dan bekerja sempurna di Cloudflare Workers. Jangan gunakan Express — terlalu berat untuk edge.
  2. Mulai dengan shared database. Satu D1 dengan tenant_id cukup hingga ribuan pelanggan. Pindah ke per-tenant database hanya jika benar-benar diperlukan.
  3. Gunakan R2 untuk data mentah. Simpan JSON event lengkap di R2 sebagai backup dan untuk analisis mendalam di masa depan.
  4. Tambah Cron Triggers untuk agregasi. Pre-compute angka yang sering diakses (visitor harian, revenue per source) setiap jam, bukan query ulang setiap kali dashboard dibuka.
  5. Implement Stripe webhooks di Worker yang sama. Satu Worker bisa menangani baik tracking event dan payment webhook — tidak perlu service terpisah.

Keterbatasan yang Perlu Diketahui

Kesimpulan

Cloudflare Workers + D1 + R2 adalah stack yang luar biasa efisien untuk SaaS. Biaya infrastruktur yang rendah memungkinkan Anda menawarkan harga kompetitif sambil tetap menghasilkan margin tinggi. Dan karena semuanya berjalan di edge, performa untuk pengguna di Indonesia sama baiknya dengan pengguna di Amerika.

KlikApa adalah bukti bahwa stack ini bekerja di produksi — analytics SaaS penuh dengan user journey, funnel, dan atribusi revenue, semuanya berjalan dengan biaya infrastruktur kurang dari $10/bulan.

Lihat KlikApa dalam Aksi

Analytics SaaS yang dibangun sepenuhnya di Cloudflare. User journey, funnel konversi, dan atribusi revenue dari $4/bulan. Mulai gratis 14 hari.