← Semua picks

Bundle Recipe Recommended

Bundle Enterprise: Spring + Postgres + K8s

Stack enterprise default yang saya jalankan 26 bulan di fintech series-B + BUMN energy Jakarta. Spring Boot 3 + Postgres + K8s + Kafka + Redis. Total cost Rp 45-65 juta/bulan untuk 18 service. Verdict Recommended sebagai baseline 2026.

18 Juli 2026 · 12 menit ·Use case: Bundle stack enterprise default untuk fintech / BUMN Indonesia 2026
Spring Boot 3PostgreSQLKubernetesKafka

TL;DR

  • Bundle Components: Spring Boot 3 (Java 21 LTS) + PostgreSQL (Cloud SQL atau self-host) + Kubernetes (GKE) + Kafka self-host + Redis + Cloudflare edge.
  • Cost run-rate: Rp 45-65 juta/bulan untuk 18 service enterprise fintech.
  • Performance baseline: p99 latency < 250ms, throughput 1k-2k RPS per service, availability 99,94%.
  • Verdict: Recommended sebagai baseline enterprise Indonesia 2026. Default untuk fintech series-B, BUMN, enterprise mid-size.

Konteks

Saya jalankan bundle ini paralel 26 bulan (Maret 2024 - Mei 2026) di:

  • Fintech series-B Jakarta: 18 microservice, full bundle, run-rate Rp 52 juta/bulan
  • BUMN energy Jakarta: 22 microservice, hybrid bundle (Rancher on-prem K8s instead of GKE, Postgres on-prem instead of Cloud SQL), run-rate equivalent Rp 78 juta/bulan (lebih mahal karena on-prem amortization + ops time)

Sebelumnya 8+ tahun pengalaman stack Spring + Postgres (sejak Spring 3.x era, Postgres 9.x).

Pricing breakdown (Juni 2026)

Compute K8s (GKE Autopilot Jakarta)

  • Control plane: USD 73/bulan/cluster × 2 (prod + staging) = USD 146/bulan
  • Workload pod compute: ~18 service × 3 replica × resource request average
  • Untuk fintech: ~Rp 16-20 juta/bulan
  • Total compute: ~Rp 18 juta/bulan

Database PostgreSQL (Cloud SQL Postgres regional HA)

  • Tier db-custom-4-15360 (4 vCPU, 15GB RAM, 500GB SSD), regional HA + read replica:
    • Primary: Rp 4,2 juta/bulan
    • Replica: Rp 2,1 juta/bulan
    • Backup automated PITR: Rp 1,8 juta/bulan
  • Total DB: Rp 8,1 juta/bulan

Message Broker (Kafka self-host)

  • 3-broker cluster di GKE Jakarta n2-standard-4: Rp 5,8 juta/bulan
  • Schema Registry + Connect: Rp 1,8 juta/bulan
  • MirrorMaker 2 ke DR Singapore: Rp 1,2 juta/bulan
  • Total Kafka: Rp 8,8 juta/bulan

Cache (Redis Memorystore basic-HA)

  • Tier basic-1, 4GB: Rp 1,6 juta/bulan
  • Snapshot ke R2: Rp 200 ribu/bulan
  • Total Redis: Rp 1,8 juta/bulan

Storage (Cloudflare R2)

  • 500GB object storage (asset, backup, log archive): Rp 1,2 juta/bulan

Observability (LGTM stack self-host)

  • Grafana + Loki + Tempo + Mimir cluster: Rp 12,4 juta/bulan (lihat artikel observability detail)

Secret management (HashiCorp Vault)

  • 3 Vault pod di GKE + KV backend: Rp 800 ribu/bulan

Networking + Load Balancer

  • Cloudflare Pro + WAF: USD 25/bulan
  • Cloud Load Balancer GCP: Rp 1,6 juta/bulan
  • Egress bandwidth: Rp 400 ribu/bulan
  • Total networking: Rp 2,4 juta/bulan

Total run-rate

KomponenCost/bulan
Compute K8sRp 18 juta
Postgres regional HARp 8,1 juta
Kafka self-hostRp 8,8 juta
RedisRp 1,8 juta
Storage R2Rp 1,2 juta
Observability LGTMRp 12,4 juta
Vault secretRp 800 ribu
Networking + LBRp 2,4 juta
TotalRp 53,5 juta/bulan

