ANALYSIS_ONLY — High Availability Flow SHIFRAUD

[!GOLD] Status dokumen

Dokumen ini adalah analisis fase pertama. Isinya belum merupakan SRS, HLD, LLD, atau Impact Analysis, dan belum menyatakan rancangan sudah diimplementasikan. Empat dokumen tersebut baru dibuat setelah scope dan keputusan di bagian akhir disetujui secara eksplisit.

Pemahaman dan Batas Scope

Topik

Menyusun flow High Availability SHIFRAUD berdasarkan source aplikasi di shifraud-core dan konfigurasi infrastruktur di /home/goy/shifor/shifraud-ha-conf.

Analisis membedakan empat jenis evidence:

Label Arti
CONFIRMED Terlihat langsung di source, config, atau log yang diperiksa
REFERENCE Diklaim oleh README/playbook, tetapi belum dibuktikan oleh runtime test
DERIVED Kesimpulan teknis dari beberapa evidence
PROPOSED Target design yang belum diimplementasikan

Ringkasan posisi sekarang

Area Klaim/dokumen Config yang aktif Runtime evidence yang tersedia Kesimpulan
PostgreSQL Empat node Patroni dalam satu stretched cluster Empat node, tiga etcd, failover_priority DC 100 dan DRC 1 Tidak ada hasil test terisi Logika election tersedia, hasil failover belum terbukti
DB entry point haproxy-dc:5000 mengikuti leader lintas site Satu instance HAProxy di DC Belum ada runtime evidence continuity Masih single point of failure
App app-dc dan app-drc active-active Kedua app dan Nginx di-comment/nonaktif; upstream DRC juga di-comment Log lama DRC menunjukkan gagal resolve haproxy-drc Active-active belum terwujud
Redis Master/replica dengan Sentinel failover Local test: satu Sentinel, quorum 1; production template: tiga Sentinel, quorum 2 Belum ada hasil failover terukur Local bukan HA; topology production gagal quorum jika dua Sentinel DC hilang
Ingress Nginx membagi trafik ke dua app Nginx production hanya mengaktifkan app DC Tidak ada continuity evidence App ingress masih DC-centric
Data durability PostgreSQL replication lintas site Asynchronous; synchronous_mode tidak aktif Tidak ada RPO test Committed transaction terakhir masih berisiko hilang saat failover
Idempotency Retry transaksi aman Ada unique key (stan, local_date, pid) pada changelog utama Belum ada test retry lintas failover Fondasi ada, kontrak replay end-to-end belum terbukti
Observability Failover audit tersedia FailoverAuditLogger ada Dua file failover-audit.log kosong Belum cukup untuk audit failover produksi

Tujuan

Success criteria fase desain

In scope

Out of scope

Current State dan Before Flow

Evidence utama

Before flow — transaksi normal pada konfigurasi yang dimaksud

[Diagram]

Diagram tersebut adalah gabungan source/config yang dimaksud, bukan runtime proof. Compose aktif saat ini tidak menjalankan Nginx DC atau App DC.

Before flow — DB primary gagal tetapi DC masih hidup

[Diagram]

REFERENCE — playbook mengharapkan recovery sekitar 10–30 detik. Nilai tersebut belum dianggap hasil karena metrics sheet masih kosong dan tidak ada test artifact yang membuktikannya.

Before flow — full DC outage saat ini

[Diagram]

Playbook test 2.5 memerintahkan stop haproxy-dc, lalu memverifikasi write melalui haproxy-dc:5000. Langkah tersebut kontradiktif. Setelah HAProxy dihentikan, endpoint yang diuji juga hilang.

Analisis Masalah dan Root Cause

