Back to News/Case Study: Offline-First Architecture di Enterprise Isla...

Case Study: Offline-First Architecture di Enterprise Isla...

Faisal Affan
11/15/2025
Case Study: Offline-First Architecture di Enterprise Isla...

Engineering Case Study: Project Tepati

"Technology is best when it brings people together." — Matt Mullenweg

Context

Seluruh backend system project ini saya bangun sendiri (single-fighter) dari nol — arsitektur, API, message brokers, database, sync engine, hingga deployment — dengan target MVP 1 bulan. Tidak ada backend engineer lain. Sementara sisi frontend (React Native) ditangani oleh tim terpisah.

Project Tepati adalah sistem digitalisasi proses pembiayaan mikro syariah untuk salah satu bank syariah terbesar di Indonesia. Sistem ini menggantikan proses manual berbasis kertas menjadi aplikasi digital end-to-end yang digunakan 5,000+ Community Officer di seluruh Indonesia.

Artikel ini membedah fitur-fitur paling menantang dari sisi engineering dan bisnis.


🏔️ 1. The Challenge

Petugas lapangan (Community Officer) bekerja di remote area — dari pelosok Sumatera hingga desa-desa di Nusa Tenggara. Koneksi internet adalah kemewahan, bukan kepastian.

Kondisi Sebelum Tepati

Sebelum Tepati dibangun, seluruh proses akuisisi nasabah dilakukan menggunakan Microsoft Power Apps. Petugas lapangan mengisi data melalui form Power Apps, mengirim via Teams, dan menunggu approval secara manual. Proses ini sangat lambat karena:

  • Tidak ada offline capability yang reliable — Power Apps membutuhkan koneksi internet stabil untuk sinkronisasi data.
  • 🗃️ Data tersebar di berbagai file dan chat thread — sulit di-track dan rawan kehilangan.
  • Approval bottleneck — atasan harus membuka attachment satu per satu di Teams.
  • 🙈 Tidak ada real-time visibility — manajemen tidak bisa memonitor progress akuisisi secara live.

Tantangan Engineering

  1. 🛡️ Data Integrity: Data finansial nasabah (income, expense, cashflow) tidak boleh hilang saat sinyal putus-nyambung.
  2. 🧩 Complex State: Form aplikasi pembiayaan memiliki 200+ fields dengan logika validasi silang (cross-field validation) yang kompleks.
  3. 🔄 Conflict Resolution: Data yang diubah di device A (saat offline) dan device B (saat online) secara bersamaan harus resolved tanpa data loss.
  4. 🏢 Multi-Level Approval: Setiap pengajuan harus melewati 6 level approval (CO → BM → SBM → BC → DH1 → DH2) yang tersebar di geografis berbeda.
  5. ⚖️ Regulatory Compliance: Semua transaksi harus sesuai dengan regulasi OJK dan prinsip syariah.
  6. ⏱️ Solo Backend Engineer, Deadline Ketat: Seluruh backend harus saya deliver sendiri dalam 1 bulan untuk MVP — tanpa backend engineer lain.

Business Impact

Sebelum Tepati, 23% pengajuan gagal karena data hilang atau tidak lengkap. Setiap kegagalan berarti petugas harus kembali ke nasabah — rata-rata membutuhkan 2-3 hari tambahan dan berdampak pada kepercayaan nasabah.


⚔️ 2. Single-Fighter Backend

Banyak yang bertanya: bagaimana bisa satu orang membangun seluruh backend system sebesar ini dalam sebulan?

Jawabannya: ruthless prioritization + technology leverage.

  • 🏗️ Minggu 1: Setup infrastruktur (Golang services, Kafka, AMQ, database schema, CI/CD pipeline).
  • ⚙️ Minggu 2: Core sync engine backend + API endpoints untuk dynamic form engine. Ini 80% dari backend complexity.
  • 🚀 Minggu 3: Approval pipeline (Kafka consumers + AMQ), IIR simulation API, document upload service.
  • 🧪 Minggu 4: Integration testing dengan tim frontend, bug fixing, deployment ke staging & production.

Kuncinya adalah saya sudah sangat familiar dengan Golang dan message broker ecosystem (Kafka + AMQ + MQTT) sehingga tidak ada learning curve yang memperlambat. Setiap keputusan arsitektur backend saya buat untuk maximize velocity tanpa mengorbankan reliability. Tim frontend tinggal consume API yang sudah saya sediakan.