Cost per service: Rp 53,5 juta / 18 = ~Rp 3 juta/service/bulan all-in. Untuk B2B SaaS dengan target Rp 5-15 juta/customer/bulan, infra cost ~20-60% revenue/customer = healthy.

SLO + performance (26 bulan)

Service-level (per microservice average)

MetrikTargetRealisasi
Availability per service99,95%99,94%
p50 latency HTTP< 30ms22ms
p99 latency HTTP< 250ms185ms
Throughput sustained per pod> 1.000 RPS1.380 RPS
Cold start (Spring Boot 3 + Java 21)< 8 detik4-6 detik
GC pause p99 (ZGC)< 15ms8ms

System-level

MetrikTargetRealisasi
End-to-end availability (compound)99,9%99,87%
RTO regional failover< 30 menit18-25 menit
RPO data< 5 menit30 detik - 2 menit
Deploy lead time p99< 20 menit14 menit
MTTR P1 incident< 60 menit45 menit

Architecture pattern

Stack arsitektural

                    Cloudflare WAF + DDoS

                       Cloudflare PoP Jakarta

                              ├─→ Cloudflare Pages (frontend SPA)

                              └─→ GKE Jakarta Ingress

                              ┌──────┴───────┐
                              │              │
                       Spring Boot 3      Spring Boot 3
                       (Java 21)          (Java 21)
                       Service A          Service B
                              │              │
                       ┌──────┴──────────────┴───┐
                       │                          │
                  Postgres HA              Redis cache
                  (Cloud SQL)              (Memorystore)

                       └─→ Replica Singapore (DR)
                       
                       
                  Kafka cluster
                  (3-broker self-host)

                  ├─→ Audit log
                  ├─→ Event streaming
                  └─→ MirrorMaker → Singapore DR
                  
                  
                  LGTM Observability
                  (Grafana + Loki + Tempo + Mimir)

                       ├─→ Metric, log, trace
                       ├─→ Alert ke Slack + PagerDuty
                       └─→ Audit log retention 7 tahun ke S3 Glacier
                  
                  
                  Vault (HashiCorp)

                       └─→ Secret KV + dynamic credential Postgres

Per-service template

Spring Boot 3 service standard saya:

service-payment/
├── src/main/java/com/company/payment/
│   ├── PaymentApplication.java
│   ├── api/                  # REST controller
│   ├── domain/               # Business logic
│   ├── infrastructure/       # Repository, external client
│   ├── config/               # Spring config
│   └── observability/        # OpenTelemetry init
├── src/main/resources/
│   ├── application.yml       # Profile prod/staging/dev
│   └── db/migration/         # Flyway script
├── src/test/                 # JUnit 5 + Testcontainers
├── Dockerfile                # Multi-stage build, distroless base
├── kustomization.yaml        # K8s manifest
└── pom.xml

application.yml baseline:

spring:
  application:
    name: payment
  datasource:
    url: jdbc:postgresql://postgres-primary:5432/payment
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
  jpa:
    hibernate:
      ddl-auto: validate
  flyway:
    enabled: true
  kafka:
    bootstrap-servers: kafka-1:9092,kafka-2:9092,kafka-3:9092
    producer:
      acks: all
      enable-idempotence: true
  data:
    redis:
      host: redis-master
      port: 6379

server:
  port: 8080
  tomcat:
    threads:
      max-threads: 10000  # virtual threads enabled
  shutdown: graceful

management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus,metrics
  endpoint:
    health:
      probes:
        enabled: true

Database migration pattern

Flyway script di db/migration/:

V1__create_payment_table.sql
V2__add_payment_status_index.sql
V3__add_refund_table.sql

Schema versioning di Git. Migration run otomatis di startup, atau via job pre-deploy untuk control.

Observability instrumentation

Auto-instrumentation via OpenTelemetry Java agent:

java -javaagent:/opt/otel-agent.jar \
  -Dotel.service.name=payment \
  -Dotel.exporter.otlp.endpoint=http://otel-collector:4318 \
  -Dotel.traces.sampler=parentbased_traceidratio \
  -Dotel.traces.sampler.arg=0.1 \
  -jar payment.jar