Observed problem Evidence Root cause / status Dampak Required change
Database bisa promote di DRC tetapi service belum tentu dapat diakses HAProxy dan Nginx production hanya ada di DC CONFIRMED — entry point tidak redundant lintas site Full outage walau DB DRC sehat Sediakan ingress dan DB proxy per site dengan health-based traffic steering
Klaim app active-active tidak sama dengan config App services dan upstream DRC nonaktif CONFIRMED Tidak ada failover app layer Deploy minimal satu app sehat per site dan aktifkan health check
Test full-site tidak executable sesuai tujuan Stop haproxy-dc, lalu query hostname yang sama CONFIRMED False confidence dari test plan Query melalui endpoint DRC/global yang memang tetap hidup
Redis production kehilangan majority saat DC hilang Dua Sentinel di DC, satu di DRC, quorum 2 DERIVED, sesuai aturan majority Redis Sentinel Redis DRC tidak dapat melakukan failover otomatis Sebar Sentinel 1 DC + 1 DRC + 1 witness/third site
Potensi kehilangan committed write Patroni memakai asynchronous replication; synchronous_mode tidak ada CONFIRMED RPO lebih besar dari nol saat primary/site hilang Putuskan RPO; aktifkan synchronous mode hanya jika bisnis mewajibkan dan latency sudah diuji
Retry bisa menggandakan side effect Response dapat hilang setelah commit; client/LB dapat retry DERIVED; constraint (stan, local_date, pid) hanya melindungi insert transaksi utama Alert, reaction, notification, atau external call dapat terduplikasi Definisikan idempotency boundary dan replay response untuk seluruh side effect
In-flight transaction tidak bisa dipindahkan ke node lain TCP connection dan Server_Collection berada di memory node CONFIRMED Client timeout/reconnect; status transaksi bisa UNKNOWN Reconciliation berdasarkan business key; jangan blind retry
In-memory state berbeda antar app node SSE emitter, TCP connection, velocity write-behind, dan beberapa cache bersifat node-local CONFIRMED Missed push, skewed counters, lost buffered aggregate saat crash Klasifikasikan state: rebuildable, replicated, sticky, atau harus dipindah ke shared store
Semua scheduler akan aktif pada setiap app node Sebagian scheduler memakai ShedLock, sebagian tidak CONFIRMED Duplicate job/cleanup/file processing Audit seluruh @Scheduled; gunakan distributed lock atau leader-only worker sesuai semantics
Audit failover belum membuktikan event runtime Audit files kosong; logDbReconnect dan logTransactionInFlight belum terbukti terpanggil CONFIRMED RCA dan bukti regulator lemah Wire event secara nyata dan kirim ke centralized immutable logging
Config dependency tidak reproducible Dockerfile.patroni memasang Patroni tanpa pin versi CONFIRMED Behavior build dapat berubah Pin versi Patroni dan lock artifact/image digest
README mengandung dua arsitektur Bagian stretched auto-failover berdampingan dengan manual DR/standby_cluster lama CONFIRMED Operator dapat menjalankan runbook yang salah Hapus/arsipkan flow lama setelah target disetujui

Root cause utama

HA saat ini dirancang per komponen, belum sebagai satu service flow end-to-end. Patroni election, HAProxy routing, Sentinel, Nginx, dan app node dibahas terpisah. Akibatnya sebuah komponen dapat dinyatakan berhasil failover walau jalur client → app → DB/cache sudah putus.

Untuk sistem finansial, status sukses harus ditentukan pada boundary bisnis: apakah request diterima, commit terjadi, response terkirim, side effect hanya sekali, dan transaksi dapat direkonsiliasi ketika response tidak diketahui.

Target State dan After Flow

Prinsip target

Proposed topology

Layer DC DRC Witness/third site Mekanisme
Global entry Endpoint DC Endpoint DRC Control/health only Global LB, DNS failover, atau network VIP TBD
App LB Dua instance/VIP atau managed LB Dua instance/VIP atau managed LB Not Applicable Active health check, connection drain
App Minimal satu node, jumlah final TBD Minimal satu node, jumlah final TBD Not Applicable Stateless request processing; state eksternal/rebuildable
DB proxy HAProxy pair/site atau managed equivalent HAProxy pair/site atau managed equivalent Not Applicable Keduanya probe semua Patroni node; write mengikuti /primary
PostgreSQL Patroni priority tinggi Patroni priority rendah Not Applicable Satu fds-cluster, satu primary
DCS etcd1 etcd2 etcd3 Majority 2/3
Redis data Master/replica candidate Replica/master candidate Not Applicable Replication dan controlled promotion
Redis Sentinel Sentinel 1 Sentinel 2 Sentinel 3 Quorum 2, majority tetap tersedia saat satu site hilang
Observability Local collector Local collector Central store TBD Metrics, logs, traces, audit lintas site

