Migrasi Google Apps Script ke Cloudflare D1: Database Gratis, Cepat, dan Anti Pause

Web dari Google Apps Script (GAS) dan Google Sheets memang gratis dan mudah dibuat. Tapi makin banyak datanya, makin lambat, dan ada batas waktu proses 6 menit. Pindah ke Supabase memang lebih cepat, tapi versi gratisnya bisa "tertidur" kalau sepi seminggu. Cloudflare D1 adalah jalan tengahnya: database gratis, cepat, dan tidak perlu dijaga agar tetap "bangun". Panduan ini menjelaskan cara memindahkan web GAS Anda ke Cloudflare langkah demi langkah.
Kenapa Cloudflare D1?
- Tidak ada aturan tertidur karena sepi. D1 tidak memakai server database yang harus menyala terus seperti Supabase. Batas versi gratisnya berupa jatah harian, bukan aturan pause karena tidak aktif. Jadi tidak perlu lagi alarm atau ping otomatis.
- Jatah gratis besar. Setiap hari Anda boleh membaca 5 juta baris dan menulis 100 ribu baris data. Total penyimpanan 5 GB, maksimal 10 database, dan tiap database maksimal 500 MB. Untuk web sekolah atau usaha kecil, ini lebih dari cukup.
- Jauh lebih cepat. Web dijalankan di server Cloudflare yang terdekat dengan pengunjung, bukan membaca Google Sheets.
- Data lebih mudah diolah. D1 memakai bahasa SQL, jadi mengurutkan, menyaring, dan menghitung data cukup dengan satu perintah.
Istilah yang perlu Anda tahu
- Database: lemari arsip digital, seperti Sheets tapi jauh lebih cepat dan rapi.
- Worker: program kecil di server Cloudflare. Di sini ia menggantikan peran
Code.gs. - API: "jalur pesan" antara halaman web dan server, misalnya alamat
/api/simpanuntuk menyimpan data. - Wrangler: alat resmi Cloudflare yang dijalankan lewat terminal (jendela perintah) untuk membuat dan mengunggah Worker.
Apa saja yang berubah?
- Google Sheets menjadi tabel di D1.
- Kode di Code.gs menjadi kode Worker.
google.script.rundi halaman diganti denganfetch().- Halaman HTML menjadi file biasa yang ditampilkan Worker yang sama.
Contoh di bawah melanjutkan web formulir pendaftaran dari artikel cara membuat web dengan Google Apps Script, dengan sheet Data berisi kolom Waktu, Nama, dan Email.
Langkah 1: Siapkan project dan database
Pasang Node.js dulu (gratis di nodejs.org). Lalu buka terminal dan jalankan:
npx wrangler login npx wrangler d1 create db-pendaftaran
Perintah pertama membuka browser untuk masuk ke akun Cloudflare. Perintah kedua membuat database baru dan menampilkan kode database_id. Catat kode itu. Setelah itu buat folder dengan susunan seperti ini:
web-pendaftaran/ public/index.html -> halaman (dari Index.html di GAS) src/index.js -> kode server (pengganti Code.gs) schema.sql wrangler.toml
Isi file pengaturan wrangler.toml, dan ganti ISI-DENGAN-DATABASE-ID dengan kode yang tadi dicatat:
name = "web-pendaftaran" main = "src/index.js" compatibility_date = "2026-10-01" [assets] directory = "./public" [[d1_databases]] binding = "DB" database_name = "db-pendaftaran" database_id = "ISI-DENGAN-DATABASE-ID"
Langkah 2: Ubah sheet menjadi tabel
Satu sheet menjadi satu tabel, dan setiap kolom sheet menjadi kolom tabel. Tulis di file schema.sql:
CREATE TABLE IF NOT EXISTS pendaftaran ( id INTEGER PRIMARY KEY AUTOINCREMENT, waktu TEXT NOT NULL, nama TEXT NOT NULL, email TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_pendaftaran_email ON pendaftaran(email);
Artinya: buat tabel pendaftaran dengan nomor urut otomatis, waktu, nama, dan email. Baris terakhir membuat "daftar isi" (index) untuk kolom email, supaya pencarian lebih cepat dan hemat jatah harian. Lalu jalankan:
npx wrangler d1 execute db-pendaftaran --remote --file=./schema.sql
Langkah 3: Pindahkan data dari Google Sheets
D1 menerima data dalam bentuk file SQL (daftar perintah), bukan file Excel atau CSV. Cara termudah: biarkan Apps Script yang membuatkan file itu. Tambahkan fungsi ini di project GAS lama Anda, klik Run sekali, lalu unduh file data.sql yang muncul di Google Drive:
function eksporKeSQL() {
const rows = SpreadsheetApp.getActive().getSheetByName('Data')
.getDataRange().getValues().slice(1); // lewati baris judul
const q = v => v === '' || v === null ? 'NULL'
: v instanceof Date ? `'${v.toISOString()}'`
: typeof v === 'number' ? v
: `'${String(v).replace(/'/g, "''")}'`;
const sql = rows
.map(r => `INSERT INTO pendaftaran (waktu, nama, email) VALUES (${r.slice(0, 3).map(q).join(', ')});`)
.join('\n');
const file = DriveApp.createFile('data.sql', sql, MimeType.PLAIN_TEXT);
Logger.log(file.getUrl());
}
Fungsi ini membaca semua baris di sheet Data (kecuali judul), mengubah setiap baris menjadi satu perintah "masukkan data", lalu menyimpannya sebagai file. Nama yang mengandung tanda kutip, seperti O'Neil, otomatis diamankan. Setelah file diunduh, masukkan ke D1 dan cek jumlahnya:
npx wrangler d1 execute db-pendaftaran --remote --file=./data.sql npx wrangler d1 execute db-pendaftaran --remote --command="SELECT COUNT(*) FROM pendaftaran"
Langkah 4: Ganti Code.gs dengan Worker
Fungsi simpanData di GAS sekarang menjadi alamat /api/simpan di Worker. Isi file src/index.js:
// src/index.js
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/api/simpan' && request.method === 'POST') {
const data = await request.json().catch(() => ({}));
const nama = String(data.nama || '').trim();
const email = String(data.email || '').trim();
if (!nama || !email) {
return Response.json({ error: 'Nama dan email wajib diisi' }, { status: 400 });
}
await env.DB.prepare('INSERT INTO pendaftaran (waktu, nama, email) VALUES (?, ?, ?)')
.bind(new Date().toISOString(), nama, email)
.run();
return Response.json({ pesan: `Terima kasih, ${nama}! Data berhasil disimpan.` });
}
return new Response('Tidak ditemukan', { status: 404 });
}
};
Cara membacanya: kalau ada kiriman ke /api/simpan, ambil nama dan email, pastikan tidak kosong, lalu simpan ke tabel. Tanda tanya (?) dan bind() adalah cara aman memasukkan data, supaya orang iseng tidak bisa menyisipkan perintah berbahaya. File di folder public, seperti index.html, otomatis ditampilkan tanpa perlu kode tambahan.
Langkah 5: Ganti google.script.run dengan fetch
Salin isi Index.html dari GAS ke public/index.html. Hapus tulisan khusus GAS seperti <?!= include('Style'); ?> dan tempel isi CSS-nya langsung. Lalu ganti bagian pengiriman data:
// Sebelum (GAS)
google.script.run
.withSuccessHandler(teks => { pesan.textContent = teks; form.reset(); })
.withFailureHandler(err => { pesan.textContent = 'Gagal: ' + err.message; })
.simpanData(data);
// Sesudah (Worker + D1)
try {
const res = await fetch('/api/simpan', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const hasil = await res.json();
if (!res.ok) throw new Error(hasil.error);
pesan.textContent = hasil.pesan;
form.reset();
} catch (err) {
pesan.textContent = 'Gagal: ' + err.message;
}
Karena kode baru memakai await (menunggu jawaban server), ubah awal fungsi pengirim formulir menjadi async function (ev) { ... }.
Langkah 6: Coba lalu terbitkan
npx wrangler d1 execute db-pendaftaran --local --file=./schema.sql npx wrangler dev # coba di http://localhost:8787 npx wrangler deploy # terbit di https://web-pendaftaran.NAMA-AKUN.workers.dev
Dua perintah pertama untuk mencoba di komputer sendiri. Perintah terakhir menerbitkan web Anda ke internet. Setelah itu Anda bisa memasang domain sendiri lewat Settings > Domains & Routes pada Worker (lihat artikel cara membuat subdomain dengan Cloudflare Worker). Web GAS lama boleh dibiarkan dulu sampai semua pengguna pindah.
Hal yang perlu diperhatikan
- Jatah harian. Kalau jatah harian habis, database menolak permintaan sampai pukul 07.00 WIB keesokan harinya. Pakai index dan batasi jumlah data yang dibaca agar hemat.
- Tidak ada sistem login bawaan. Berbeda dengan Supabase, D1 tidak punya fitur login. Lindungi halaman admin, misalnya dengan kata sandi rahasia yang disimpan lewat
npx wrangler secret put. - Rutin cadangkan data. Unduh salinan database dengan
npx wrangler d1 export db-pendaftaran --remote --output=backup.sql. - Kapan Supabase lebih cocok? Kalau aplikasi Anda butuh login pengguna, data yang berubah langsung (realtime), atau fitur database yang lebih lengkap. Panduannya ada di artikel migrasi Apps Script ke Supabase, dan supaya tidak tertidur, lihat cara agar Supabase gratis tidak pause dengan cron-job.org.
Sumber: Getting started, Cloudflare D1, Pricing, Cloudflare D1, Limits, Cloudflare D1, dan Import and export data, Cloudflare D1.