🛠️ 3. Technology Stack

Backend

  • 🐹 Golang: High-concurrency microservices, mampu handle 15,000 concurrent connections dengan memory footprint minimal.
  • 📨 Apache Kafka: Event streaming untuk data ingestion dari lapangan — throughput 50,000 events/second pada peak hours.
  • 📬 AMQ (ActiveMQ): Message broker untuk orchestrasi approval workflow antar-level.
  • MongoDB: Primary database untuk menyimpan data formulir dinamis (JSON) dari lapangan.
  • Microsoft SQL Server: Database relasional untuk menyimpan data struktur organisasi dan hierarki approval.
  • Redis: Distributed caching dan session management.

Frontend (Mobile)

  • ⚛️ React Native: Cross-platform mobile app yang di-deploy ke 5,000+ Android devices.
  • 🗄️ SQLite: Local database — menyimpan hingga 10,000 records per device tanpa degradasi performa.
  • 📡 MQTT (Mosquitto): Protokol ringan untuk real-time notification di kondisi bandwidth < 50kbps (intermittent).

🔍 4. Feature Deep Dives

Feature #1: Offline-First Sync Engine

Problem: Petugas sering berada di area tanpa sinyal selama 4-6 jam.

Solution: Saya membangun arsitektur yang selalu offline dan hanya melakukan sinkronisasi saat ada sinyal.

Key Engineering Decisions:

  • 📦 Delta Sync Protocol: Hanya mengirim perubahan, bukan seluruh payload. Menghemat bandwidth rata-rata 78%.
  • ⚔️ Conflict Resolution: Last-Write-Wins (LWW) untuk data non-finansial, server-authoritative merge untuk data finansial kritikal.
  • 🔄 Retry with Exponential Backoff: Max 5 retries dengan jitter untuk menghindari thundering herd.
// Simplified Sync Consumer (Golang)
func (s *SyncService) ProcessSyncBatch(ctx context.Context, batch []SyncEvent) error {
    for _, event := range batch {
        existing, err := s.repo.FindByDeviceID(ctx, event.DeviceID, event.RecordID)
        if err != nil {
            return fmt.Errorf("failed to find record: %w", err)
        }

        if existing != nil && existing.UpdatedAt.After(event.Timestamp) {
            // Server version is newer — skip, notify client
            s.notifier.SendConflict(ctx, event.DeviceID, existing)
            continue
        }

        if err := s.repo.Upsert(ctx, event.ToRecord()); err != nil {
            return fmt.Errorf("failed to upsert: %w", err)
        }

        s.kafka.Publish("sync.completed", event)
    }
    return nil
}

Results:

MetricSebelumSesudahImprovement
Data loss rate23%0%↓ 100%
Avg sync time45 detik3.2 detik↓ 93%
Bandwidth usage per sync2.4 MB520 KB↓ 78%
App crash rate (offline)12%0.3%↓ 97.5%

Feature #2: Dynamic Form Engine

Problem: Form pengajuan pembiayaan memiliki 200+ fields yang berubah berdasarkan jenis usaha nasabah, lokasi, dan kebijakan branch. Setiap perubahan form memerlukan app update (re-deploy ke 5,000 devices).

Solution: Server-Driven Form Engine — form definition di-download sebagai JSON schema dari server dan dirender secara dinamis di client.

// Form Schema (simplified)
interface FormField {
  id: string;
  type: "text" | "number" | "select" | "photo" | "signature";
  label: string;
  rules: ValidationRule[];
  dependencies?: {
    field: string;
    condition: "equals" | "gt" | "lt";
    value: any;
    action: "show" | "hide" | "require";
  }[];
}

Cross-Field Validation Examples:

  • 🌾 Jika jenis_usaha === "pertanian" → field lama_usaha minimum 2 tahun.
  • 💰 Jika income_busy_day < angsuran * 3 → tolak otomatis, tampilkan warning IIR.
  • 💍 Jika status_perkawinan === "menikah" → wajib upload img_surat_nikah_url dan img_ktp_pasangan_url.

Results:

MetricSebelumSesudahImprovement
Form update cycle2-3 minggu (app release)Real-time↓ 100%
Incomplete submission34%4.2%↓ 88%
Avg form completion time45 menit18 menit↓ 60%