After flow — transaksi normal

[Diagram]

After flow — full DC outage

[Diagram]

After flow — recovery dan failback

[Diagram]

Perbandingan Before dan After

Area Before After Dampak Requirement/Decision
Service health Health per proses/komponen Readiness end-to-end per site Mengurangi false-ready DEC-INFRA-001
App ingress Nginx hanya DC; DRC upstream nonaktif Endpoint/LB independen di DC dan DRC DRC tetap reachable DEC-INFRA-001
DB proxy Satu HAProxy di DC Proxy redundant per site Hilangkan DB entry-point SPOF DEC-INFRA-002
PostgreSQL Stretched async Patroni Single-writer tetap; durability mode diputuskan dari RPO Availability vs latency eksplisit DEC-DB-001
Redis Sentinel Local satu Sentinel; prod 2 DC + 1 DRC 1 DC + 1 DRC + 1 witness Majority survive one-site loss DEC-CACHE-001
Retry Generic retry belum dibatasi Retry dengan business idempotency + reconciliation Mencegah duplicate financial side effect DEC-APP-001
Scheduler Campuran locked/unlocked Semua job diklasifikasi dan dikoordinasikan Hindari duplicate job DEC-APP-002
SSE/TCP Node-local connection Reconnect-aware; tidak menjanjikan seamless transfer Client behavior eksplisit DEC-APP-003
Failback Manual, gate belum lengkap Controlled switchover setelah lag/health gate Mengurangi second outage DEC-OPS-001
Testing Banyak expected result, metrics kosong Evidence bundle per scenario Klaim HA dapat diaudit DEC-OPS-002

Requirement Challenge

“Active-active” perlu didefinisikan per layer

App dapat active-active. PostgreSQL dalam design ini tidak: hanya satu primary yang menerima write. Redis juga mempunyai satu master. Istilah yang lebih tepat adalah active-active application, active-passive stateful services, multi-site automatic failover.

Automatic failover tidak sama dengan zero downtime

Dengan ttl: 30, election dan reconnection mempunyai failure window. Koneksi TCP lama putus dan tidak dapat dipindahkan. Request yang sudah commit tetapi response belum sampai menjadi UNKNOWN. Karena itu target “zero downtime” atau “zero failed transaction” tidak boleh disetujui tanpa protocol-specific retry/reconciliation dan hasil test.

failover_priority bukan larangan absolut

Patroni mengutamakan node dengan WAL receive/replay LSN paling maju; priority membedakan kandidat ketika posisi WAL setara. Jadi klaim “DRC hanya pernah promote setelah semua node DC mati” perlu diuji terhadap lag/timeline aktual, bukan hanya dibaca dari nilai 100 versus 1.

Asynchronous replication adalah keputusan bisnis

Konfigurasi sekarang mengutamakan availability dan latency, tetapi dapat kehilangan committed write yang belum sampai ke replica. Dokumentasi resmi Patroni menjelaskan bahwa batas data loss juga dipengaruhi WAL yang ditulis selama window ttl. Untuk transaksi finansial, pemilik bisnis harus menyetujui RPO. synchronous_mode tidak boleh diaktifkan otomatis tanpa latency dan WAN partition test.

Read replica dapat menghasilkan stale read

Semua transaksi Spring readOnly=true diarahkan ke port 5001. Setelah write, request berikutnya dapat membaca replica yang belum catch up. Flow yang membutuhkan read-your-write harus tetap ke primary atau menggunakan consistency rule yang eksplisit.

Nginx passive health check tidak cukup untuk site readiness

Config Nginx open-source baru menandai backend bermasalah setelah request error/timeout. Untuk financial traffic, routing idealnya memakai active readiness probe yang memeriksa dependency penting. Tetap perlu batas agar health check tidak memperparah load saat DB/cache terganggu.

Gap dan Edge Cases

Gap matrix

