Yang Saya Lakukan di Level CTO — Strategi Bisnis Melalui Teknologi

Saya tidak lagi dinilai dari baris kode. Saya dinilai dari keputusan — arsitektur apa yang dipakai, trade-off apa yang diterima, dan bagaimana membimbing developer lain. Inilah kisah nyata merancang IoT telemetry untuk 50K events/detik, microservices untuk perusahaan asuransi terbesar di Australia, dan keputusan stack yang menjadi artikel paling banyak dibaca.

"Kamu tidak menjadi senior engineer dengan menulis lebih banyak kode. Kamu menjadi satu dengan membuat keputusan yang bertahan lebih lama dari dirimu." — Saya, setelah merusak production untuk ke-47 kalinya
Lompatan dari mid-level ke senior adalah transisi paling membingungkan dalam rekayasa perangkat lunak. Tahun-tahun mid-level-mu mengajarimu untuk mengirim fitur. Sekarang, tidak ada yang peduli seberapa cepat kamu secara pribadi mengirim. Mereka peduli apakah arsitektur yang kamu pilih bertahan selama tiga tahun pertumbuhan, apakah trade-off yang kamu dokumentasikan menghemat enam bulan penemuan ulang tim berikutnya, dan apakah engineer junior yang kamu bimbing bisa mengirim tanpa dirimu.
Sebelum (Mid-Level): "Bisakah kamu memiliki sebuah fitur dari ujung ke ujung dan mengirimkannya dengan andal?" Sekarang (Senior): "Bisakah kamu membuat keputusan arsitektur yang akan diikuti oleh banyak tim — dan benar tentang trade-off-nya 80% dari waktu?"
Saya tidak lagi dinilai dari baris kode. Saya dinilai dari keputusan — arsitektur apa yang dipakai, trade-off apa yang diterima, dan bagaimana membimbing developer lain tanpa menulis kode mereka untuk mereka.
Inilah bagaimana tampilannya dalam praktik.
Peran: Backend Engineer & System Architect Stack: Go, MQTT, Kafka, TimescaleDB, React Skala: 50K events telemetry/detik, 100+ unit alat berat di 3 lokasi tambang terpencil
Operasi pertambangan Petrosea memiliki masalah: 100+ dump truck, ekskavator, dan kendaraan pendukung yang beroperasi di lokasi terpencil di Kalimantan menghasilkan telemetry terus-menerus — posisi GPS, suhu mesin, konsumsi bahan bakar, berat muatan — setiap 2 detik. Data ini krusial untuk keputusan dispatch real-time, peringatan geofence, dan perawatan prediktif. Namun lokasi-lokasi tersebut memiliki konektivitas satelit intermiten yang membuat arsitektur berbasis HTTP tidak andal.
Saya merancang mesin geofencing real-time yang mampu memproses 50K events per detik dengan latensi peringatan di bawah 2 detik. Pilihan arsitektur inti adalah pipeline data:
Masalah: 100+ truk tambang di lokasi terpencil menghasilkan data GPS/mesin setiap 2 detik. Konektivitas satelit intermiten — terkadang 6-8 jam pemadaman total. Data harus mencapai dashboard HQ dalam 5 detik untuk peringatan geofence real-time.
Keputusan Arsitektur:
Edge Gateway (Go) → MQTT (QoS 1) → Kafka → Stream Processor → TimescaleDB → WebSocket → React Dashboard
↓
Geofence Engine (< 2s alerts)Rincian Komponen:
Edge Gateway (Go): Berjalan di hardware kelas Raspberry Pi yang dipasang di setiap truk. Buffer SQLite lokal untuk periode offline. Menerbitkan telemetry via MQTT saat konektivitas tersedia. Menangani terjemahan protokol dari berbagai sensor OEM (Caterpillar, Komatsu, Hitachi) ke skema yang dinormalisasi.
MQTT Broker (Mosquitto): Dipilih secara eksplisit karena protokolnya yang ringan, tingkat QoS (QoS 1 untuk pengiriman setidaknya sekali), dan sesi persisten yang bertahan dari pemutusan koneksi. Ketika sebuah truk muncul dari titik buta setelah 6 jam, status sesi MQTT membangun kembali dan antrean mengalir tanpa intervensi developer.
Kafka Stream Processor: Memisahkan ingestion dari pemrosesan. Menangani masalah "thundering herd" ketika 50 truk terhubung kembali secara bersamaan — Kafka mem-buffer lonjakan sementara konsumen downstream memproses dengan kecepatan mereka sendiri.
TimescaleDB: Ekstensi PostgreSQL yang dioptimalkan untuk time-series. Dipilih daripada InfluxDB karena kami membutuhkan SQL JOIN antara telemetry dan metadata peralatan. Peningkatan performa query 10x dibanding PostgreSQL vanilla untuk query rentang waktu.
Geofence Engine: Indeks spasial in-memory menggunakan R-tree. Memproses koordinat GPS yang masuk terhadap poligon geofence yang telah ditentukan. Deteksi sub-detik memicu peringatan via WebSocket push — tanpa polling.
Trade-Off Utama: MQTT daripada HTTP. HTTP polling pada 50K events/detik akan membutuhkan minimal 50 permintaan per detik, masing-masing dengan overhead jabat tangan TLS. Pada tautan satelit dengan latensi 600ms+, badai percobaan ulang saja akan meruntuhkan pipeline. Koneksi TCP persisten MQTT dengan QoS 1 dan status sesi menghilangkan ini sepenuhnya.
Yang Akan Saya Ubah: Tambahkan dead-letter queue untuk pesan yang tidak dapat diproses dan terapkan pensinyalan backpressure dari Kafka ke MQTT. Kami kehilangan ~0,3% telemetry di bulan pertama akibat lag konsumen Kafka selama jam sibuk — mekanisme backpressure akan mencegah ini.
| Metrik | Sebelum | Sesudah |
|---|---|---|
| Pemrosesan telemetry | Manual/berbasis log | Real-time, 50K events/detik |
| Latensi peringatan geofence | 5-10 menit | < 2 detik |
| Deteksi pencurian BBM | Tidak diketahui (tidak terdeteksi) | Tertangkap di bulan pertama |
| Penghematan tahunan | — | Rp 3,2 M ($200K) |
| Visibilitas utilisasi armada | Laporan shift berbasis kertas | Dashboard langsung, 65% → 79% |
Peran: Frontend & Backend Engineer Stack: Nuxt.js (SSR), Go microservices, PostgreSQL, D3.js Skala: 5+ integrasi mitra, digitalisasi seluruh siklus hidup asuransi untuk perusahaan asuransi terbesar di Australia
IAG (Insurance Australia Group) — perusahaan asuransi umum terbesar di Australia, kapitalisasi pasar ~AU$12 M — membutuhkan platform untuk melayani pasar asuransi cyber UKM yang kurang terlayani. Proses yang ada membutuhkan 3-4 hari untuk sebuah kutipan, melibatkan 100+ pertanyaan manual, dan memerlukan bolak-balik underwriter melalui email. Kami harus mendigitalkan seluruh siklus hidup: penilaian risiko → pembuatan kutipan → pengikatan → pemantauan → klaim.
Kebutuhan Bisnis: Broker asuransi Australia mencari "cyber insurance quote" di Google. Jika alur kutipan kami tidak dapat diindeks oleh mesin pencari, broker tidak akan menemukan kami — dan mereka akan beralih ke pesaing.
Keputusan: Nuxt.js Server-Side Rendering (SSR) daripada React Single Page Application (SPA).
Mengapa Bukan React SPA:
/quote/business-profile?industry=tech&employees=50 — setiap URL perlu dapat diindeks dengan meta tag unikMengapa Nuxt.js SSR:
Gambaran Arsitektur:
Browser → Nuxt.js SSR → Go API Gateway → Microservices:
├── Risk Assessment Service (integrasi pemindaian kerentanan)
├── Quoting Engine (kalkulasi premi + mesin aturan)
├── Policy Management Service (pengikatan + pembuatan dokumen)
├── Partner Integration Layer (UpGuard, Acronis, RHCS)
└── Notification Service (email, peringatan dashboard)Trade-Off yang Diterima: SSR memperkenalkan biaya server yang lebih tinggi per permintaan dibandingkan SPA statis. Setiap render halaman memerlukan perjalanan pulang-pergi server Node.js. Kami memitigasi ini dengan Redis page caching untuk halaman publik (halaman tarif, FAQ, blog) dan menyediakan SSR dinamis hanya untuk alur kutipan yang terautentikasi.
Hasil: Platform sepenuhnya diindeks oleh Google dalam 2 minggu setelah peluncuran. Lalu lintas organik dari pencarian broker berkontribusi 40% dari sesi kutipan baru di kuartal pertama. Alur kutipan yang didigitalkan mengurangi waktu-kutipan dari 3-4 hari menjadi di bawah 15 menit.
| Metrik | Sebelum | Sesudah |
|---|---|---|
| Perputaran kutipan | 3-4 hari | < 15 menit |
| Siklus hidup asuransi | Manual/kertas | Sepenuhnya digital |
| Integrasi mitra | Tidak ada | 5+ (UpGuard, Acronis, RHCS, dll.) |
| Jangkauan platform | Australia saja | Asia Pasifik (Singapura, Malaysia, Hong Kong) |
Peran: Pengambil Keputusan Teknologi Stack: Go (dipilih), dievaluasi terhadap Node.js, Python, Rust
Setiap senior engineer pada akhirnya menghadapi pertanyaan: "Apa stack utama kamu dan mengapa?" Ini bukan pertanyaan trivia — ini adalah ujian kemampuanmu untuk mengevaluasi trade-off di berbagai dimensi: performa, produktivitas developer, kematangan ekosistem, pasar perekrutan, dan biaya perawatan jangka panjang.
Saya mengevaluasi empat opsi terhadap lima kriteria:
| Kriteria | Go | Node.js | Python | Rust |
|---|---|---|---|---|
| Model konkurensi | Goroutine (built-in) | Event loop (single-threaded) | Terbatas GIL | Async/await (kompleks) |
| Kecepatan kompilasi | < 2 detik | N/A (interpreted) | N/A (interpreted) | 30-120 detik |
| Deployment | Satu binary | Node + node_modules | Python runtime + pip | Satu binary |
| Kurva pembelajaran | Rendah (25 keywords) | Rendah | Rendah | Curam (ownership, lifetimes) |
| Perekrutan di Indonesia | Tumbuh pesat | Matang | Matang | Niche |
Keputusan: Go menang pada kesederhanaan, kecepatan kompilasi, dan ergonomi deployment — bukan performa mentah. Seorang pendukung Rust dapat dengan tepat menunjukkan bahwa Rust mengungguli Go dalam beban kerja CPU-bound sebesar 2-5x. Namun throughput CPU mentah jarang menjadi hambatan saya. I/O Jaringan, query database, dan throughput antrean pesan adalah hambatannya. Model konkurensi berbasis goroutine Go menangani itu dengan sempurna.
Setiap keputusan tingkat senior dalam karier saya mengikuti pola yang sama: identifikasi kendala nyata (bukan yang hipotetis), evaluasi trade-off secara eksplisit, dan pilih opsi yang mengoptimalkan hambatan — apakah itu produktivitas developer, kemudahan deployment, atau persyaratan SEO.
Di luar proyek individu, peran senior menuntut saya mendokumentasikan keputusan arsitektur sehingga dapat dipahami, ditantang, dan diperluas oleh engineer lain. Berikut adalah dua diagram kunci yang mewakili masalah arsitektur paling kompleks yang saya selesaikan.
Pernyataan Masalah: 100+ truk tambang menghasilkan 50K events telemetry/detik di 3 lokasi terpencil dengan konektivitas satelit intermiten. Data harus mencapai dashboard HQ dalam waktu kurang dari 5 detik untuk dispatch real-time dan peringatan keselamatan.
Arsitektur:
┌─────────────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐
│ Edge Gateway │────▶│ MQTT │────▶│ Kafka │────▶│ TimescaleDB │
│ (Go + SQLite) │ │ Broker │ │ Stream │ │ (Time-Series)│
│ Local Buffer │ │ QoS 1 │ │ Cluster │ │ │
└─────────────────┘ └──────────┘ └──────────┘ └───────┬───────┘
│ │
│ Offline: SQLite Lokal │
│ Online: MQTT publish │
│ (QoS 1, persistent session) │
│
┌────────────────┐ ┌──────────────────┐ ┌─────────────────┐│
│ Geofence │◀────│ Stream Processor│◀────│ Kafka Consumer ││
│ Engine (R-Tree)│ │ (Go) │ │ (Go) ││
│ < 2s alerts │ │ + Alerting │ └─────────────────┘│
└────────────────┘ └──────────────────┘ │
│
┌────────────▼───────┐
│ WebSocket Server │
│ (Go) │
└────────────┬───────┘
│
┌────────────▼───────┐
│ React Dashboard │
│ (Real-Time Maps) │
└────────────────────┘Keputusan: Edge gateway dengan buffer SQLite lokal → MQTT publish (QoS 1) → Kafka stream processing → TimescaleDB → WebSocket push ke React.
Trade-Off yang Dipertimbangkan:
Pernyataan Masalah: 5.000+ petugas lapangan yang bekerja di area tanpa konektivitas internet sama sekali. Mereka mengisi formulir dinamis, mengambil foto, dan mengumpulkan tanda tangan digital. Semua data harus sinkron tanpa kehilangan saat konektivitas kembali. Solusi Microsoft Power Apps sebelumnya memiliki tingkat kehilangan data 23%.
Arsitektur:
┌──────────────────┐ ┌──────────┐ ┌──────────────────┐
│ Flutter Mobile │────▶│ MQTT │────▶│ Go API Gateway │
│ App │ │ Broker │ │ │
│ ┌────────────┐ │ │ QoS 1 │ │ ┌────────────┐ │
│ │ SQLite DB │ │ └──────────┘ │ │ CRDT │ │
│ │ (Local) │ │ │ │ Resolution │ │
│ ├────────────┤ │ ┌──────────┐ │ ├────────────┤ │
│ │ Change Log │ │────▶│ MQTT │────▶│ │ PostgreSQL │ │
│ │ Table │ │ │ Batch │ │ │ (Source of │ │
│ └────────────┘ │ │ Upload │ │ │ Truth) │ │
└──────────────────┘ └──────────┘ └──────────────────┘
│
│ Offline: Tulis ke SQLite + change log
│ Online: Dorong change log via MQTT
│ Reconnect: Tarik perubahan server, terapkan penggabungan CRDTKeputusan: SQLite DB lokal → tabel change log → MQTT push saat online → resolusi konflik sisi server (last-write-wins dengan timestamp + vektor ID perangkat).
Trade-Off yang Dipertimbangkan:
Hasil: 0% kehilangan data (dari 23% di sistem sebelumnya). 4,1 juta pengguna akhir dilayani.
| Item Portofolio | Apakah Saya Melakukannya? | Bukti |
|---|---|---|
| Diagram sistem arsitektur | ✅ Didokumentasikan di beberapa studi kasus dengan analisis trade-off | |
| Keputusan trade-off dengan alasan | ✅ Go vs Rust, MQTT vs HTTP, SSR vs SPA — masing-masing dengan matriks evaluasi eksplisit | |
| Dampak mentoring | ⚠️ Hanya mentoring informal — tidak pernah membuat program terstruktur | |
| Berbicara/menulis | ✅ 20+ artikel teknis yang diterbitkan termasuk analisis stack Go yang paling banyak dibaca | |
| Pengaruh arsitektur lintas tim | ✅ Merancang pola yang diadopsi oleh 3+ tim produk (form engine, pipeline telemetry) | |
| Kepemimpinan insiden produksi | ✅ Memimpin RCA untuk insiden IoT kritis, mendokumentasikan runbook untuk serah terima operasi | |
| ADR / dokumentasi teknis | ⚠️ Tidak konsisten — keputusan didokumentasikan dalam studi kasus tetapi tidak dalam ADR formal di setiap kasus |
Kolom mentoring informal adalah celah terbesar saya. Saya membimbing engineer junior dan mid-level pada code review dan keputusan arsitektur mereka, tetapi saya tidak pernah membuat kerangka mentoring terstruktur. Melihat ke belakang, itu adalah peluang yang terlewatkan — para engineer yang saya bimbing secara informal tumbuh lebih cepat, tetapi organisasi tidak dapat mereplikasi pola tersebut karena tidak didokumentasikan.
Perbedaan antara senior dan mid-level bukanlah membuat keputusan sempurna — ini adalah mampu menjelaskan mengapa kamu membuat keputusan, alternatif apa yang dipertimbangkan, dan kapan kamu akan meninjaunya kembali. Mulailah menulis ADR (Architecture Decision Records) untuk setiap pilihan teknis yang tidak sepele. Analisis stack Go yang saya publikasikan menjadi artikel yang paling banyak dibaca bukan karena secara teknis mengesankan, tetapi karena menunjukkan matriks evaluasi — format yang persis sama dengan yang kamu butuhkan untuk portofolio senior-mu.
Kamu tidak menjadi senior dengan mengetahui lebih banyak. Kamu menjadi satu dengan membuat orang lain lebih efektif. Mulailah dengan satu engineer junior. Code review dengan penjelasan ("Saya akan melakukan X karena Y, tetapi pendekatanmu berfungsi jika Z"). Pair programming pada fitur yang kompleks. Tulislah dokumentasi internal yang membuka blokir tim. Bunga majemuk dari mentoring membuahkan hasil lebih cepat daripada fitur individu apa pun yang bisa kamu bangun.
Setiap keputusan arsitektur, analisis trade-off, atau postmortem produksi yang kamu tulis adalah aset. Itu memvalidasi pemikiranmu untuk calon pemberi kerja masa depan, membantu engineer lain yang menghadapi masalah yang sama, dan membangun pengakuan yang membuat peran senior lebih mudah diamankan. Saya menulis 20+ artikel teknis selama tahun-tahun senior saya — dan setiap satu dari artikel tersebut berkontribusi lebih banyak pada lintasan karier saya daripada fitur tunggal mana pun yang saya kirim.
Engineer mid-level mengoptimalkan untuk "apakah ini berfungsi." Engineer senior mengoptimalkan untuk "apakah ini bertahan." Latensi, throughput, error budget, MTTR, frekuensi deployment — ini bukan metrik DevOps. Ini adalah metrik engineering senior. Mulailah mengukur sebelum kamu mengoptimalkan. "Penghematan tahunan $200K" dari Petrosea ada karena saya menginstrumentasi sistem dari hari pertama dan dapat menunjuk pada peningkatan spesifik dengan nilai dolar spesifik.
Senior engineering bukanlah langit-langit. Ini adalah landasan peluncuran. Keputusan arsitektur yang kamu buat di tingkat ini bertahan lebih lama dari masa jabatanmu. Engineer yang kamu bimbing melampaui pengaruhmu. Trade-off yang kamu dokumentasikan menghemat waktu bertahun-tahun penemuan ulang tim masa depan. Kode-mu dikompilasi dan di-deploy. Namun keputusanmu berakumulasi — dan itulah yang membuat seorang senior engineer.