Feature #3: Real-Time Multi-Level Approval Pipeline

Problem: Pengajuan pembiayaan harus melewati 6 level approval (CO → BM → SBM → BC → DH1 → DH2). Sebelumnya, approval dilakukan via WhatsApp group — rawan human error dan tidak auditable.

Solution: Event-driven approval pipeline menggunakan Kafka + AMQ yang saya rancang sendiri.

Key Engineering:

  • 🏎️ Setiap level approval adalah independent Kafka consumer — jika satu level down, yang lain tetap jalan.
  • 🔒 AMQ digunakan untuk DH-level approval karena memerlukan guaranteed delivery dengan transaction support.
  • 🔔 MQTT push notification ke device approver — response time turun dari jam ke menit.
  • 📝 Audit trail lengkap: siapa approve, kapan, dari device mana, di koordinat GPS berapa.

Results:

MetricSebelumSesudahImprovement
Approval cycle time5-7 hari< 24 jam↓ 85%
Bottleneck detectionManualReal-time dashboard
Approval fraud rate~2.1%0.08%↓ 96%

Feature #4: IIR Simulation Engine

Problem: Petugas harus menghitung Installment to Income Ratio (IIR) secara manual. Kesalahan hitung menyebabkan pengajuan ditolak di level atas, membuang waktu semua pihak.

Solution: Real-time IIR calculator yang berjalan di device (offline-capable), dengan tabel tenor dan margin yang di-sync dari server.

// IIR Calculation Engine (Golang - mirrored in React Native)
type IIRSimulation struct {
    Tenor       int     `json:"tenor"`
    Angsuran    int64   `json:"angsuran"`
    TotalIIR    float64 `json:"total_iir"`
    Margin      float64 `json:"margin"`
    IsEligible  bool    `json:"is_eligible"`
}

func SimulateIIR(totalIncome, existingInstallment, requestedAmount int64, tenors []int) []IIRSimulation {
    var results []IIRSimulation
    for _, tenor := range tenors {
        angsuran := calculateAngsuran(requestedAmount, tenor, getMarginRate(tenor))
        totalIIR := float64(angsuran+existingInstallment) / float64(totalIncome) * 100

        results = append(results, IIRSimulation{
            Tenor:      tenor,
            Angsuran:   angsuran,
            TotalIIR:   totalIIR,
            Margin:     getMarginRate(tenor),
            IsEligible: totalIIR <= 30.0, // OJK threshold
        })
    }
    return results
}

Results:

MetricSebelumSesudahImprovement
IIR calculation error18%0.1% (rounding only)↓ 99.4%
Rejection at upper level (due to IIR)22%3%↓ 86%
Time to simulate5-10 menit (manual)< 1 detik↓ 99%

Feature #5: Secure Document Capture & Upload

Problem: Petugas mengambil foto KTP, KK, Surat Nikah menggunakan kamera personal dan mengirim via WhatsApp. Masalah: kualitas tidak konsisten, tidak terenkripsi, tidak auditable.

Solution: In-app camera module dengan:

  • 📸 Auto-detect document boundaries (OpenCV-based edge detection).
  • 👁️ Image quality validator — reject jika blur score > threshold.
  • 🔐 AES-256 encryption at rest di SQLite, decrypted hanya saat upload.
  • 📤 Progressive upload — gambar dikirim dalam chunks saat sinyal tersedia.

Results:

MetricSebelumSesudahImprovement
Document re-capture rate31%5%↓ 84%
Avg upload success rate67%99.2%↑ 48%
Security incidents (data leak)3 per tahun0↓ 100%

🚀 5. Overall Business Impact

Implementasi keseluruhan Tepati mengubah fundamental cara kerja pembiayaan mikro:

Key Numbers

  • 📈 Nasabah ter-serve: dari 2.8 juta4.1 juta (+46%) dalam 18 bulan
  • 💰 Cost per acquisition: turun 62% secara year-on-year
  • Turnaround time: dari 7 hari< 24 jam (↓85%)
  • 📉 NPL (Non-Performing Loan): turun dari 1.8%1.2% karena data underwriting lebih akurat
  • 👩‍💼 CO productivity: naik 2.3x (dari 8 nasabah/hari → 18 nasabah/hari)

🏢 6. Post-Launch: Tantangan Organisasi

