Kembali ke blog

Kenapa Gue Default ke Boring Tech

Tiap project godaannya nyobain yang baru. Ini alasan gue tetep balik ke Postgres, Next.js, dan Dockerfile — plus kapan boring tech justru pilihan yang salah.

21 Mei 20265 min readarsitekturkeputusanstack

Ada perasaan yang familiar tiap kali mulai project baru: lo lagi natap repo kosong, dan semua keputusan masih terbuka. Database apa? Framework apa? Deploy ke mana? Auth gimana? Tiba-tiba yang lagi rame di Hacker News kelihatan menggoda. Edge runtime, vector-native database, framework yang baru rilis 1.0 minggu lalu. Greenfield itu satu-satunya momen di mana lo bisa milih apa aja, jadi kenapa gak pilih yang menarik?

Gue belajar untuk menahan insting itu. Gak selalu — kadang yang baru emang pilihan yang tepat — tapi sebagai default, gue selalu balik ke boring tech. Postgres. Next.js. Dockerfile. Managed runtime. Tools yang udah cukup lama di pasar sampai semua failure mode-nya udah terdokumentasi dan jawaban di StackOverflow dari lima tahun lalu masih relevan.

Post ini soal alasannya, bukan aturannya. Aturan "pakai boring tech" tanpa alasan bakal jadi cargo culting secepat aturan "selalu coba yang baru".

Boring tech failure mode-nya lebih murah

Tiap teknologi yang lo adopsi punya failure surface. Ada yang obvious — bug, outage, performance cliff. Ada yang halus — maintainer-nya burnout, API-nya churn, dokumen-nya basi, komunitasnya pindah, hosting provider-nya deprecate runtime-nya.

Boring tech udah punya waktu puluhan tahun untuk failure mode itu muncul dan dipatch. Pas Postgres punya edge case aneh, udah ada orang lain yang ngalamin, nulis tentangnya, dan ngeluarin fix-nya. Pas Next.js bertingkah aneh di Vercel, ada thread-nya. Pas Dockerfile build lo error, error message-nya bisa di-google dalam tiga bahasa.

Tech baru belum punya itu. Bukan karena dia jelek — tapi karena belum ada yang stress-test di situasi spesifik aneh kayak punya lo. Lo jadi orang pertama yang nemu edge case jam 2 pagi hari Sabtu, tanpa jawaban Stack Overflow dan tanpa thread untuk diikutin.

Itu fine kalau lo lagi belajar. Tapi mahal kalau lo lagi shipping.

Bagian menarik dari project lo bukan stack-nya

Ini jebakannya: lo bilang ke diri sendiri, tech baru ini bakal bikin lo build sesuatu yang lebih ambisius. Vector database bakal unlock semantic search. Edge runtime bakal bikin lebih cepet. Framework yang baru rilis 1.0 bakal lebih elegan.

Kadang itu bener. Tapi kebanyakan enggak. Kebanyakan, bagian menarik dari project lo — yang user lo beneran peduli — adalah domain logic, UX, konten, integrasi. Stack itu cuma substrate di bawahnya.

Kalau project lo menarik karena domain-nya, milih boring tech ngebiarin lo nge-spend attention budget lo di domain-nya. Kalau project lo menarik karena tech-nya, lo bukan punya project — lo punya tech demo.

Gue udah ngeluarin banyak side project, dan yang nge-stick bukan yang stack-nya paling pinter. Yang nge-stick adalah yang stack-nya cepet minggir, biar gue bisa pake malam-malam buat ngerjain masalah aslinya.

Apa sih "boring" itu sebenernya

Boring itu beda sama tua. Beda sama jelek. Yang gue maksud:

  • Terdokumentasi: ada tutorial resmi yang masih akurat.
  • API surface stabil: upgrade gak rutin minta rewrite.
  • Install base gede: banyak orang ngejalanin di production.
  • Performance predictable: lo bisa reasoning tanpa instrumentasi semuanya.
  • Ops story-nya udah dimengerti: backup, monitoring, scaling udah masalah yang solved.

Pakai definisi itu, Next.js itu boring. Postgres juga. Tailwind juga. React juga. Gak ada yang berasa tua, tapi semuanya memenuhi kriteria. Maksudnya bukan pakai COBOL — maksudnya pakai tools yang udah nyebrang ke titik di mana failure mode-nya udah dikenal.

Default stack gue sehari-hari

Buat project web full-stack solo yang tipikal, jawabannya hampir selalu:

  • Frontend + backend: Next.js (App Router, TypeScript)
  • Database: Postgres (managed kalau lagi buru-buru, self-hosted kalau cost-sensitive)
  • ORM: Prisma
  • State: Zustand buat client state, server component buat sisanya
  • Styling: Tailwind
  • Validation: Zod di boundary API
  • Auth: tergantung, tapi biasanya email + session cookie, gak pakai third-party sampai butuh SSO
  • Deploy: Dockerfile ke GHCR, redeploy webhook ke VPS kecil lewat Dokploy. Vercel buat preview
  • Tests: Vitest, plus Playwright kalau UI-nya cukup banyak

Ini bukan karena gue mikir ini optimal buat semua project. Tapi karena ini optimal buat kebanyakan project gue, dan mulai dari known-good base ngebiarin gue fokus minggu pertama di domain-nya, bukan yak-shaving platform-nya.

Pas project beneran butuh sesuatu yang beda — heavy ML inference, real-time multiplayer, target embedded device — gue deviate. Tapi "ini bakal CRUD app dengan sedikit AI di atasnya" hampir gak pernah perlu deviate.

Kapan boring justru pilihan yang salah

Gue gak nge-argue lo gak boleh pernah adopsi tech baru. Ada alasan beneran buat break default:

  1. Lo lagi belajar. Side project itu tempat yang sah buat main-main sama tools baru. Cost of failure-nya weekend lo, upside-nya lo beneran ngerti tools baru itu pas dia muncul di kerjaan.
  2. Tech baru solve masalah yang lo beneran punya. Kalau lo build real-time collaboration dan reach socket.io karena itu boring, padahal liveblocks bisa bikin lo ship sepersepuluh waktu, pilihan boring justru jadi yang mahal.
  3. Pilihan boring punya ceiling struktural yang bakal lo hit. Kalau domain lo beneran butuh vector search di scale dan lo coba fake-in di Postgres, lo bakal ngabisin waktu lebih banyak buat fight itu daripada belajar vector DB beneran.

Yang ketiganya punya kesamaan: ada alasan spesifik buat deviate-nya, dinama-in dari awal. Bukan "ini kayaknya keren". Tapi masalah spesifik yang pilihan boring gak bisa solve.

Judgment call, bukan aturan

Boring tech itu default, bukan doktrin. Maksudnya bukan menolak belajar hal baru — tapi memastikan kalau lo emang reach yang baru, lo bayar learning cost-nya on purpose, dengan mata terbuka soal berapa harga debugging time, doc gaps, dan bangun jam 2 pagi-nya.

Kebanyakan waktu, jawaban dari "gue harus pakai apa buat project ini" adalah "yang sama kayak yang gue pake terakhir, kecuali ada alasan spesifik buat ganti". Itu bukan jawaban boring karena project-nya boring. Itu jawaban boring karena emang itu yang bener kebanyakan waktu, dan nyimpen budget novelty buat bagian yang beneran butuh, itu cara lo shipping.