Website Sangat Hemat Biaya dengan Hugo + S3 + CloudFront + Cloudflare
Masih banyak perusahaan yang membangun website company profile atau blog di atas stack yang sebenarnya jauh terlalu berat: server aplikasi selalu aktif, database, autoscaling group, load balancer, dan tim ops yang harus siaga. Untuk website yang kontennya jarang berubah dan tidak membutuhkan interaksi real-time, semua lapisan itu tidak memberikan nilai — hanya biaya.
Pendekatan yang lebih masuk akal adalah memindahkan seluruh kompleksitas ke build time, bukan runtime. Artinya, server hanya terlibat saat konten baru diterbitkan — bukan setiap kali user membuka halaman. Stack yang mewujudkan ini: Hugo → S3 → CloudFront → Cloudflare. Arsitektur ini sudah terbukti stabil untuk blog teknis, company profile, dokumentasi, hingga portal berita berbasis konten.
Gambaran Besar Arsitektur
graph TB
subgraph "Content Creation Layer (Internal Only)"
Editor["Admin / Editor"] --> AdminUI["Admin Panel<br/>(Internal tool)"]
AdminUI -->|"Simpan / Publish"| HugoSvc["Hugo Service<br/>(Build engine)"]
end
subgraph "Build & Deploy Pipeline"
HugoSvc -->|"hugo build"| Static["Static Files<br/>(HTML, CSS, JS)"]
Static -->|"aws s3 sync"| S3["Amazon S3<br/>(Object Storage)"]
Static -->|"Invalidate cache"| CFront["CloudFront<br/>(AWS CDN)"]
end
subgraph "Edge & Security Layer"
CF["Cloudflare<br/>DNS, WAF, DDoS Protection,<br/>Edge Cache"]
end
subgraph "User Access (No Server Involved)"
User["Visitor / User"] --> CF
CF -->|"Cache hit"| User
CF -->|"Cache miss"| CFront
CFront -->|"Cache hit"| User
CFront -->|"Cache miss"| S3
S3 --> CFront
end
style Editor fill:#f5f5f4,stroke:#78716c,color:#000
style AdminUI fill:#f5f5f4,stroke:#78716c,color:#000
style HugoSvc fill:#fef3c7,stroke:#d97706,color:#000
style Static fill:#fef3c7,stroke:#d97706,color:#000
style S3 fill:#bfdbfe,stroke:#2563eb,color:#000
style CFront fill:#bfdbfe,stroke:#2563eb,color:#000
style CF fill:#fef3c7,stroke:#d97706,color:#000
style User fill:#f5f5f4,stroke:#78716c,color:#000Kuncinya ada di bagian bawah diagram: tidak ada server yang terlibat saat user mengakses halaman. Semua yang dilihat user sudah menjadi file statis yang di-cache di edge node terdekat — baik di Cloudflare maupun CloudFront. S3 hanya disentuh saat terjadi cache miss, dan itu pun sangat jarang untuk konten yang jarang berubah.
Peran Setiap Komponen
Admin Panel dan Hugo Service — Hanya untuk Internal
Layer ini adalah satu-satunya bagian yang bersifat dinamis, dan hanya digunakan oleh tim internal (admin, editor, content creator). Tidak pernah terekspos ke publik.
graph LR
subgraph "Alur Penerbitan Konten"
Write["Editor menulis<br/>di Admin Panel"]
Save["Klik Publish"]
Trigger["Admin Panel trigger<br/>Hugo Service"]
Build["Hugo Service menjalankan<br/>hugo build"]
Upload["Upload ke S3<br/>Invalidate CloudFront"]
Live["Konten live<br/>di seluruh edge"]
end
Write --> Save --> Trigger --> Build --> Upload --> Live
style Write fill:#f5f5f4,stroke:#78716c,color:#000
style Save fill:#f5f5f4,stroke:#78716c,color:#000
style Trigger fill:#fef3c7,stroke:#d97706,color:#000
style Build fill:#fef3c7,stroke:#d97706,color:#000
style Upload fill:#bfdbfe,stroke:#2563eb,color:#000
style Live fill:#bbf7d0,stroke:#16a34a,color:#000Hugo Service tidak berjalan sebagai tool manual — ia adalah service yang dipicu secara programatik: bisa via API call dari admin panel, message queue, atau webhook dari CMS. Ia menerima instruksi “generate ulang”, menjalankan hugo build, dan menghasilkan file statis terbaru. Setelah itu, pekerjaannya selesai dan tidak perlu standby.
Karena tidak diakses publik dan hanya aktif saat ada konten baru, Hugo Service tidak perlu high availability, tidak perlu auto-scaling, dan bisa berjalan sebagai container kecil yang non-permanen.
Amazon S3 — Penyimpanan File Statis
S3 adalah tempat hasil build Hugo disimpan. Dari perspektif S3, tidak ada perbedaan antara menyimpan artikel blog dengan menyimpan file gambar — semuanya hanyalah objek yang bisa di-serve via HTTP.
Yang membuat S3 menarik untuk use case ini:
| Aspek | Detail |
|---|---|
| Biaya storage | USD 0.023 per GB/bulan (ap-southeast-1) |
| Biaya GET request | USD 0.0004 per 1.000 request |
| Downtime | SLA 99.99% availability |
| Maintenance | Nol — fully managed |
| Scaling | Otomatis, tidak perlu konfigurasi |
S3 tidak tahu apa itu “artikel” atau “halaman” — ia hanya menyajikan file. Dan justru karena itu, S3 sangat murah dan sangat stabil.
Origin Access Control (OAC) memastikan S3 bucket tidak pernah perlu dibuat public — hanya CloudFront yang boleh mengaksesnya. User tidak pernah berinteraksi langsung dengan S3.
CloudFront — CDN Native AWS
CloudFront adalah lapisan CDN yang duduk di antara S3 dan Cloudflare. Perannya adalah mendistribusikan file statis ke edge location AWS yang tersebar di seluruh dunia, sehingga user mendapatkan konten dari server yang secara geografis terdekat.
graph LR
S3["S3 Origin<br/>(ap-southeast-1)"]
subgraph "CloudFront Edge Locations"
SEA["Singapore PoP"]
JP["Tokyo PoP"]
US["Virginia PoP"]
EU["Frankfurt PoP"]
end
S3 --> SEA & JP & US & EU
UserSEA["User di Indonesia"] --> SEA
UserJP["User di Jepang"] --> JP
UserUS["User di Amerika"] --> US
UserEU["User di Eropa"] --> EU
style S3 fill:#bfdbfe,stroke:#2563eb,color:#000
style SEA fill:#bbf7d0,stroke:#16a34a,color:#000
style JP fill:#bbf7d0,stroke:#16a34a,color:#000
style US fill:#bbf7d0,stroke:#16a34a,color:#000
style EU fill:#bbf7d0,stroke:#16a34a,color:#000CloudFront juga menangani TLS termination (HTTPS), cache behavior per path (misalnya: cache HTML 5 menit, cache JS/CSS 1 tahun karena ada content hash di nama file), dan integrasi IAM dengan S3 via Origin Access Control.
Cloudflare — Shield Layer di Paling Depan
Cloudflare ditempatkan di depan CloudFront — bukan menggantikannya. Ini sering terlihat redundant, tapi keduanya memiliki peran yang berbeda dan saling melengkapi.
graph LR
subgraph "Cloudflare (Shield)"
DNS["DNS Resolution"]
WAF["WAF<br/>(Web Application Firewall)"]
DDoS["DDoS Protection"]
Bot["Bot Management"]
EdgeCache["Edge Cache<br/>(Free CDN global)"]
end
subgraph "CloudFront (AWS Native)"
OAC["Origin Access Control"]
CacheBehavior["Cache behavior per path"]
TLS["TLS termination"]
Compression["Gzip / Brotli compression"]
end
Internet["Internet Traffic"] --> DNS --> WAF --> DDoS --> Bot --> EdgeCache
EdgeCache -->|"Cache miss"| CacheBehavior --> OAC --> TLS --> S3["S3"]
style Internet fill:#f5f5f4,stroke:#78716c,color:#000
style DNS fill:#fef3c7,stroke:#d97706,color:#000
style WAF fill:#fef3c7,stroke:#d97706,color:#000
style DDoS fill:#fef3c7,stroke:#d97706,color:#000
style Bot fill:#fef3c7,stroke:#d97706,color:#000
style EdgeCache fill:#fef3c7,stroke:#d97706,color:#000
style OAC fill:#bfdbfe,stroke:#2563eb,color:#000
style CacheBehavior fill:#bfdbfe,stroke:#2563eb,color:#000
style TLS fill:#bfdbfe,stroke:#2563eb,color:#000
style Compression fill:#bfdbfe,stroke:#2563eb,color:#000
style S3 fill:#bfdbfe,stroke:#2563eb,color:#000Cloudflare menyaring traffic berbahaya sebelum mencapai infrastruktur AWS. Traffic yang lolos Cloudflare tapi ada di cache-nya tidak pernah sampai ke CloudFront — ini langsung mengurangi biaya AWS karena CloudFront billing berdasarkan jumlah request dan data transfer. Di free tier Cloudflare, semua proteksi DDoS, WAF dasar, dan CDN global sudah tersedia tanpa biaya.
Mengapa Arsitektur Ini Sangat Murah
Tidak Ada yang Perlu Dibayar saat Tidak Ada User
Ini adalah perbedaan fundamental dari arsitektur server-based. Pada arsitektur tradisional, server terus berjalan dan terus dibayar terlepas dari ada atau tidak ada pengunjung. Pada arsitektur statis ini, tidak ada komponen yang mengonsumsi biaya saat tidak ada request.
graph LR
subgraph "❌ Arsitektur Tradisional"
ServerAlways["EC2 / VM<br/>Selalu menyala<br/>Selalu dibayar"]
DB["Database<br/>Selalu menyala<br/>Selalu dibayar"]
LB["Load Balancer<br/>Selalu aktif<br/>Min USD 16/bulan"]
end
subgraph "✅ Arsitektur Statis"
S3Cost["S3<br/>Bayar per GB storage<br/>+ per GET request"]
CFCost["CloudFront<br/>Bayar per request<br/>+ per GB transfer"]
CFlareCost["Cloudflare<br/>Gratis di free tier"]
end
style ServerAlways fill:#fecaca,stroke:#dc2626,color:#000
style DB fill:#fecaca,stroke:#dc2626,color:#000
style LB fill:#fecaca,stroke:#dc2626,color:#000
style S3Cost fill:#bbf7d0,stroke:#16a34a,color:#000
style CFCost fill:#bbf7d0,stroke:#16a34a,color:#000
style CFlareCost fill:#bbf7d0,stroke:#16a34a,color:#000Estimasi Biaya Realistis
| Komponen | Model Biaya | Estimasi (blog/company profile medium) |
|---|---|---|
| S3 Storage | Per GB/bulan | < USD 1/bulan (untuk ratusan artikel) |
| S3 GET Requests | Per 1.000 request | < USD 1/bulan |
| CloudFront | Per request + transfer | USD 1–5/bulan |
| Cloudflare | Free tier | USD 0 |
| Hugo Service | Hanya saat publish | Hampir USD 0 (container non-permanen) |
| Total estimasi | — | USD 2–7/bulan |
Bandingkan dengan arsitektur WordPress atau CMS tradisional di atas VM:
| Pendekatan | Estimasi/Bulan | Biaya Idle |
|---|---|---|
| EC2 t3.small + RDS | USD 50–100 | Dibayar 24/7 |
| EC2 + Managed WordPress hosting | USD 20–50 | Dibayar 24/7 |
| Arsitektur Hugo + S3 + CDN ini | USD 2–7 | Hampir nol |
Untuk website dengan traffic tinggi (jutaan page view per bulan), biaya CloudFront dan bandwidth akan naik — tapi masih jauh lebih murah dibanding scaling EC2 + database untuk traffic yang sama.
Performa dan SEO — Keuntungan Bawaan
HTML statis yang di-serve dari CDN edge tidak hanya murah — ini juga cara tercepat untuk menyajikan halaman web. Tidak ada database query, tidak ada server-side rendering, tidak ada cold start. File sudah siap, tinggal dikirim.
graph LR
subgraph "Server-Side Rendering (Tradisional)"
Req1["Request"] --> Server1["Server"]
Server1 --> DB1["Query DB"]
DB1 --> Render1["Render template"]
Render1 --> Resp1["Response HTML"]
Latency1["Latency: 200ms - 2s+"]
end
subgraph "Static Site dari CDN Edge"
Req2["Request"] --> Edge["CDN Edge<br/>(geografis terdekat)"]
Edge --> Resp2["Response HTML<br/>(dari cache)"]
Latency2["Latency: 10-50ms"]
end
style Server1 fill:#fecaca,stroke:#dc2626,color:#000
style DB1 fill:#fecaca,stroke:#dc2626,color:#000
style Latency1 fill:#fecaca,stroke:#dc2626,color:#000
style Edge fill:#bbf7d0,stroke:#16a34a,color:#000
style Latency2 fill:#bbf7d0,stroke:#16a34a,color:#000Implikasi untuk SEO dan AdSense
| Aspek | Dampak pada Static Site |
|---|---|
| Core Web Vitals (LCP, FID, CLS) | Sangat baik — HTML sudah pre-rendered, tidak ada layout shift dari SSR |
| Time to First Byte (TTFB) | Sangat rendah — CDN edge response |
| Crawlability | Optimal — Googlebot langsung membaca HTML tanpa perlu render JS |
| Indexing | Cepat — tidak ada SPA rendering yang perlu di-wait |
| AdSense approval | Lebih mudah — konten HTML murni, tidak ada dynamic loading |
| JSON-LD / Structured Data | Mudah disisipkan di Hugo template |
Alur Build dan Deploy
Dua Mode yang Perlu Dihandle
Ada dua skenario yang berbeda dan perlu dipersiapkan berbeda juga:
graph TB
subgraph "Mode 1: Publish Konten Baru"
E1["Editor klik Publish"] --> T1["Admin Panel trigger Hugo Service"]
T1 --> B1["Hugo build (incremental atau full)"]
B1 --> U1["Sync ke S3 (hanya file berubah)"]
U1 --> I1["Invalidate CloudFront cache<br/>(path spesifik yang berubah)"]
I1 --> Live1["Konten live dalam 1-2 menit"]
end
subgraph "Mode 2: Update Template / Theme"
D1["Developer push ke repo"] --> CI1["CI/CD Pipeline"]
CI1 --> B2["Full hugo build"]
B2 --> U2["Full sync ke S3"]
U2 --> I2["Invalidate semua CloudFront cache"]
I2 --> Live2["Perubahan live"]
end
style E1 fill:#f5f5f4,stroke:#78716c,color:#000
style T1 fill:#fef3c7,stroke:#d97706,color:#000
style B1 fill:#fef3c7,stroke:#d97706,color:#000
style U1 fill:#bfdbfe,stroke:#2563eb,color:#000
style I1 fill:#bfdbfe,stroke:#2563eb,color:#000
style Live1 fill:#bbf7d0,stroke:#16a34a,color:#000
style D1 fill:#f5f5f4,stroke:#78716c,color:#000
style CI1 fill:#f5f5f4,stroke:#78716c,color:#000
style B2 fill:#fef3c7,stroke:#d97706,color:#000
style U2 fill:#bfdbfe,stroke:#2563eb,color:#000
style I2 fill:#bfdbfe,stroke:#2563eb,color:#000
style Live2 fill:#bbf7d0,stroke:#16a34a,color:#000Untuk publish konten baru, invalidasi CloudFront sebaiknya dilakukan hanya untuk path yang berubah (misal: /artikel/judul-baru/* dan /index.html) — bukan invalidasi semua cache. Ini lebih murah dan lebih cepat karena cache konten lain tidak perlu direfresh.
Trade-off dan Batasan
Arsitektur ini adalah pilihan yang sangat tepat untuk use case yang sesuai, tapi ada batasan nyata yang perlu dipahami.
Tidak Ada Fitur Dinamis di Runtime
Semua yang dihasilkan adalah HTML statis. Fitur yang membutuhkan logika server-side per request tidak bisa diimplementasikan secara native:
| Fitur | Bisa? | Solusi |
|---|---|---|
| Search | Terbatas | Algolia / Pagefind (client-side search) |
| Komentar | Tidak native | Disqus, Utterances (external service) |
| Form / Contact | Tidak native | Formspree, Netlify Forms, atau Lambda |
| Login / Auth | Tidak native | Butuh service terpisah |
| Konten per user | Tidak | Butuh SPA + API terpisah |
| Real-time update | Tidak | Butuh WebSocket / SSE terpisah |
Build Time Meningkat seiring Jumlah Konten
Hugo sangat cepat — ribuan halaman dalam hitungan detik. Tapi untuk website dengan ratusan ribu artikel, build time mulai terasa. Solusinya adalah incremental builds: Hugo hanya me-render ulang halaman yang kontennya berubah, bukan seluruh site.
Kompleksitas Admin Panel dan Hugo Service
Berbeda dengan WordPress yang sudah include CMS, arsitektur ini membutuhkan admin panel yang dibangun atau dipilih secara terpisah. Ini bisa berupa headless CMS (Contentful, Sanity, Forestry), custom admin panel, atau bahkan editing Markdown langsung di Git. Setiap pilihan punya trade-off sendiri.
| Trade-off | Dampak | Mitigasi |
|---|---|---|
| Tidak ada fitur dinamis native | Search, komentar perlu service eksternal | Algolia, Utterances, Formspree |
| Build time untuk site besar | Publish bisa memakan beberapa menit | Incremental builds Hugo |
| Admin panel perlu dibangun/dipilih | Effort awal lebih besar | Headless CMS atau Git-based editing |
| Preview sebelum publish lebih kompleks | Editor tidak bisa langsung preview | Hugo server mode + staging environment |
Cocok untuk Use Case Apa
graph LR
subgraph "Sangat Cocok"
G1["Company profile"]
G2["Blog engineering / marketing"]
G3["Documentation site"]
G4["News portal berbasis artikel"]
G5["Landing page kampanye"]
G6["Portfolio / personal site"]
end
subgraph "Perlu Evaluasi"
M1["Website dengan search kompleks<br/>(bisa dengan Algolia)"]
M2["Multi-bahasa dengan konten berbeda<br/>(Hugo support i18n)"]
M3["Konten yang sangat sering diupdate<br/>(build time jadi pertimbangan)"]
end
subgraph "Tidak Cocok"
B1["Aplikasi dengan login per user"]
B2["Dashboard dengan data real-time"]
B3["E-commerce dengan cart / checkout"]
B4["Forum / komunitas interaktif"]
end
style G1 fill:#bbf7d0,stroke:#16a34a,color:#000
style G2 fill:#bbf7d0,stroke:#16a34a,color:#000
style G3 fill:#bbf7d0,stroke:#16a34a,color:#000
style G4 fill:#bbf7d0,stroke:#16a34a,color:#000
style G5 fill:#bbf7d0,stroke:#16a34a,color:#000
style G6 fill:#bbf7d0,stroke:#16a34a,color:#000
style M1 fill:#fef3c7,stroke:#d97706,color:#000
style M2 fill:#fef3c7,stroke:#d97706,color:#000
style M3 fill:#fef3c7,stroke:#d97706,color:#000
style B1 fill:#fecaca,stroke:#dc2626,color:#000
style B2 fill:#fecaca,stroke:#dc2626,color:#000
style B3 fill:#fecaca,stroke:#dc2626,color:#000
style B4 fill:#fecaca,stroke:#dc2626,color:#000Penting dicatat: meski website utama butuh fitur dinamis (login, dashboard), konten statis tetap bisa dipisahkan. Blog engineering, dokumentasi publik, atau halaman marketing bisa menggunakan arsitektur ini secara independen, sementara bagian dinamis menggunakan stack yang berbeda.
Ringkasan
- Prinsip inti: pindahkan seluruh kompleksitas ke build time, bukan runtime. Server hanya terlibat saat konten baru diterbitkan — tidak saat user mengakses halaman.
- Stack: Hugo (build engine) → S3 (object storage) → CloudFront (AWS CDN) → Cloudflare (shield layer). Tidak ada VM, tidak ada database, tidak ada server runtime.
- Hugo Service bersifat non-permanen: hanya aktif saat ada trigger publish, bisa berjalan sebagai container kecil, tidak perlu high availability.
- Cloudflare + CloudFront bukan redundant: Cloudflare sebagai shield (WAF, DDoS, DNS, edge cache) sebelum traffic mencapai AWS, CloudFront sebagai native AWS CDN dengan Origin Access Control ke S3.
- Biaya estimasi: USD 2–7/bulan untuk blog atau company profile medium — dibandingkan USD 50–100+/bulan untuk stack VM + database tradisional.
- Performa: HTML statis dari CDN edge memiliki TTFB 10–50ms, sangat baik untuk Core Web Vitals, crawlability optimal untuk SEO, dan aman untuk AdSense.
- Batasan nyata: tidak ada fitur dinamis native (search perlu Algolia, komentar perlu layanan eksternal, tidak ada login per user). Ini bukan kekurangan untuk use case yang memang konten-statis.
- Cocok untuk: company profile, blog, dokumentasi, news portal artikel. Tidak cocok untuk aplikasi dengan login, real-time data, atau interaksi user yang kompleks.