Area Current state Target state Gap Required change
Infrastructure LB/proxy utama di DC Endpoint independen per site Belum ada DRC entry point Tambah LB/proxy DRC dan global steering
Application DRC app belum aktif App runnable dan ready di kedua site Deployment/config belum tersedia Buat profile/env contract yang sama, berbeda endpoint/node ID
Database Election tersedia Election + reachable proxy + measured RPO Proxy dan RPO belum selesai Redundant proxy, version pin, failover test
Cache Sentinel placement tidak tahan DC loss Majority lintas tiga failure domain Penempatan salah Pindah salah satu Sentinel DC ke witness
Idempotency Unique transaction tuple tersedia Semua duplicate side effect dibatasi Coverage belum terbukti Trace transaction, alert, reaction, notification, external call
Scheduler Sebagian memakai ShedLock Semua job safe multi-node Beberapa job tidak locked Audit dan pilih lock/leader/outbox
Stateful memory Banyak state node-local State loss/rebuild behavior eksplisit Belum diklasifikasi Inventory dan test node crash
Observability Log audit kosong Correlated failover audit dan metric Wiring/centralization belum terbukti Instrument event dan immutable sink
Operations Runbook lama dan baru bercampur Satu approved runbook Operator ambiguity Hapus flow manual lama setelah migration
Security Placeholder credential dan plaintext endpoints Secret management + TLS sesuai environment Production config belum final Integrate vault/secret store dan certificate lifecycle

Edge cases

Skenario Perilaku yang diharapkan Risiko Penanganan Status/evidence
Commit berhasil, response putus Retry mengembalikan outcome yang sama Double debit/reaction Reconcile by business key; replay result PROPOSED
DC-Witness partition, DRC punya quorum Hanya partition mayoritas boleh primary Split brain etcd majority + fencing test Config ada, test belum terbukti
DRC tertinggal > allowed lag Jangan promote kandidat yang unsafe Data loss Lag gate dan alert maximum_lag_on_failover ada
Read segera setelah write Data terbaru terbaca Stale decision Primary read/read-your-write rule NEEDS_CLARIFICATION
Redis master hilang bersama dua Sentinel DC DRC tetap dapat authorize promotion Cache outage Sentinel ketiga di witness Current prod topology gagal criterion
App mati saat write-behind buffer terisi Raw transaction tetap durable; aggregate direbuild Temporary scoring skew Recovery/warmup test dan metric buffer Source menyebut rebuildable, runtime unverified
TCP client reconnect ke node lain Session baru diterima, old in-flight direkonsiliasi Duplicate/timeout Client contract + business idempotency NEEDS_CLARIFICATION
SSE client pindah node Client reconnect dan refresh state Missed notification SSE sebagai hint, state diambil dari API/DB PROPOSED
Dua app menjalankan scheduler tanpa lock Hanya satu side effect terjadi Duplicate batch/cleanup ShedLock/leader-only/idempotent worker Gap ditemukan
Liquibase start pada dua app Migration serialized atau dipisah dari app start Startup race/lock contention Dedicated migration job disarankan PROPOSED
DC pulih dengan timeline lama Node rejoin sebagai replica Divergent history pg_rewind, timeline verification Config use_pg_rewind ada
Global LB menganggap app sehat saat DB write path gagal Site tidak menerima write traffic Error storm Dependency-aware readiness dengan timeout PROPOSED

Alternatif dan Trade-off

Opsi Manfaat Kekurangan Risiko Kompleksitas/upaya Rekomendasi
A. Pertahankan satu stretched Patroni cluster, tambah ingress/proxy per site Perubahan paling dekat dengan config sekarang; automatic election tetap Bergantung WAN dan DCS lintas site Latency replication, partition handling Menengah Direkomendasikan sebagai baseline, setelah RPO dan network topology disetujui
B. Dua cluster terpisah dengan manual DR Isolasi site lebih kuat; operasi DR eksplisit RTO lebih lama; promote/failback rumit Human error, stale replica, split brain saat salah prosedur Menengah-tinggi Pilih jika governance melarang stretched DCS
C. Dua cluster dengan logical/CDC replication Fleksibel untuk regional topology Conflict, ordering, schema compatibility jauh lebih kompleks Duplicate/lost financial side effect Tinggi Tidak direkomendasikan tanpa kebutuhan multi-writer yang nyata
D. Managed PostgreSQL multi-AZ/multi-region Mengurangi operasi Patroni/etcd Vendor/cost/network constraint; belum tentu tersedia on-prem Lock-in dan capability mismatch Bergantung platform Evaluasi hanya bila environment mengizinkan

