Cara Kami Melayani Ribuan View Halaman Bio-Link di Single VPS (Tanpa Microservices)
Pelajari bagaimana Trakk.id menangani lonjakan trafik besar pada satu VPS menggunakan arsitektur pemisahan read/write dengan Redis dan Nginx.

Cara Kami Melayani Ribuan View Halaman Bio-Link di Single VPS (Tanpa Microservices)
Halaman bio-link (situs mikro "link in bio" yang digunakan kreator) terlihat sederhana di permukaan — hanya halaman statis dengan beberapa tombol. Namun, pola trafiknya cukup menantang: semuanya normal, lalu seorang kreator membagikan link di media sosial dan server Anda tiba-tiba dibanjiri ribuan permintaan dalam hitungan menit.
Di Trakk.id, kami menjalankan fitur ini (trakk.id/l/:slug) pada satu VPS — tanpa cluster Kubernetes, tanpa armada microservices. Berikut adalah arsitektur yang memungkinkan hal tersebut, dan dua masalah utama yang harus kami selesaikan.
Masalah: Dua Beban yang Saling Beradu pada Setiap Request
Setiap kunjungan halaman sebenarnya menciptakan dua pekerjaan untuk backend Anda:
- Beban Baca (Read) — menyajikan HTML dan aset statis (foto profil, latar belakang) secepat mungkin.
- Beban Tulis (Write) — mencatat impresi untuk dashboard analitik kreator.
Pendekatan naif — merender halaman pada setiap request dan menulis impresi langsung ke Postgres — mungkin bekerja saat trafik rendah, namun akan tumbang tepat saat Anda paling membutuhkannya: ketika trafik melonjak. Setiap request membangunkan app server, mengakses database, dan Anda berakhir dengan lock contention serta latensi yang melonjak tinggi tepat saat sebuah link menjadi viral.
Solusinya adalah memisahkan jalur baca dan jalur tulis sepenuhnya.
ℹ️ Prinsip Arsitektur
Dengan memisahkan jalur baca frekuensi tinggi dari jalur tulis yang intensif, kami memastikan lonjakan trafik tidak membuat database tumbang atau memperlambat penyajian halaman bagi pengguna.
Penyajian: Jangan Biarkan Request Menyentuh App Server Sama Sekali
Alih-alih merender halaman bio-link secara dinamis pada setiap request, kami melakukan pre-render menjadi HTML statis setiap kali kreator memperbarui halaman mereka dari dashboard. Trafik publik tidak pernah menyentuh backend Node.js/Fastify kami — Nginx menyajikan HTML yang sudah di-cache tersebut langsung di edge.
Dua konsekuensi dari hal ini:
- Penggunaan vCPU tetap stabil saat lonjakan trafik, karena tidak ada pekerjaan rendering yang terjadi per request.
- Aset yang diunggah pengguna (avatar, tema kustom) disimpan di object storage yang kompatibel dengan S3 (kami menggunakan IDCloudHost untuk alasan residensi data), bukan di disk lokal — sehingga I/O file besar tidak pernah berebut sumber daya dengan app server.
Lapisan API adalah satu-satunya bagian yang pernah menyentuh kredensial penyimpanan; jalur penyajian publik tidak memiliki akses sama sekali ke sana.
Analitik: Berhenti Menulis ke Postgres pada Setiap Kunjungan
Ini adalah masalah yang lebih menarik. Pelacakan impresi harus bersifat real-time-ish untuk dashboard, tetapi Anda tidak mampu melakukan penulisan database per kunjungan ketika sebuah halaman mungkin mendapatkan 50.000 kunjungan dalam lima menit.
Solusi kami: in-memory counting + batched flushes.
kunjungan halaman → Redis INCR biolink:impression:{slug} (< 1ms, tanpa akses DB)
setiap 5 menit:
cron worker → membaca semua counter dari Redis
→ menulis batch ke Postgres dalam satu transaksi
→ mereset counter Redis ke nol
Wawasan utamanya: INCR pada kunci Redis adalah O(1) dan tidak peduli apakah itu kenaikan ke-1 atau ke-50.000 dalam jendela waktu tersebut. Postgres hanya melihat satu penulisan per slug per jendela 5 menit, tidak peduli berapa banyak orang yang berkunjung. Hal inilah yang menjaga latensi tetap stabil di bawah beban tinggi tanpa perlu melakukan scaling database secara vertikal.
Catatan Singkat tentang Keamanan di Sisi Edge
Karena halaman-halaman ini dirender dan disajikan secara publik, kami menyetel X-Frame-Options: SAMEORIGIN pada setiap respon. Ini memungkinkan dashboard kami sendiri untuk melihat pratinjau halaman kreator dalam iframe, tetapi memblokir situs pihak ketiga mana pun untuk menyematkannya — menutup celah serangan clickjacking umum di mana penyerang menumpuk link tersembunyi di atas halaman yang di-iframe.
Kesimpulan
Anda tidak memerlukan cluster microservices untuk mencapai performa kelas enterprise. Yang Anda butuhkan adalah mengidentifikasi dengan benar bagian mana dari beban kerja Anda yang berat di sisi baca vs berat di sisi tulis, dan memberikan arsitektur yang sesuai untuk masing-masing:
- Jalur Baca → pre-render + edge caching, sehingga app server hampir tidak perlu bekerja.
- Jalur Tulis → in-memory counters + batch flush, sehingga database hanya melihat sebagian kecil dari trafik sebenarnya.
Dengan pemisahan tersebut, satu VPS yang dikonfigurasi dengan baik yang menjalankan Nginx + Node.js + Redis + Postgres mampu mempertahankan waktu respon di bawah 50ms melalui lonjakan trafik yang seharusnya akan melumpuhkan setup naif.
Kami telah menyusun arsitektur lengkapnya — termasuk setup isolasi aset S3 dan detail lebih lanjut tentang lapisan caching — dalam whitepaper teknis, tersedia di sini, jika Anda ingin mempelajarinya lebih dalam.
Punya pertanyaan atau masukan mengenai keputusan arsitektur ini? Kami ingin mendengar bagaimana Anda menyelesaikan masalah pemisahan read/write serupa — hubungi tim kami.
Artikel ini juga tersedia dalam English