10% trace sampling untuk service biasa, 100% untuk service kritis (payment).

High availability + DR

Multi-region active-passive

Primary: GKE asia-southeast2 (Jakarta)
   ├── 3 zone HA
   ├── Postgres Cloud SQL regional HA (synchronous replication)
   ├── Kafka 3-broker (acks=all)
   └── Redis basic-HA

DR: GKE asia-southeast1 (Singapore)
   ├── 30% capacity standby
   ├── Postgres replica (async, RPO 30 detik)
   ├── Kafka mirror via MirrorMaker 2
   └── Redis snapshot restore

Failover trigger:
- Manual via runbook (BUMN compliance)
- Auto-detect health check fail &gt; 5 menit (fintech)
- DNS swap via Cloudflare API

RPO/RTO realisasi

KomponenRPO targetRTO targetRealisasi
Compute K8s05 menit3-4 menit
Postgres5 menit30 menit30-90 detik / 12-18 menit
Kafka5 menit15 menit1-3 menit / 8-12 menit
Redis60 menit10 menitsnapshot last + restore 6-10 menit
Total system5 menit30 menit2-3 menit / 18-25 menit

Failover test quarterly via chaos engineering drill.

Decision matrix

Kapan adopt bundle full ini?

  • Tim engineering 8+ dev dengan dedicated SRE 1+ FTE
  • 8+ microservice production
  • Customer-facing dengan SLO 99,95%+
  • Budget infra Rp 30+ juta/bulan
  • Compliance audit requirement (OJK, BSP, atau internal)

Kapan sederhanakan bundle?

Untuk SMB < 10 service:

  • Skip K8s: pakai Cloud Run / Fly.io / Railway
  • Postgres managed (Neon, Supabase) instead of Cloud SQL HA
  • Skip Kafka self-host: pakai Confluent Cloud free tier atau hilangkan event streaming kalau tidak butuh
  • Observability: Grafana Cloud free tier (50GB log gratis)
  • Cost target: Rp 5-15 juta/bulan

Kapan upgrade ke beyond bundle?

Untuk enterprise large (50+ microservice, 100+ engineer):

  • Service mesh (Istio, Linkerd) untuk traffic management + mTLS
  • Multi-cluster federation
  • Distributed cache (Hazelcast, Apache Ignite)
  • Premium observability (Datadog APM AI insight)
  • Cost: Rp 200+ juta/bulan

Trade-off

Pro bundle ini

  • Maturity: setiap komponen battle-tested 10+ tahun production
  • Hiring: pool Indonesia paling besar untuk semua komponen
  • Documentation: knowledge base luas + community Indonesia aktif
  • Scalability: scale dari 3 pod ke 300 pod tanpa rewrite arsitektural
  • Compliance: pattern audit-friendly + data residency Indonesia controllable
  • Cost predictable: scale predictable, no surprise pricing

Con bundle ini

  • Operational overhead: butuh dedicated SRE (LGTM, K8s, Kafka semua ops-heavy)
  • Cold start Spring Boot: 4-6 detik (vs Quarkus native 60-200ms) — bukan ideal untuk serverless scale-to-zero
  • Java verbosity: lebih banyak boilerplate dibanding Kotlin / Go
  • Kafka complexity: ops 25-35 jam/bulan kalau self-host

Variasi bundle

Bundle BUMN dengan on-prem mandate

  • K8s on-prem (Rancher / Talos) instead of GKE
  • Postgres self-host on-prem instead of Cloud SQL
  • Object storage MinIO instead of R2 (kalau on-prem-only)
  • Cost lebih tinggi karena ops overhead, tapi compliance sektoral satisfied

Bundle fintech series-B agile

  • Full managed cloud (GKE Autopilot, Cloud SQL managed, Memorystore)
  • Konsolidasi ke 1 cloud (saya pilih GCP karena Jakarta region)
  • Cloudflare di depan untuk WAF + DDoS
  • Cost optimized untuk speed-to-market

Bundle SaaS B2B Indonesia mid-market

  • Sama dengan fintech series-B tapi tambah:
    • Multi-tenant pattern (1 deployment, isolation via DB schema atau row-level security)
    • Feature flag (GrowthBook self-host atau LaunchDarkly)
    • Auth bundle (Clerk + WorkOS)

