Astro dari Nol sampai Portal Berita di AWS
Dari komponen .astro pertama sampai memindahkan portal berita yang sudah hidup โ
ratusan ribu artikel, membership berbayar, dan jutaan request per jam โ dari CodeIgniter 3 ke Astro,
tanpa mematikan situs lama satu hari pun.
Tiga hal yang paling menentukan dibahas tuntas: paywall yang tidak bisa dilewati sekaligus tetap bisa di-cache di CDN, dua jalur data โ Kysely langsung ke MySQL dan consume API โ beserta kapan masing-masing benar, dan deployment di AWS di belakang Cloudflare.
- Durasi
- ~18 minggu
- Beban
- ~8 jam/minggu
- Prasyarat
- Pernah ngoding, paham HTTP & SQL
- Target akhir
- Portal berita berbayar di AWS
Untuk siapa roadmap ini
"Dari nol" di sini berarti nol Astro, bukan nol pemrograman. Kamu diasumsikan sudah pernah menulis kode di bahasa apa pun โ kemungkinan besar PHP โ dan paham dasar HTTP serta SQL. TypeScript dibahas secukupnya di Fase 0: enam konstruksi yang benar-benar dipakai, bukan kursus TypeScript lengkap.
Konteks yang dipakai sepanjang roadmap ini konkret: sebuah portal berita dan data perusahaan berbasis CodeIgniter 3 dengan membership berbayar, melayani sekitar 1,25 juta request per jam โ 750 ribu dilayani Cloudflare, 500 ribu lolos ke origin. Angka-angka itu dipakai untuk menghitung kapasitas, biaya, dan target sepanjang roadmap.
Versi acuan: Astro 7.2 (Astro 6 rilis Maret 2026, Astro 7 rilis Juni 2026). Beberapa hal
berubah dan membuat tutorial lama menyesatkan: output: "hybrid" sudah dihapus,
<ViewTransitions /> menjadi <ClientRouter />, content
collections wajib memakai Content Layer API, dan Node 22.12 jadi syarat minimum. Kalau sebuah tutorial
menyuruhmu cukup menaruh berkas Markdown di src/content/blog/ tanpa
content.config.ts, tutorial itu ditulis untuk Astro 4 ke bawah.
Yang sengaja dilewati
| Topik | Alasan |
|---|---|
| Pemrograman dari nol | Diasumsikan bisa ngoding; Fase 0 memetakan yang berbeda di Astro |
| TypeScript mendalam | Enam konstruksi yang dipakai, sisanya bisa menyusul |
| Vue mendalam | Dibahas sebagai island; dasar Vue diasumsikan bisa dibaca |
| Terraform & CDK | Konsep AWS-nya yang diajarkan; alat IaC bisa menyusul |
| Kubernetes | ECS Fargate cukup, dan jauh lebih sedikit yang harus dioperasikan |
| Microservice sebagai titik awal | Dibahas kapan pemisahan justru masuk akal di Fase 11 |
| Astro sebagai blog pribadi | Sudah banyak; roadmap ini tentang aplikasi berskala |
Bentuk roadmap ini
| Bagian | Fase | Menjawab |
|---|---|---|
| Cara Astro bekerja | 0 โ 1 | Island, routing, dan model rendering yang menentukan sisanya |
| Dari mana datanya | 2 โ 4 | MySQL lewat Kysely, API, dan bagian interaktif |
| Membership & uang | 5 โ 7 | Paywall, Midtrans, dan keamanan yang menjaganya |
| Melayani jutaan orang | 8 โ 11 | Cache Cloudflare, migrasi dari CI3, AWS, dan performa |
Urutannya disengaja. Fase 10 adalah bagian yang paling sering dicari duluan โ tapi deploy ke AWS sebelum cache-nya benar hanya memindahkan tagihan, dan memasang paywall sebelum memahami server islands akan menghasilkan paywall yang bisa dilewati dengan Ctrl+U. Jangan lompat ke Fase 10.
Fondasi: Node, TypeScript & Cara Pikir Astro
Tujuan: punya proyek Astro yang berjalan, bisa membaca berkas .astro tanpa
tersandung sintaks, dan paham kenapa arsitektur island membuat portal beritamu bisa di-cache utuh di
CDN โ sesuatu yang tidak bisa dilakukan CI3 tanpa menulis ulang cara sesinya bekerja.
Setup sekali jalan
node --version # wajib v22.12.0 atau lebih baru
corepack enable pnpm
pnpm create astro@latest portal-berita
cd portal-berita
pnpm astro add vue node
pnpm add kysely mysql2 zod
pnpm dev
Empat hal yang harus benar sejak hari pertama
| Hal | Kenapa |
|---|---|
TypeScript preset strict | Melonggarkan nanti mudah; mengetatkan di 200 berkas hampir tidak pernah terjadi |
pnpm-lock.yaml di-commit | Setara composer.lock; tanpanya build produksi tidak reprodusibel |
Alias @/* di tsconfig.json | Menghapus ../../../ yang bikin refactor menyakitkan |
Hanya src/lib/ yang menyentuh database | Filter status = 'terbit' tidak bisa terlupa di satu halaman |
Materi
-
Node 22, pnpm & memasang AstroResmiToolchain JavaScript untuk orang yang terbiasa dengan PHP dan Composer โ termasuk tiga kebiasaan Composer yang justru menyesatkan di sini.docs.astro.buildBaca rangkuman โ
-
TypeScript secukupnya untuk AstroResmiBagian TypeScript yang benar-benar dipakai di Astro โ dan kenapa untuk portal berita, tipe adalah pengganti langsung dari dokumentasi yang tidak pernah ditulis.docs.astro.buildBaca rangkuman โ
-
Arsitektur island โ kenapa Astro, bukan NextResmiSatu keputusan arsitektur yang menentukan seluruh sisanya: default-nya nol JavaScript, dan interaktivitas dibeli satu per satu.docs.astro.buildBaca rangkuman โ
-
Struktur proyek & konvensi folderResmiFolder mana yang punya arti khusus bagi Astro, mana yang bebas โ dan perbedaan public/ vs src/assets/ yang menjebak semua pendatang.docs.astro.buildBaca rangkuman โ
-
Anatomi komponen .astroResmiPagar tiga strip, template, slot, dan satu aturan yang menjelaskan hampir semua kebingungan pendatang: frontmatter tidak pernah jalan di browser.docs.astro.buildBaca rangkuman โ
-
Peta CodeIgniter 3 โ AstroResmiTerjemahan satu per satu dari konsep CI3 ke padanannya di Astro โ termasuk empat hal yang sengaja tidak punya padanan, dan kenapa itu bagus.codeigniter.comBaca rangkuman โ
Kamu bisa menjelaskan kenapa halaman artikel Astro bisa dilayani dari edge Cloudflare sementara halaman CI3 yang sama tidak โ dan menunjuk baris kode mana penyebabnya.
Routing, Layout & Model Rendering
Tujuan: paham model rendering Astro cukup dalam untuk mengambil keputusan yang benar per halaman โ dan menguasai server islands, satu fitur yang membuat paywall dan cache CDN bisa hidup berdampingan.
Keputusan per halaman
| Halaman | Model | Cache |
|---|---|---|
| Artikel | On-demand | s-maxage=300 + Cache-Tag |
| Beranda | On-demand | s-maxage=60 |
| Blok paywall | Server island | private, no-store |
| Dashboard member | On-demand | private, no-store |
| Tentang, S&K | prerender = true | Statis |
Materi
-
Routing berbasis berkasResmiLetak berkas menentukan URL โ termasuk aturan prioritas saat dua rute sama-sama cocok, yang tidak intuitif dan menggigit saat migrasi.docs.astro.buildBaca rangkuman โ
-
Rute dinamis & getStaticPathsResmiCara memberitahu Astro halaman apa saja yang harus dibuat saat build โ dan kenapa untuk 200 ribu artikel jawabannya justru jangan.docs.astro.buildBaca rangkuman โ
-
Layout, slot & kepala halamanResmiKerangka halaman yang tidak bisa lupa memuat footer โ plus cara menaruh meta SEO dan JSON-LD di satu tempat, bukan tersebar di tiga puluh view.docs.astro.buildBaca rangkuman โ
-
Statis vs on-demand โ memilih model renderResmiKeputusan tunggal yang menentukan biaya AWS-mu, kesegaran beritamu, dan apakah Cloudflare bisa menolongmu sama sekali.docs.astro.buildBaca rangkuman โ
-
Server islands โ halaman ter-cache dengan isi per pembacaResmiFitur tunggal yang membuat paywall dan cache CDN bisa hidup berdampingan โ beserta empat jebakan yang tidak disebut tutorial mana pun.docs.astro.buildBaca rangkuman โ
-
Middleware โ satu tempat untuk tiap requestResmiPengganti hook pre_controller CI3 yang bisa dibaca dari atas ke bawah โ plus alasan kenapa membaca sesi di sini justru bisa merusak seluruh cache-mu.docs.astro.buildBaca rangkuman โ
-
Actions โ form dan mutasi yang tervalidasiResmiPengganti $this->input->post() yang tidak bisa kamu lupa validasi โ karena validasinya bagian dari deklarasi fungsinya.docs.astro.buildBaca rangkuman โ
Kamu bisa membuat halaman yang di-cache di edge selama lima menit tapi menampilkan blok berbeda
untuk member dan non-member โ dan membuktikannya dengan curl.
MySQL dengan Kysely
Tujuan: memindahkan seluruh kueri CI3 Query Builder ke Kysely dengan tipe yang diturunkan dari skema aslimu, dan memahami aritmetika koneksi yang menentukan batas atas autoscaling-mu nanti.
Peta cepat dari CI3
// CodeIgniter 3
$this->db->select('a.id, a.judul')->from('artikel a')
->where('a.status', 'terbit')->order_by('a.terbit_pada', 'DESC')
->limit(20)->get()->result();
// Kysely โ bentuknya sama, tapi nama tabel & kolom diperiksa compiler
await db.selectFrom("artikel as a").select(["a.id", "a.judul"])
.where("a.status", "=", "terbit").orderBy("a.terbit_pada", "desc")
.limit(20).execute();
Aritmetika yang menentukan segalanya
total koneksi = connectionLimit ร jumlah task ECS MAKSIMUM
+ koneksi CI3 selama transisi
+ cron, admin, BI
< max_connections RDS
Materi
-
Kenapa Kysely, bukan ORMResmiKysely bukan Active Record โ ia Query Builder, dan justru itu yang membuatnya terasa akrab kalau kamu datang dari CI3.kysely.devBaca rangkuman โ
-
Koneksi MySQL & ukuran poolResmiSatu pool untuk seluruh aplikasi, angka yang benar untuk ECS, dan hitungan yang menjelaskan kenapa autoscaling bisa menjatuhkan database.sidorares.github.ioBaca rangkuman โ
-
Membaca skema CI3 dengan kysely-codegenResmiMenghasilkan tipe TypeScript langsung dari database yang sudah berjalan โ dan lima kejutan yang menunggumu di skema CI3 berumur lima tahun.kysely.devBaca rangkuman โ
-
SELECT, JOIN & relasi bersarangResmiTerjemahan langsung dari CI3 Query Builder, ditambah cara mengambil relasi bersarang dalam satu kueri โ bukan satu kueri per baris.kysely.devBaca rangkuman โ
-
INSERT, UPDATE & transaksiResmiMySQL tidak punya RETURNING โ dan itu mengubah cara kamu menulis insert. Plus transaksi yang benar untuk alur pembayaran.kysely.devBaca rangkuman โ
-
EXPLAIN, index & kueri yang menjatuhkan portalResmiCara membaca EXPLAIN dalam tiga kolom, index mana yang benar-benar dibutuhkan portal berita, dan kueri mana yang harus tidak pernah ada.dev.mysql.comBaca rangkuman โ
-
Read replica โ memisahkan baca dari tulisResmiCara portal read-heavy menskalakan database โ beserta satu kelas bug yang hanya muncul setelah replica dipasang, dan cara menghindarinya.docs.aws.amazon.comBaca rangkuman โ
-
Migrasi skema tanpa mematikan situsResmiCara mengubah skema yang dipakai CI3 lama dan Astro baru sekaligus โ plus aturan tiga-deploy untuk mengganti nama kolom tanpa downtime.kysely.devBaca rangkuman โ
Kamu bisa menjalankan kysely-codegen terhadap skema CI3-mu, menulis ulang tiga kueri
tersibuk sebagai Kysely, dan menyebutkan angka connectionLimit yang benar untuk portalmu
beserta alasannya.
Jalur API
Tujuan: menguasai jalur data yang kedua โ Astro sebagai penyedia dan konsumen API โ dan bisa menjawab dengan tepat kapan API adalah keputusan yang benar dan kapan ia lapisan yang tidak menyelesaikan apa pun.
Argumen yang perlu diluruskan lebih dulu: API tidak mengurangi jumlah koneksi database โ ia memindahkan pool-nya. Yang menentukan benar-tidaknya adalah di mana Astro berjalan: di ECS sebagai proses panjang, pool sudah terpusat dan API cuma menambah satu hop; di Lambda, kekhawatirannya nyata dan jawabannya RDS Proxy, bukan API buatan sendiri. Alasan yang benar untuk membangun API ada, dan dibahas di fase ini.
Materi
-
"API menghemat koneksi database" โ meluruskan argumennyaResmiArgumen yang sering dipakai untuk memilih API ternyata keliru โ tapi kesimpulannya bisa tetap benar, dengan alasan yang berbeda.docs.aws.amazon.comBaca rangkuman โ
-
Menulis API di AstroResmiEndpoint sebagai berkas .ts di dalam pages/ โ untuk webhook, feed RSS, sitemap, dan API yang dikonsumsi aplikasi lain.docs.astro.buildBaca rangkuman โ
-
Mengambil data dari API di AstroResmifetch di frontmatter terlihat sepele โ sampai API-nya lambat dan menjatuhkan seluruh halamanmu. Timeout, paralelisasi, dan fallback.docs.astro.buildBaca rangkuman โ
-
Zod โ memvalidasi data yang datang dari luarResmiTipe TypeScript hilang saat runtime. Zod adalah pengganti yang benar-benar memeriksa โ di batas API, form, dan webhook.zod.devBaca rangkuman โ
-
Cache berlapis โ dari edge sampai memori prosesResmiEmpat lapis cache, apa yang layak ada di masing-masing, dan cara menghindari thundering herd yang menjatuhkan origin saat cache kedaluwarsa.docs.aws.amazon.comBaca rangkuman โ
-
Content Collections & data eksternalResmiLapisan konten bertipe milik Astro โ kapan ia cocok untuk portal berita, dan kapan ia justru salah alat.docs.astro.buildBaca rangkuman โ
-
Retry, backoff & circuit breakerResmiRetry yang salah memperparah gangguan, bukan menyembuhkannya. Aturan tentang apa yang boleh diulang, berapa kali, dan kapan berhenti sama sekali.aws.amazon.comBaca rangkuman โ
Kamu bisa membangun halaman yang mengambil dua sumber data secara paralel, tetap merender dalam tiga detik meski salah satunya menggantung sepuluh detik, dan menurunkan TTL cache-nya saat itu terjadi.
Island Vue & Interaktivitas
Tujuan: menambahkan tabel data, grafik, dan komponen interaktif tanpa membengkakkan JavaScript yang sampai ke pembaca โ dengan anggaran yang ditegakkan otomatis di CI, bukan diingat orang.
Anggaran JavaScript
| Halaman | Anggaran (gzip) |
|---|---|
| Artikel | โค 45 KB |
| Beranda | โค 60 KB |
| Data perusahaan | โค 140 KB |
| Dashboard member | โค 180 KB |
Materi
-
Memasang Vue sebagai islandResmiVue di dalam Astro punya batas yang tidak ada di aplikasi Vue biasa โ dan batas itu yang membuat bundelnya tetap kecil.docs.astro.buildBaca rangkuman โ
-
Direktif hidrasi & anggaran JavaScriptResmiLima direktif, kapan masing-masing benar, dan cara menetapkan anggaran JavaScript yang tidak bisa dilanggar diam-diam.docs.astro.buildBaca rangkuman โ
-
Tabel data yang tidak menjatuhkan browserResmiSortir, filter, dan paginasi untuk ribuan baris data perusahaan โ dan keputusan tunggal yang menentukan semuanya: di klien atau di server.vuejs.orgBaca rangkuman โ
-
Grafik tanpa membengkakkan bundelResmiLibrary grafik adalah dependensi terberat di portal data. Cara memilihnya, memuatnya malas, dan kapan SVG buatan sendiri lebih baik.chartjs.orgBaca rangkuman โ
-
Berbagi state antar islandResmiIsland tidak saling kenal. Nanostores menghubungkannya tanpa membawa seluruh state manager โ dan sering kali jawabannya adalah tidak usah.docs.astro.buildBaca rangkuman โ
-
ClientRouter & transisi halamanResmiNavigasi mulus tanpa jadi SPA โ beserta harga yang dibayar: skrip pihak ketiga, iklan, dan analitik yang berhenti bekerja diam-diam.docs.astro.buildBaca rangkuman โ
Kamu bisa membangun tabel data perusahaan yang bisa disortir dan difilter, tetap berfungsi tanpa JavaScript, dan tidak melewati anggaran JS halamannya.
Membership, Auth & Paywall
Tujuan: memindahkan member CI3 tanpa satu pun dari mereka perlu reset password, dan membangun paywall yang isinya benar-benar tidak pernah meninggalkan server untuk pembaca yang tidak berhak.
Paywall yang mengirim seluruh artikel lalu menutupinya dengan CSS bukan paywall. Ctrl+U membukanya, mode baca peramban membukanya, dan ekstensi yang menghapusnya tersedia gratis. Fase ini membangun yang sesungguhnya.
Materi
-
Sesi & cookie di AstroResmiSesi yang dibaca hanya saat dibutuhkan โ kebalikan dari CI3 โ plus atribut cookie yang menentukan apakah paywall-mu bisa dibobol.docs.astro.buildBaca rangkuman โ
-
Memindahkan password member dari CI3ArtikelMember tidak boleh diminta reset password gara-gara kamu ganti framework. Cara memverifikasi hash lama di Node dan meningkatkannya diam-diam.owasp.orgBaca rangkuman โ
-
Sesi bersama selama CI3 dan Astro hidup berdampinganArtikelci_sessions berisi data PHP-serialized yang tidak bisa dibaca Node. Tiga jalan keluar, dan yang mana yang benar untuk migrasi bertahap.owasp.orgBaca rangkuman โ
-
Membangun paywall yang tidak bisa dilewatiResmiPaywall yang menahan isi di server, tetap ramah Google, dan tidak menghancurkan cache edge โ satu komponen, tiga syarat.developers.google.comBaca rangkuman โ
-
Alur masuk, daftar & lupa sandiArtikelEmpat alur yang dipakai tiap hari dan paling sering bocor โ termasuk enumerasi akun, yang hampir semua portal Indonesia masih melakukannya.owasp.orgBaca rangkuman โ
-
Tier langganan & peran redaksiArtikelDua sistem izin yang berbeda dalam satu aplikasi โ hak baca berbasis langganan dan hak tulis berbasis peran โ dan cara menjaga keduanya tidak tercampur.owasp.orgBaca rangkuman โ
-
Rate limit & penyalahgunaan akunResmiDua lapis pembatas โ Cloudflare untuk yang kasar, aplikasi untuk yang butuh konteks โ plus deteksi akun berlangganan yang dipakai beramai-ramai.developers.cloudflare.comBaca rangkuman โ
curl tanpa cookie ke artikel premium tidak menemukan satu pun kalimat dari paragraf
kesepuluh โ dan hash password $2y$ dari PHP terverifikasi di Node lalu naik kelas
diam-diam saat member login.
Midtrans & Langganan
Tujuan: alur pembayaran yang benar meski webhook datang dua kali, terbalik urutannya, atau tidak datang sama sekali โ dan penagihan berulang yang tidak kehilangan pelanggan gara-gara kartu kedaluwarsa.
Aturan yang tidak bisa ditawar
| Aturan | Kalau dilanggar |
|---|---|
| Halaman "sukses" bukan bukti pembayaran | Siapa pun bisa membuka URL-nya tanpa membayar |
gross_amount dari database, bukan klien | Langganan setahun seharga seribu rupiah |
| Verifikasi tanda tangan atas raw body | Siapa pun bisa mengaktifkan langganan dengan curl |
| Pemrosesan idempoten | Satu pembayaran memperpanjang langganan dua kali |
| Webhook dikecualikan dari WAF | Pembayaran diblokir tanpa jejak di log aplikasi |
Materi
-
Snap โ alur checkout langgananResmiDari tombol Berlangganan sampai halaman pembayaran, dengan satu aturan yang tidak boleh dilanggar: jangan pernah percaya pada halaman sukses.docs.midtrans.comBaca rangkuman โ
-
Webhook: verifikasi tanda tangan atas raw bodyResmiEndpoint tempat uang benar-benar berpindah. Rumus SHA-512-nya, kenapa harus endpoint .ts bukan Action, dan lima syarat yang disebut Midtrans sendiri.docs.midtrans.comBaca rangkuman โ
-
Idempotensi & notifikasi yang datang tidak berurutanResmiWebhook akan datang dua kali, dan kadang terbalik urutannya. Cara membuat pemrosesannya benar dalam kedua kasus.docs.midtrans.comBaca rangkuman โ
-
Langganan berulang & penagihan otomatisResmiDua cara menagih otomatis di Midtrans, cara memilihnya, dan penanganan kegagalan penagihan yang menentukan berapa banyak pelanggan yang bertahan.docs.midtrans.comBaca rangkuman โ
-
Rekonsiliasi, refund & pertanyaan keuanganResmiAngka di databasemu harus cocok dengan angka di dashboard Midtrans. Cara membuktikannya tiap hari, dan apa yang dilakukan saat tidak cocok.docs.midtrans.comBaca rangkuman โ
-
Mengamankan jalur pembayaranResmiWAF yang memblokir webhook Midtrans, kunci yang bocor ke bundel klien, dan log yang menyimpan data yang seharusnya tidak โ tiga kesalahan yang mahal.developers.cloudflare.comBaca rangkuman โ
Mengirim notifikasi webhook yang sama tiga kali hanya memajukan langganan_sampai
sekali, dan settlement yang tiba sebelum pending tidak menurunkan status
yang sudah aktif.
Keamanan
Tujuan: menutup jalur serangan yang benar-benar ada di portal berita โ HTML artikel dari tiga generasi editor, endpoint buatan sendiri tanpa CSRF, dan rahasia yang bisa bocor ke bundel klien lewat satu impor.
Satu pertukaran yang harus kamu putuskan sadar: CSP bawaan Astro tidak kompatibel
dengan <ClientRouter /> dari Fase 4. Untuk portal berbayar, saranku CSP
yang menang โ transisi halaman adalah kenyamanan, XSS di halaman yang memegang sesi berbayar adalah
pengambilalihan akun.
Materi
-
Content Security PolicyResmiAstro bisa menghitung hash seluruh skrip dan gaya untukmu โ tapi fitur itu bertabrakan dengan ClientRouter, dan kamu harus memilih.docs.astro.buildBaca rangkuman โ
-
XSS & bahaya set:htmlArtikelAstro meng-escape otomatis โ kecuali di satu tempat yang justru kamu butuhkan untuk menampilkan artikel: set:html.owasp.orgBaca rangkuman โ
-
Injeksi SQL โ apa yang Kysely tutup, dan apa yang tidakArtikelKysely menutup hampir semua jalur injeksi secara struktural โ kecuali tiga, dan ketiganya ada di kode yang terlihat wajar.owasp.orgBaca rangkuman โ
-
CSRF & CORSArtikelDua hal yang sering dikira sama padahal berlawanan: CSRF membatasi siapa yang boleh bertindak atas namamu, CORS membatasi siapa yang boleh membaca jawabannya.owasp.orgBaca rangkuman โ
-
Rahasia, variabel lingkungan & astro:envResmiBatas antara yang boleh dilihat browser dan yang tidak โ ditegakkan oleh tipe, bukan oleh ingatan.docs.astro.buildBaca rangkuman โ
-
Header keamanan & tempat memasangnyaResmiTujuh header, dan keputusan yang lebih penting dari isinya: dipasang di Cloudflare atau di Astro?developer.mozilla.orgBaca rangkuman โ
-
Dependensi & rantai pasokResmiProyek Astro tipikal menarik ratusan paket transitif. Cara membatasi risikonya tanpa berhenti memakai npm sama sekali.docs.npmjs.comBaca rangkuman โ
Membuat PR yang mengimpor server key Midtrans ke komponen Vue akan menggagalkan build, dan daftar payload XSS standar tidak ada satu pun yang lolos sanitizer-mu.
Cloudflare: Cache, Edge & WAF
Tujuan: menaikkan cache hit ratio dari 60% ke 92โ95%, memangkas beban origin lima sampai enam kali lipat, dan memastikan seluruh lapisan Cloudflare tidak bisa dilewati begitu saja.
Target yang bisa diukur
| Sekarang | Setelah fase ini | |
|---|---|---|
| Cache hit ratio | 60% | 92โ95% |
| Request ke origin | 500.000 / jam | ~75.000 / jam |
| Rata-rata req/detik ke origin | 139 | ~21 |
| Egress AWS | ~10,8 TB/bulan | ~1,6 TB/bulan |
Satu hal yang sering luput diperiksa: kalau ALB-mu punya IP publik yang bisa dihubungi
langsung, seluruh WAF, rate limit, dan bot protection-mu opsional โ dan
cf-connecting-ip yang kamu pakai untuk rate limiting bisa dipalsukan. Situsnya bekerja
sempurna meski salah, jadi tidak ada yang menyadarinya.
Materi
-
Apa yang Cloudflare cache secara bawaanResmiCloudflare tidak meng-cache HTML secara bawaan โ dan itu penjelasan lengkap kenapa 500 ribu request per jam sampai ke origin-mu.developers.cloudflare.comBaca rangkuman โ
-
Cache Rules โ membuat HTML ter-cacheResmiAturan yang menaikkan cache hit ratio dari 60% ke 93% โ beserta satu aturan yang harus ada lebih dulu supaya paywall-mu tidak bocor.developers.cloudflare.comBaca rangkuman โ
-
Purge selektif dengan Cache TagResmiSaat editor menyunting artikel, satu tag di-purge โ bukan seluruh situs. Termasuk kenapa Purge Everything adalah tombol yang berbahaya di trafikmu.developers.cloudflare.comBaca rangkuman โ
-
Cache key, Vary & kebocoran antar pembacaResmiKesalahan paling mahal di seluruh roadmap ini: satu respons personal yang tersimpan di edge dan tersaji ke ribuan orang lain.developers.cloudflare.comBaca rangkuman โ
-
Tiered Cache, Cache Reserve & arsip lamaResmiDua fitur yang paling menguntungkan portal berita dengan arsip besar โ dan satu yang tagihannya bisa mengejutkan.developers.cloudflare.comBaca rangkuman โ
-
Gambar & video di portal beritaResmiOptimasi gambar Astro tidak berlaku untuk gambar dari database โ dan gambar adalah bagian terbesar dari bandwidth portalmu.docs.astro.buildBaca rangkuman โ
-
WAF, bot & crawler yang harus tetap masukResmiPortal berita hidup dari crawler. Memblokir bot terlalu agresif berarti memblokir Google โ dan itu terlihat sebagai trafik yang hilang, bukan sebagai error.developers.cloudflare.comBaca rangkuman โ
-
Menutup origin โ WAF yang bisa dilewati bukan WAFResmiKalau ALB-mu punya IP publik, seluruh WAF, rate limit, dan bot protection-mu bisa dilewati dengan satu perintah curl.developers.cloudflare.comBaca rangkuman โ
Halaman artikel mengembalikan cf-cache-status: HIT termasuk dengan parameter
?utm_source=, jalur /akun selalu BYPASS, dan menghubungi IP
origin langsung tidak menghasilkan apa pun.
Migrasi dari CodeIgniter 3
Tujuan: memindahkan portal yang sudah hidup, sepotong demi sepotong, dengan rollback semudah menonaktifkan satu aturan Cloudflare โ tanpa kehilangan satu pun URL yang sudah terindeks.
Urutan pemindahan
| Tahap | Yang dipindah | Kenapa urutan ini |
|---|---|---|
| 1 | Halaman statis | Membuktikan pipeline deploy bekerja |
| 2 | Login, daftar, akun | Sesi bersama harus hidup sebelum yang lain |
| 3 | Halaman artikel | Volume terbesar; di sini keuntungan cache muncul |
| 4 | Beranda & kategori | Setelah artikel terbukti stabil |
| 5โ6 | Data perusahaan, lalu langganan | Yang menyentuh uang paling akhir |
| 7โ8 | Panel redaksi, lalu matikan CI3 | Setelah berminggu-minggu tanpa trafik |
Materi
-
Strangler: CI3 dan Astro berdampinganResmiMemindahkan portal per bagian, dengan rollback semudah mengubah satu aturan โ dan urutan pemindahan yang meminimalkan risiko.developers.cloudflare.comBaca rangkuman โ
-
Peta URL lama & redirect 301ResmiPuluhan ribu URL terindeks yang tidak boleh mati. Cara memetakannya, melayaninya dengan cepat, dan membuktikan tidak ada yang terlewat.developers.google.comBaca rangkuman โ
-
SEO portal berita saat migrasiResmiKanonik, sitemap berita, data terstruktur, dan tiga hal khusus Google News yang tidak berlaku untuk situs biasa.developers.google.comBaca rangkuman โ
-
Dari MySQL FULLTEXT ke mesin pencariResmiKenapa LIKE '%kata%' menjatuhkan database di trafikmu, apa yang bisa diselamatkan dengan FULLTEXT, dan kapan harus pindah.dev.mysql.comBaca rangkuman โ
-
Membersihkan data & konten warisanResmiCharset yang salah, HTML dari tiga generasi CMS, dan berkas yatim โ pekerjaan yang tidak terlihat sampai kamu mulai.dev.mysql.comBaca rangkuman โ
-
Uji paritas โ membuktikan Astro sama benarnyaResmiSebelum memindahkan trafik, buktikan halaman baru menghasilkan hal yang sama dengan yang lama โ secara otomatis, untuk ribuan URL.docs.astro.buildBaca rangkuman โ
-
Runbook cutover & rollbackResmiDokumen yang dibaca saat semua orang panik. Langkah, ambang batal, dan siapa yang memutuskan.developers.cloudflare.comBaca rangkuman โ
Seluruh daftar URL lama dari log akses mengembalikan 301 ke tujuan akhir tanpa rantai, dan uji paritas terhadap seribu URL nyata tidak menghasilkan satu pun selisih pada status, kanonik, dan JSON-LD.
Deploy di AWS
Tujuan: menjalankan Astro di AWS dengan deploy tanpa satu pun 5xx, rollback dalam dua menit, dan kapasitas yang dihitung dari angka trafikmu โ bukan ditebak.
Hitungan kapasitas
Ke origin setelah cache diperbaiki : ~24 req/detik rata-rata
Puncak (2,5โ3ร) : ~70 req/detik
45 req/dtk halaman ร 35 ms = 1,58 detik-CPU/detik
25 req/dtk island ร 8 ms = 0,20 detik-CPU/detik
รท target 60%
= 3 task, + margin AZ = 5
Batas ATAS bukan dari CPU, tapi dari max_connections RDS.
Materi
-
Node adapter & bentuk hasil buildResmiApa persisnya yang keluar dari pnpm build, apa yang perlu dibawa ke container, dan cara mematikannya dengan benar saat ECS menghentikan task.docs.astro.buildBaca rangkuman โ
-
Dockerfile multi-stageResmiImage yang kecil, membangun cepat, dan tidak berjalan sebagai root โ plus urutan layer yang membuat build ulang hitungan detik.docs.docker.comBaca rangkuman โ
-
ECS Fargate โ task definition & serviceResmiDefinisi task yang benar untuk Astro, beserta enam pengaturan yang menentukan apakah deploy-mu mulus atau menghasilkan 502.docs.aws.amazon.comBaca rangkuman โ
-
VPC, subnet & jalur keluarResmiTata letak jaringan yang benar โ dan NAT Gateway, komponen yang tagihannya paling sering mengejutkan orang.docs.aws.amazon.comBaca rangkuman โ
-
CI/CD dengan GitHub ActionsResmiPipeline yang menolak kode yang salah sebelum sempat di-deploy โ termasuk pemeriksaan yang khusus dibutuhkan portal berbayar.docs.aws.amazon.comBaca rangkuman โ
-
Autoscaling & menghitung kapasitasResmiBerapa task yang benar-benar kamu butuhkan untuk 1,25 juta request per jam โ dihitung dari angkamu, bukan dari tebakan.docs.aws.amazon.comBaca rangkuman โ
-
Mengoperasikan RDS MySQLResmiParameter group, cadangan yang benar-benar bisa dipulihkan, dan failover yang sudah dilatih โ bukan yang diharapkan bekerja.docs.aws.amazon.comBaca rangkuman โ
-
Log, metrik & alarmResmiLog terstruktur yang bisa dikueri, metrik yang benar-benar dibaca, dan alarm yang tidak diabaikan orang.docs.aws.amazon.comBaca rangkuman โ
-
Tugas terjadwal & pekerjaan latarResmiCron yang berjalan sekali, bukan sebanyak jumlah task โ dan daftar pekerjaan latar yang dibutuhkan portalmu.docs.aws.amazon.comBaca rangkuman โ
Menjalankan uji beban sambil melakukan deploy menghasilkan nol 5xx, dan container yang menerima
SIGTERM di tengah request lambat menyelesaikannya lalu keluar dengan kode 0.
Performa & Capstone
Tujuan: membuktikan portalnya cepat dengan data lapangan pembaca sungguhan, mengetahui di mana titik patahnya, dan menyelesaikan capstone yang menggabungkan seluruh roadmap.
Target akhir
| Metrik | Target |
|---|---|
| Cache hit ratio | > 90% |
| p95 render origin | < 150 ms |
| p95 server island | < 50 ms |
| JS halaman artikel | < 45 KB gzip |
| LCP / CLS (lapangan) | < 2,5 dtk / < 0,1 |
| Uji beban 2ร puncak | Nol 5xx |
| Kebocoran isi premium | Nol |
Materi
-
Core Web Vitals untuk portal beritaResmiTiga metrik yang dinilai Google, apa yang benar-benar memperbaikinya di halaman artikel, dan kenapa data lapangan berbeda dari Lighthouse.web.devBaca rangkuman โ
-
Mengukur waktu render & kueriResmiAngka yang kamu butuhkan untuk menghitung kapasitas โ dan cara menemukan bagian mana dari satu halaman yang sebenarnya mahal.nodejs.orgBaca rangkuman โ
-
Uji beban ke angka trafikmuResmiMembuktikan portal barumu sanggup sebelum pembaca membuktikannya untukmu โ dengan skenario yang benar-benar menyerupai trafik portal berita.grafana.comBaca rangkuman โ
-
Biaya & runbook insidenResmiMembuktikan migrasi ini menghemat uang, dan menyiapkan diri untuk saat semuanya tetap rusak.docs.aws.amazon.comBaca rangkuman โ
-
Keputusan yang akan kamu tinjau ulangResmiEnam keputusan di roadmap ini yang benar hari ini dan mungkin tidak benar dalam dua tahun โ beserta sinyal yang memberitahumu kapan meninjaunya.docs.astro.buildBaca rangkuman โ
-
Capstone: portal berita berbayar, ujung ke ujungResmiSpesifikasi lengkap yang menggabungkan seluruh roadmap โ dengan kriteria penerimaan yang bisa diverifikasi, bukan yang "kelihatannya jalan".docs.astro.buildBaca rangkuman โ
Seluruh perintah verifikasi di halaman capstone berjalan hijau โ kebenaran, cache, pembayaran, keamanan, performa, dan operasional.
Rekomendasi best practice
Delapan belas aturan yang muncul berulang di seluruh roadmap ini. Kalau kamu hanya sempat mengingat satu halaman, ingat yang ini.
- Halaman yang di-cache tidak boleh menyentuh cookie. Satu pembacaan sesi mengubah halaman jadi personal โ dan kalau kamu lupa mematikan cache-nya, halaman satu member tersaji ke member lain.
- Isi berbayar tidak pernah diambil kalau haknya belum terbukti. Bukan diambil lalu
disembunyikan. Kueri isi lengkap hanya berjalan setelah
hak.boleh === true. - Server island untuk yang personal, halaman untuk yang sama bagi semua orang. Ini satu-satunya cara paywall dan cache CDN hidup berdampingan.
- Pasang
ASTRO_KEYtetap sebelum deploy pertama. Tanpanya, tiap rolling deploy menghasilkan lima menit island yang gagal โ dan sudah pulih saat kamu memeriksanya. - Kirim ID sebagai props island, bukan data. Melewati 2048 byte membuat Astro beralih ke POST, yang tidak di-cache browser sama sekali.
- Hanya
src/lib/yang menyentuh database. Bukan kerapian: ia yang membuat filterstatus = 'terbit'tidak bisa terlupa, dan yang membuat jalur data bisa diubah nanti tanpa menyentuh halaman. - Batasi operasi tulis lewat
WHERE, bukan lewatif.WHERE id = ? AND penulis_id = ?membuat baris orang lain tidak pernah ditemukan โ pertahanan yang tidak bisa lupa dipasang. - Hitung
connectionLimituntuk jumlah task maksimum. Autoscaling yang tidak memperhitungkan ini akan menjatuhkan database tepat saat trafik memuncak. - Transaksi hanya berisi kueri database, dan sependek mungkin. Satu panggilan HTTP di dalamnya bisa menahan baris terkunci selama lima detik dan menghabiskan pool.
- Timeout di setiap lapisan, mengecil ke dalam. Cloudflare > ALB > Node > kueri. Kalau lapisan dalam lebih longgar, klien menyerah sementara kuerinya tetap bekerja untuk tidak ada siapa-siapa.
- Validasi di batas sistem, selalu. Tipe TypeScript dihapus saat build; hanya Zod yang benar-benar memeriksa data dari API, form, cookie, dan variabel lingkungan.
- Verifikasi tanda tangan webhook atas raw body, dengan perbandingan
waktu-tetap. Dan jangan pernah mengonversi
gross_amountโ ia string. - Webhook harus idempoten dan dikecualikan dari WAF. Ia akan datang dua kali, dan managed rules akan memblokirnya tanpa jejak di log aplikasimu.
stale-while-revalidatedanstale-if-erroryang panjang adalah jaring pengamanmu. Origin tumbang total tetap menyisakan portal yang menyajikan artikel dari edge.- Purge by tag, jangan Purge Everything. Di trafikmu, mengosongkan cache berarti mengirim 16 kali beban normal ke origin sekaligus.
- Kunci origin-mu. IP yang bisa dihubungi langsung membuat seluruh lapisan Cloudflare โ WAF, rate limit, bot protection โ jadi opsional.
- Migrasi skema harus kompatibel dua arah selama CI3 masih hidup. Menghapus satu kolom lebih awal mengubah rollback dari "ubah satu aturan" jadi "pulihkan database".
- Matikan cron di sistem lama saat cutover. Ini yang paling sering terlupa, dan akibatnya newsletter ganda โ atau penagihan ganda.
Kesalahan yang paling mahal
| Kesalahan | Akibatnya | Dibahas di |
|---|---|---|
Halaman personal ditandai public di CDN | Data satu member tersaji ke member lain | Fase 1, 8 |
| Isi premium dikirim lalu disembunyikan CSS | Paywall bisa dilewati Ctrl+U | Fase 5 |
| Endpoint JSON lupa memeriksa hak | Paywall bocor lewat pintu belakang | Fase 3, 5 |
gross_amount dari input klien | Langganan setahun seharga seribu rupiah | Fase 6 |
| Webhook diblokir WAF | Pembayaran tidak tercatat, tanpa jejak di log | Fase 6, 8 |
| Halaman "sukses" mengaktifkan langganan | Siapa pun bisa berlangganan gratis | Fase 6 |
| IP origin bisa dihubungi langsung | Seluruh WAF terlewati; rate limit jebol | Fase 8 |
ASTRO_KEY tidak tetap | Island gagal tiap deploy, pulih sendiri | Fase 1, 10 |
keepAliveTimeout < idle timeout ALB | 502 acak tanpa jejak di log aplikasi | Fase 10 |
| Sesi di memori proses | Member ter-logout acak | Fase 5 |
| Migrasi di entrypoint container | Dua belas task menjalankannya bersamaan | Fase 2, 10 |
| Health check ALB menyentuh database | Gangguan sebagian jadi pemadaman total | Fase 10 |
| Cron di dalam service web | Job berjalan sebanyak jumlah task | Fase 10 |
| Redirect 302 untuk migrasi URL | Sinyal peringkat tidak berpindah; trafik turun perlahan | Fase 9 |
| Konversi charset pada data yang sudah rusak | Kerusakan terkunci permanen | Fase 9 |
sql.raw() menerima input dari luar | Injeksi SQL | Fase 7 |
Satu hal yang tidak akan diselesaikan infrastruktur: halaman yang butuh empat puluh kueri dan
mengirim dua megabita HTML tetap mahal di runtime mana pun, di belakang CDN mana pun. Ukur dulu, baru
belanja โ dan di roadmap ini, "ukur" berarti EXPLAIN, Server-Timing, dan
cache hit ratio, bukan perasaan.
Aturan main
- Bangun, jangan cuma baca. Setiap materi di sini punya latihan konkret di akhirnya; latihan itu yang membuatnya melekat.
- Ukur sebelum dan sesudah. Hampir setiap klaim performa di roadmap ini bisa kamu buktikan sendiri dalam sepuluh menit โ lakukan.
- Pakai angka portalmu sendiri. Angka trafik, waktu render, dan biaya di sini adalah contoh. Yang menentukan keputusanmu adalah milikmu.
- Satu perubahan pada satu waktu. Menaikkan versi Astro dan mengubah adapter bersamaan membuat hasilnya tidak bisa dibaca.
- Uji di
pnpm preview, bukanpnpm dev. Bug yang hanya muncul di produksi hampir selalu sudah terlihat di sana. - Jangan lompat ke Fase 10. Deploy ke AWS sebelum cache-nya benar hanya memindahkan tagihan.
- Hapus resource AWS setelah berlatih. RDS, NAT Gateway, dan ElastiCache ditagih per jam, dipakai atau tidak.
- Uji pemulihan cadangan, jangan cuma membuatnya. Cadangan yang tidak pernah dipulihkan bukan cadangan.
Sebelum & sesudah ini
Roadmap ini mengandaikan kamu sudah pernah menulis kode dan paham dasar HTTP serta SQL. Kalau belum pernah ngoding sama sekali, mulai dari Python Dasar untuk Pemula. Kalau kamu ingin mendalami sisi AWS-nya lebih jauh โ IAM, IaC, observability โ AWS untuk AI Engineer membahasnya dengan sudut pandang berbeda. Dan kalau kamu penasaran bagaimana bahasa lain menyelesaikan masalah yang sama di skala yang sama, Go dari Nol sampai Enterprise dan Laravel dari Nol sampai Enterprise menempuh jalur paralel dengan pertukaran yang sangat berbeda.