Setelah MVP berhasil di-deliver, ada beberapa tantangan non-teknis yang cukup berdampak terhadap velocity pengembangan selanjutnya. Saya dokumentasikan ini sebagai pembelajaran:

6.1 Migrasi Protokol: AMQ/MQTT (Intermittent) → HTTP

Arsitektur awal menggunakan AMQ dan MQTT untuk handling koneksi offline-first. Namun, kendala infrastruktur server menyebabkan koneksi ke broker sering terputus di tengah jalan (intermittent). Pasca-launch, protokol diubah ke HTTP-based untuk mengatasi instabilitas tersebut sekaligus menyelaraskan dengan enterprise backend ecosystem yang sudah mature.

Meskipun MQTT lebih efisien secara bandwidth, memelihara stateful connection broker di skala enterprise membutuhkan overhead operasional yang tinggi. Transisi ke HTTP dipilih untuk menjamin maintainability jangka panjang oleh tim operasional yang sudah sangat ahli di REST/HTTP environment, meskipun harus mengorbankan sedikit efisiensi bandwidth.

Engineering Insight

Ini adalah pelajaran tentang "Organizational-Fit". Arsitektur terbaik bukan hanya yang paling canggih secara teknis, tapi yang bisa di-support dengan baik oleh kapabilitas operasional organisasi saat ini.

6.2 CI/CD Pipeline yang Belum Optimal

Salah satu hambatan signifikan dalam iterasi pengembangan adalah kecepatan deployment pipeline. Pada kondisi saat itu:

StageDurasiCatatan
Build → Beta~15 menitCukup lama untuk rapid iteration
Build → Production~30 menitBelum termasuk rollback jika error
Hotfix cycle45-60 menitTermasuk re-test dan re-deploy

Sebagai perbandingan, standar industri untuk pipeline modern adalah < 5 menit untuk build-to-deploy. Pipeline yang lambat ini menghambat feedback loop dan memperlambat siklus perbaikan bug di lapangan.

6.3 Security Compliance & Developer Experience

Seiring matangnya project, standar keamanan perusahaan (Enterprise Security) mulai diterapkan sepenuhnya, termasuk penggunaan perangkat terstandarisasi dengan EDR (Endpoint Detection & Response) dan VPN corporate.

Tantangan yang muncul adalah menyeimbangkan Compliance dengan Velocity:

  • Resource Constraints: Tooling keamanan enterprise seringkali memakan resource CPU/IO yang signifikan, yang berdampak pada waktu kompilasi (terutama Golang/React Native) dibandingkan environment development non-standard.
  • Workflow Adaptation: Developer perlu beradaptasi dengan environment yang lebih terbatas demi menjaga keamanan data nasabah.

Ini adalah trade-off yang wajar di industri perbankan: Security is non-negotiable, namun tantangannya adalah bagaimana tetap menjaga feedback loop pengembangan tetap cepat di dalam batasan tersebut.

6.4 The Efficiency Dilemma: Balancing Scope & Focus

Refleksi penting lainnya adalah mengenai alokasi resource engineer dalam fase maintenance.

1. Multitasking vs Deep Work Di fase awal (zero-to-one), peran hybrid (Backend + Infra + Support) sangat efektif untuk kecepatan. Namun di fase steady state, peran ini perlu dispesialisasi. Mengharapkan satu engineer menangani logic bisnis sekaligus isue infrastruktur dapat memecah fokus (context switching) yang berisiko pada kualitas jangka panjang.

Sustainability Note

Efisiensi tim tidak hanya diukur dari "seberapa banyak role yang dipegang satu orang", tapi dari seberapa fokus tim tersebut dapat menyelesaikan masalah spesifik tanpa distraksi operasional yang berlebihan.

2. Optimizing Processes Proses deployment dan policy keamanan adalah bagian vital dari governance. Tantangan engineering leadership adalah memastikan proses ini efisien (misalnya melalui otomatisasi CI/CD yang lebih baik atau whitelisting policy) sehingga engineer tidak menghabiskan waktu menunggu proses (wait time), melainkan mencipta solusi (build time).

3. Conclusion True efficiency adalah ketika sistem pendukung (people, process, tools) memungkinkan tim engineering bekerja dengan friksi minimal, menyeimbangkan kecepatan inovasi dengan kepatuhan regulasi.