Migration pattern

Dari legacy on-prem ke bundle ini

12-18 bulan total kalau ada legacy investment besar. Pattern bertahap:

  1. Bulan 1-3: Setup K8s + observability paralel dengan legacy
  2. Bulan 4-9: Migrate service per-domain (strangler fig pattern)
  3. Bulan 10-12: Database migration (legacy DB → Postgres)
  4. Bulan 13-15: Decommission legacy
  5. Bulan 16-18: Optimization + hardening

Pengalaman saya di BUMN energy: 14 bulan total untuk full migrate 22 service legacy ke bundle ini.

Dari MVP cloud SaaS ke bundle ini

3-6 bulan kalau scale outgrow Cloud Run / Fly.io. Pattern:

  1. Bulan 1: Setup K8s + observability
  2. Bulan 2-3: Migrate service ke K8s
  3. Bulan 4: Setup Kafka + Redis
  4. Bulan 5: Hardening + compliance
  5. Bulan 6: Performance tuning

Common pitfall

  1. Premature adoption full bundle. Untuk < 8 service: K8s + Kafka + LGTM = over-engineering. Wait until pain point real.
  2. Multi-region tanpa test failover. Failover yang tidak pernah di-test = failover yang tidak akan work saat butuh. Chaos engineering quarterly drill.
  3. Skip observability di awal. “Add later” = tidak pernah. Setup LGTM bersamaan dengan service pertama.
  4. No infrastructure-as-code. Manual click di console = drift, no audit trail. Pakai OpenTofu / Terraform dari hari pertama.
  5. Cost monitoring tidak setup. Cloud cost bisa balloon. Setup billing alert + monthly review.

Cost of ownership 36 bulan

ItemCost 3 tahun
Infrastructure (Rp 53,5 juta × 36)Rp 1,93 miliar
Ops engineer (2 SRE × Rp 35 juta × 36)Rp 2,52 miliar
Migration / build out one-timeRp 1,2 miliar
Insiden (rata-rata Rp 30 juta/quarter)Rp 360 juta
Training tim + tooling upgradeRp 240 juta
Total 3 tahunRp 6,25 miliar

Untuk fintech series-B Series B funded (USD 30-60 juta typical): 6,25 miliar = ~0,3-0,5% total funding. Acceptable.

Untuk BUMN dengan IT budget Rp 25-40 miliar/tahun: 6,25 miliar 3 tahun = ~6-8% IT budget. Acceptable.

Untuk SMB Indonesia Rp 1-3 miliar/tahun IT: 6,25 miliar 3 tahun = 100-200% budget. NOT acceptable — pakai bundle simplified.

Yang surprising

Setelah 26 bulan: ops cost engineer ternyata lebih dari infrastructure cost (47% vs 31%). Untuk justify bundle full, butuh SRE skill + dedication. Tanpa SRE: ops cost balloon karena engineer biasa firefighting + tooling drift.

Surprise lain: Postgres regional HA + read replica setup ternyata cover hampir semua use case enterprise saya. Tidak butuh upgrade ke distributed (Citus, CockroachDB) dalam 26 bulan. Threshold dari single Postgres ke distributed lebih jauh dari ekspektasi awal (saya kira hit di 5k RPS, realita comfortable di 15k+ RPS dengan Postgres tuning + connection pooling agresif).

Verdict

Recommended sebagai bundle baseline enterprise Indonesia 2026.

  • Default fintech series-B / BUMN mid-size / enterprise: Bundle full ini. ROI clear, scalability runway 5-10 tahun.
  • SMB < 10 service: Bundle simplified (skip K8s + self-host Kafka). Cost target Rp 5-15 juta/bulan.
  • Enterprise large 50+ service: Bundle ini sebagai foundation + add service mesh + advanced observability.
  • Skip bundle full kalau Anda < 5 dev atau pre-PMF — over-engineering tidak justify.

Threshold konkret untuk adopt: 8+ microservice + dedicated SRE 0,5+ FTE + budget Rp 30+ juta/bulan infra. Di bawah ini, bundle simplified atau platform abstraksi (Cloud Run, Fly.io) lebih ROI-friendly.

Ditulis oleh Asti Larasati

// Pick Bundle Recipe lain


← Semua picks RSS feed