SAINS API — Shared Backend untuk Platform Multi-Produk
Go backend yang men-serve satu stack auth, subscription, pembayaran, dan admin dashboard untuk 4 produk web (Atomic, Klinik, KontrakPro, Surat) dalam satu monorepo SAINS.
- Role
- Solo backend engineer / full-stack platform owner
- Ownership
- Solo builder untuk desain skema, handler, service, SQL, admin dashboard, integrasi Midtrans + SMTP, setup VPS + Cloudflare, serta dokumentasi PRD/TRD/Architecture.
- Team
- Solo project
- Period
- 2026
- Focus
- Backend, Web, Backend Developer
Overview
SAINS API adalah binary Go tunggal yang dirancang sebagai single source of truth untuk autentikasi, subscription, pembayaran Midtrans, dan operasi admin dari beberapa produk web konsumen di bawah payung SAINS. Backend ini di-deploy satu kali di VPS IDCloudHost dan di-hit oleh empat frontend web berbeda lewat query param product, sehingga setiap produk baru tidak perlu stack backend tersendiri dan tim produk bisa fokus pada experience per segmen.
Tech & Libraries
Teknologi dan library yang dipakai atau disentuh di project ini:
Problem
Beberapa produk SAINS butuh auth, paywall, dan dashboard admin dengan logika yang mirip, tetapi membangun backend terpisah per produk akan menghasilkan duplikasi kode, inkonsistensi kontrak API, dan biaya maintenance yang terus membesar. Selain itu platform ini butuh kontrol anti account-sharing dan akses guest yang viral-friendly tapi tetap bisa dipantau, sehingga model auth sederhana tidak cukup.
My Role & Ownership
Solo builder untuk desain skema, handler, service, SQL, admin dashboard, integrasi Midtrans + SMTP, setup VPS + Cloudflare, serta dokumentasi PRD/TRD/Architecture.
Technical Approach
Membangun satu binary Go 1.23 dengan Gin, pgx v5, dan sqlc untuk query type-safe, plus golang-migrate untuk schema evolution. Auth pakai JWT access token 1 jam dan refresh token httpOnly 30 hari, dengan single-session rule yang otomatis revoke session lama setiap login baru. Pembayaran memakai Midtrans Snap dengan webhook idempotent yang meng-aktifkan subscription setelah settlement.
Admin dashboard di-render server-side pakai go:embed HTML template, HTMX, dan Tabler CSS, jadi tidak butuh SPA terpisah dan deploy tetap satu binary. Semua handler mengikuti lapisan handler → service → repository (sqlc-generated) → PostgreSQL, dengan struktur admin dipecah modular per domain (auth, audience, user, guest_code, subscription, pricing, revenue, anomaly, product, audit) supaya perubahan di satu fitur tidak menyentuh fitur lain.
Architecture Notes
Backend dipecah menjadi dua permukaan route dalam satu proses: /api/* return JSON untuk semua frontend produk, /admin/* return HTML untuk dashboard berbasis HTMX. Setiap handler mengikuti lapisan handler → service → repository (sqlc-generated) → PostgreSQL, dengan model domain terpisah dari generated code agar logic tidak bocor ke lapisan SQL.
Multi-product by design: frontend mengirim ?product=atomic|klinik|kontrak|surat dan backend memetakan ke plan, quota, serta access-check yang sesuai tanpa kode khusus per produk. Admin panel dipecah modular per domain sehingga refactor di satu halaman tidak menyentuh halaman lain, dan shared components (layout.html, helpers.go seperti formatIDR, uuidStr, parseUUID) didokumentasikan eksplisit dengan peta siapa memakainya.
Trade-offs
Memilih HTMX + server-rendered HTML untuk admin ketimbang SPA React/Vue untuk menjaga deploy tetap satu binary dan tidak perlu build pipeline tambahan; konsekuensinya admin UI terikat server dan kurang rich-interaction. Query database pakai sqlc tanpa ORM untuk kontrol SQL penuh dan nol reflection, trade-off-nya perlu regenerate Go code setiap ubah file .sql.
Halaman Audience sementara memuat 500 row lalu filter di Go; diakui sebagai utang teknis yang akan dipindah ke SQL WHERE ketika data tumbuh.
Implementation Highlights
- Anomaly scoring system dengan multi-session, IP switch, device switch, dan rapid login; user di atas threshold otomatis flagged ke /admin/anomalies dan bisa di-lock + revoke semua session sekaligus.
- Single-session rule: login baru otomatis revoke session lama dan tulis anomaly log, mencegah account-sharing by design.
- Guest login 2-step dengan email + kode undangan → OTP 6 digit (expire 5 menit), plus maksimum 2 login per email per kode agar tetap kontrolable.
- Contract error yang konsisten: semua /api/* return { data | error: { code, message } } dengan kode terstandar (VALIDATION_ERROR, TOKEN_EXPIRED, QUOTA_FULL) untuk memudahkan frontend mapping.
- Admin panel modular per domain (admin_auth_handler.go, user_handler.go, pricing_handler.go, revenue_handler.go) dengan satu template per halaman, menekan blast radius perubahan.
- Webhook Midtrans idempotent di /api/midtrans/webhook dengan pengecekan signature dan state machine subscription yang aman di-replay.
Results
- Menunjukkan kemampuan merancang backend satu-binari yang efisien untuk platform multi-produk: auth dengan model ancaman yang realistis, payment gateway dengan webhook idempotent, dan admin panel yang cukup matang untuk operasi harian, semuanya tanpa stack tambahan di luar Go + PostgreSQL + HTMX.
- Satu binary Go men-serve 4 produk frontend (Atomic, Klinik, KontrakPro, Surat) lewat query parameter product tanpa perubahan skema per produk.
- Admin dashboard live di https://sains-atomic.web.id/admin dengan 12+ halaman (Dashboard, Audience, Users, Guest Codes, Subscriptions, Pricing, Revenue, Products, Settings, Audit Logs, Feedback, Anomalies).
- Midtrans Snap terintegrasi di produksi dengan webhook idempotent yang meng-aktifkan subscription setelah settlement.
- Anti account-sharing jalan: single-session rule + anomaly scoring (multi-session, IP/device switch, rapid login) + lock + revoke semua session dari satu tombol admin.
- Guest login 2-step (email + kode, lalu OTP 6 digit) dengan rate limit 3 OTP per 10 menit dan maksimum 2 login per email per kode aktif.
- Live di https://sains-atomic.web.id men-serve 4 produk frontend produksi.
- Target performance terdokumentasi: API p95 < 200ms sebagai non-functional requirement.
- ~20 endpoint API (public + protected + admin) dan 12+ halaman admin terdokumentasi di URLS.md.
- Quota default 200 subscriber aktif + 50 guest (configurable) dipakai untuk progress bar dashboard.