☠️ 6.5 The Silent Killer: Technical & Intellectual Bankruptcy

Kecepatan ekstrem di awal seringkali menjadi candu. Namun, membiarkan satu orang memegang kunci seluruh sistem tanpa pendamping adalah kesalahan manajerial yang fatal.

The Illusion of Speed Saat Anda memiliki "Hero Developer", Anda merasa aman karena fitur ter-deliver cepat. Realitanya, Anda sedang menumpuk bunga berbunga dari utang organisasi. Ketergantungan ini adalah bom waktu.

Critical Risk Assessment

Ketergantungan pada satu individu adalah Single Point of Failure (SPOF) terbesar.

Jika Anda tidak mendistribusikan pengetahuan sekarang, bersiaplah menghadapi realita pahit saat transisi terjadi:

  1. Lumpuh Total: Engineer baru butuh waktu 3-4 sprint (1-2 bulan) hanya untuk sekadar membaca dan memahami mental model kode "jenius" tersebut tanpa berani menyentuhnya.
  2. The Inevitable Rewrite: Seringkali, kompleksitas kode "single-fighter" begitu tinggi dan spesifik sehingga engineer pengganti akan memvonis: "Ini harus di-rewrite ulang dari nol."
  3. Biaya Ganda: Anda tidak hanya membayar gaji engineer baru, tapi juga membayar biaya hilangnya momentum bisnis karena stagnasi pengembangan selama berbulan-bulan.

Stop berharap pada satu orang. Pecah silo pengetahuan hari ini, atau Anda akan dipaksa me-reboot ulang produk Anda di masa depan.


🎓 7. Lessons Learned

What Went Well

  • 🧠 Offline-first mindset dari hari pertama — bukan afterthought.
  • 🐹 Golang terbukti ideal untuk high-concurrency sync workloads.
  • 📡 MQTT (sebelum migrasi) jauh lebih efisien dibanding HTTP polling untuk kondisi low-bandwidth.
  • 🦸‍♂️ Single-fighter backend memungkinkan keputusan arsitektur yang cepat tanpa bottleneck meeting dan approval. Tim frontend cukup consume API contract yang sudah saya definisikan di awal.
  • 💬 Menggantikan Microsoft Teams workflow dengan sistem dedicated meningkatkan efisiensi secara drastis.

What I'd Do Differently

  • 📝 Mulai dengan CRDT (Conflict-free Replicated Data Types) sejak awal, bukan LWW yang kemudian harus di-migrate.
  • 🤖 Invest lebih awal di automated E2E testing untuk offline scenarios — sulit dikoordinasikan antara backend (saya) dan frontend (tim lain) saat deadline ketat.
  • 📦 Gunakan Protocol Buffers sejak awal — JSON parsing overhead terasa pada device low-end.
  • 📢 Advokasi lebih kuat untuk mempertahankan message broker architecture dengan menyediakan runbook dan monitoring yang lebih baik untuk tim operations.
  • Push for better CI/CD infrastructure sejak awal — pipeline yang lambat menghambat seluruh tim, bukan hanya saya.

Technical Debt yang Masih Ada

  • 🔄 Migration dari SQLite ke WatermelonDB untuk lazy loading yang lebih baik.
  • ⚠️ Standardisasi error codes antara Kafka events dan REST API responses.
  • 🔌 Implementasi circuit breaker pattern di Sync Manager.
  • Optimisasi CI/CD pipeline — target di bawah 5 menit per deployment stage.

🎉 Conclusion

Project ini membuktikan bahwa seorang backend engineer yang menguasai arsitektur distributed systems — dari API design, message brokers, hingga sync engine — bisa men-deliver seluruh backend infrastructure sendirian dalam waktu yang sangat terbatas.

Fitur tersulit bukan selalu tentang algoritma AI yang canggih. Terkadang, engineering excellence adalah tentang empati — memahami bahwa user kita berdiri di tengah sawah dengan sinyal 1 bar, dan memastikan teknologi tetap melayani mereka dengan tangguh.

Personal Note

Yang membuat saya bangga: teknologi yang baik adalah teknologi yang invisible. Petugas tidak perlu tahu tentang Kafka, MQTT, atau delta sync. Yang mereka tahu: aplikasi ini just works, bahkan di tengah hutan — dan seluruh backend yang menopang itu saya bangun sendiri dalam 30 hari.


Related Articles