Rekomendasi awal adalah opsi A, tetapi istilah “active-active” dibatasi pada app layer. Database dan Redis tetap single-primary dengan automatic promotion.

Decision Register

ID Keputusan Domain/Jenis Status Rationale/Evidence Dampak Relasi
DEC-INFRA-001 Sediakan ingress sehat dan independen di DC/DRC, lalu global traffic steering Infrastructure PROPOSED Ingress sekarang hanya DC DRC dapat menerima trafik saat DC hilang Full-site flow
DEC-INFRA-002 Jalankan DB proxy redundant per site Infrastructure PROPOSED haproxy-dc adalah SPOF App DRC tidak bergantung proxy DC DEC-INFRA-001
DEC-DB-001 Pertahankan PostgreSQL single-writer dan putuskan async/sync berdasarkan RPO Database NEEDS_CLARIFICATION Async memberi availability, tetapi RPO > 0 Mempengaruhi latency dan durability RPO/RTO
DEC-CACHE-001 Tempatkan Sentinel pada tiga failure domain Cache PROPOSED Majority harus bertahan dari satu site loss Redis failover tetap authorized Full-site flow
DEC-APP-001 Wajibkan idempotency + reconciliation untuk financial retry Application PROPOSED Unique tuple belum membuktikan semua side effect aman Mengurangi duplicate dan status UNKNOWN Retry flow
DEC-APP-002 Audit dan koordinasikan semua scheduled job untuk multi-node Application PROPOSED Ada scheduler tanpa @SchedulerLock Hindari duplicate processing App active-active
DEC-APP-003 Perlakukan TCP/SSE sebagai reconnectable, bukan transparently movable Application PROPOSED Connection state berada di memory node Client contract dan UX harus jelas Failover flow
DEC-OPS-001 Failback selalu controlled switchover setelah health/lag gate Operations PROPOSED Automatic failback berisiko second outage Recovery lebih aman Recovery flow
DEC-OPS-002 Klaim HA hanya setelah evidence bundle test terisi Operations PROPOSED Metrics sheet dan audit log masih kosong Status readiness dapat diaudit Semua decision
DEC-SEC-001 Production menggunakan secret management dan encrypted transport Security PROPOSED Template masih berisi placeholder dan local config terbuka Mengurangi credential/network exposure Production deployment

Open Questions dan Rekomendasi Approval

Blocker keputusan

  1. Berapa RPO dan RTO yang diterima untuk transaksi online, alert, dan cache? Angka final masih (perlu dilengkapi).
  2. Apakah WAN DC–DRC mampu dan diizinkan untuk synchronous PostgreSQL replication? Latency, jitter, packet loss, dan bandwidth belum tersedia.
  3. Apa global entry point production: DNS failover, GSLB, appliance, Keepalived/VIP, atau load balancer lain? TBD.
  4. Apakah client ISO 8583 mengulang transaksi dengan STAN + localDate + pid yang stabil, dan bagaimana response duplicate harus dibentuk? NEEDS_CLARIFICATION.
  5. Dependency mana yang wajib dalam readiness: write DB, read DB, Redis, license, Kafka/RabbitMQ, ML service, file share? NEEDS_CLARIFICATION.
  6. Apakah DRC app harus selalu menerima traffic normal atau hanya warm standby? Ini menentukan arti active-active dan kapasitas DRC.
  7. Di mana file/bulk input, model, GeoIP, license, dan output report disimpan agar kedua app node melihat data yang konsisten?
  8. Siapa pemilik approval failback dan apa maintenance/incident gate-nya? (perlu dilengkapi).

Rekomendasi scope yang dimintakan approval

Approval yang disarankan:

Jika scope ini disetujui dengan APPROVED atau GENERATE DOCUMENTATION, fase berikutnya akan menghasilkan tepat empat artefak: SRS, HLD, LLD, dan Impact Analysis.

Evidence Index

Source dan config lokal

Referensi perilaku vendor

Verification yang dilakukan