Start HereOrdered learning track

System Scope and Architecture Map

Learn Enterprise CPQ OMS Camunda 7 - Part 001

Menentukan scope, mental model arsitektur, service boundary, dan production bar untuk membangun platform Java microservices CPQ dan Order Management enterprise-grade dari nol.

21 min read4054 words
Start
Next
Lesson 0164 lesson track0112 Start Here
#java#microservices#cpq#oms+10 more

Part 001 — System Scope and Architecture Map

Kita tidak sedang membangun aplikasi quote sederhana. Kita sedang membangun platform CPQ + OMS enterprise-grade: sistem yang menangani konfigurasi produk, pricing, approval, quotation, acceptance, order capture, orchestration, fulfillment coordination, audit, exception handling, dan integration event ke sistem lain.

Perbedaan utamanya ada di sini:

Playground project fokus pada “fitur jalan”. Enterprise platform fokus pada “fitur tetap benar ketika data berubah, user bersamaan, approval berbeda, integrasi gagal, order sebagian sukses, proses tertunda, dan auditor bertanya enam bulan kemudian”.

Part ini adalah peta medan. Setelah part ini kamu harus punya gambaran jelas tentang:

  1. sistem apa yang akan dibangun,
  2. batas mana yang sengaja tidak kita bangun,
  3. service apa saja yang dibutuhkan,
  4. data apa yang menjadi source of truth,
  5. bagaimana OpenAPI, Schema-first, Jersey, EclipseLink, PostgreSQL, Camunda 7, Kafka, dan Redis ditempatkan secara masuk akal,
  6. invariant apa yang harus dijaga sejak awal.

Kita mulai dari scope, bukan dari framework.


1. Problem Statement

Platform yang akan kita bangun melayani proses:

product catalog → configure → price → quote → approve → accept → order → orchestrate → fulfill → close/fallout

Dalam dunia enterprise, proses ini hampir tidak pernah lurus. Contohnya:

  • produk bisa berupa bundle dengan dependency dan incompatibility,
  • harga bisa punya discount, surcharge, contract price, promotion, tax placeholder, dan manual override,
  • quote bisa direvisi berkali-kali,
  • approval bisa tergantung margin, discount, region, customer segment, product risk, dan sales hierarchy,
  • order bisa dipecah menjadi beberapa fulfillment item,
  • fulfillment bisa sebagian sukses dan sebagian gagal,
  • proses bisa butuh manual intervention,
  • event harus dikirim ke CRM, Billing, Inventory, ERP, Notification, dan Data Platform,
  • semua keputusan penting harus bisa dijelaskan ulang.

Sistem seperti ini tidak bisa dimodelkan sebagai CRUD biasa.

Salah satu kesalahan paling mahal dalam CPQ/OMS adalah memperlakukan quote seperti shopping cart dan order seperti row header-detail biasa. Untuk sistem kecil, mungkin cukup. Untuk sistem enterprise, itu biasanya menjadi sumber bug lifecycle, pricing drift, data audit lemah, dan proses recovery yang kacau.


2. Target System yang Akan Dibangun

Kita akan membangun reference implementation dengan karakteristik berikut:

  • Java microservices sebagai runtime utama.
  • OpenAPI-first untuk HTTP API contract.
  • Schema-first untuk payload, command, event, dan validation contract.
  • JAX-RS/Jersey untuk REST resource layer.
  • PostgreSQL sebagai transactional source of truth.
  • JPA EclipseLink untuk persistence mapping di service yang cocok memakai ORM.
  • Camunda 7 untuk BPMN/DMN workflow orchestration.
  • Kafka untuk integration events dan asynchronous propagation.
  • Redis untuk cache, TTL-based ephemeral state, idempotency helper, dan read optimization tertentu.
  • Outbox pattern untuk menghubungkan transaksi database dan event publishing.
  • Operational control plane untuk admin, replay, compensation, incident visibility, dan recovery.

Yang kita bangun bukan hanya code, tetapi sistem berpikir: bagaimana memutuskan boundary, data ownership, consistency model, failure behavior, dan observability.


3. Non-Goals

Agar pembelajaran tajam, beberapa hal sengaja tidak menjadi fokus utama:

AreaTidak Menjadi FokusAlasannya
Basic JavaSyntax, OOP dasar, collection dasarSudah diasumsikan dikuasai.
Basic SQL/PostgreSQLSELECT/JOIN/index dasarSeri ini memakai PostgreSQL untuk desain sistem, bukan tutorial SQL dari nol.
Basic KafkaProducer/consumer hello worldFokus kita adalah event architecture CPQ/OMS.
Basic RedisSET/GET/cache sederhanaFokus pada boundary penggunaan Redis di sistem enterprise.
UI detailPixel-perfect frontendKita hanya bahas BFF dan user journey kritikal.
Full billing engineInvoice, tax final, payment reconciliationBilling adalah downstream boundary, bukan inti CPQ/OMS.
Full ERPProcurement/accounting/warehouse lengkapKita cukup desain integration boundary.
Camunda 8 migration deep diveZeebe, Operate, Tasklist, connectorsSeri ini fokus Camunda 7; migration fence dibahas nanti.

Non-goal bukan berarti tidak penting. Non-goal berarti tidak boleh mengaburkan inti pembelajaran.


4. First Architecture Sketch

Secara kasar, sistem kita akan terlihat seperti ini:

Diagram ini belum final. Di part berikutnya kita akan menguji apakah boundary-nya benar dari domain lifecycle.

Untuk sekarang, simpan satu prinsip:

Service boundary tidak boleh ditentukan dari tabel database. Service boundary harus ditentukan dari ownership atas keputusan bisnis, lifecycle, invariant, dan failure mode.


5. Capability Map

Sebelum bicara service, kita bicara capability.

Capability adalah kemampuan bisnis atau teknis yang harus ada agar sistem bisa menjalankan quote-to-order secara defensible.

CapabilityTanggung JawabContoh Keputusan
Product CatalogMenyediakan produk, offering, bundle, attribute, constraint metadataProduk A boleh dijual ke segment X?
ConfigurationMemvalidasi kombinasi pilihan produkOption B wajib jika product C dipilih?
PricingMenghitung price component, discount, surcharge, override, traceDiscount 15% valid atau butuh approval?
Quote ManagementMengelola lifecycle commercial proposalQuote boleh diedit setelah approved?
ApprovalMenentukan apakah quote perlu approval dan siapa approverMargin rendah harus approval level berapa?
Order ManagementMengubah accepted quote menjadi fulfillment intentQuote version mana yang menjadi order?
Workflow OrchestrationMengatur proses long-running, retry, task, escalationKalau inventory gagal, retry atau fallout?
Inventory IntegrationMengecek availability dan reservationStock cukup untuk semua order line?
Document GenerationMembuat proposal/quote artifact immutablePDF memakai template versi apa?
NotificationMengirim pesan ke user/systemApproval reminder kapan dikirim?
AuditMencatat perubahan, keputusan, dan alasanSiapa override harga? Kenapa?
Search/Read ModelMenyediakan query lintas entity untuk UI/opsTampilkan order stuck 24 jam terakhir.
Admin Control PlaneMengelola config, rule, process, recoveryRe-run failed event / fix stuck process.

Dari capability map, baru kita turunkan service map.


6. Proposed Service Boundary

Kita akan mulai dengan boundary seperti ini:

ServicePrimary OwnershipBukan Tanggung Jawabnya
catalog-serviceProduct offering, product spec, bundle metadata, catalog versionMenghitung final price.
configuration-serviceConfiguration validation, compatibility, dependency graphMenyimpan quote lifecycle.
pricing-servicePrice calculation, price trace, discount rule, surchargeApproval workflow execution.
quote-serviceQuote aggregate, quote line, quote lifecycle, revision, acceptanceFulfillment orchestration.
approval-policy-serviceApproval requirement, approval matrix, approval decision supportHuman task execution.
order-serviceOrder aggregate, order line, order lifecycle, decomposition resultCatalog authoring.
workflow-serviceBPMN deployment, process start/correlation helper, workflow facadeMenjadi source of truth semua domain state.
document-serviceQuote/order document generation and artifact metadataMengubah price atau order.
notification-serviceNotification template, delivery attempt, retryMenentukan business approval.
audit-serviceAppend-only audit and decision trailMenjadi transactional source untuk quote/order.
search-serviceDenormalized read model for search and opsMenjadi source of truth.
admin-serviceOperational command, replay, config view, recovery UI APIBypass invariant domain.

Boundary ini tidak sempurna. Ia adalah starting point. Sepanjang seri, kita akan menguji boundary ini dengan skenario nyata.


7. Core Architectural Invariants

Sebelum menulis code, kita butuh invariant. Invariant adalah aturan yang tidak boleh dilanggar walau sistem sedang sibuk, event telat, user klik dua kali, atau service downstream gagal.

7.1 Quote Invariants

  1. Quote memiliki identity stabil.
  2. Quote revision bersifat eksplisit.
  3. Accepted quote harus menunjuk ke satu quote revision yang immutable.
  4. Harga yang ditampilkan ke customer harus bisa direkonstruksi.
  5. Manual override harus menyimpan actor, reason, timestamp, dan policy impact.
  6. Quote yang sudah accepted tidak boleh diam-diam berubah karena catalog atau price rule berubah.
  7. Quote expiry harus deterministic.
  8. Approval decision harus terikat pada quote revision, bukan hanya quote header.

7.2 Order Invariants

  1. Order berasal dari accepted quote atau valid order capture command.
  2. Order harus punya commercial snapshot yang cukup untuk audit.
  3. Fulfillment boleh asynchronous, tetapi order identity dan line identity harus stabil.
  4. Order status harus merepresentasikan progress aggregate, bukan sekadar status teknis workflow.
  5. Duplicate submit tidak boleh membuat order ganda.
  6. Cancellation/amendment harus lewat command yang terkontrol.
  7. Partial failure harus terlihat dan recoverable.

7.3 Pricing Invariants

  1. Setiap price result punya price trace.
  2. Rounding rule harus konsisten.
  3. Discount manual harus dibedakan dari discount rule-based.
  4. Price calculation harus version-aware.
  5. Pricing cache tidak boleh menjadi source of truth.
  6. Reprice harus menghasilkan revision/trace baru, bukan menimpa jejak lama tanpa alasan.

7.4 Workflow Invariants

  1. Workflow process instance bukan pengganti domain aggregate.
  2. Business key harus bisa menghubungkan process instance dengan quote/order.
  3. Task completion harus idempotent dari sudut pandang domain command.
  4. Retry teknis tidak boleh menciptakan side effect bisnis ganda.
  5. Incident harus dapat diklasifikasikan: transient, data issue, integration issue, policy issue, human issue.

7.5 Event Invariants

  1. Event yang sudah dipublish tidak boleh diubah.
  2. Event harus menyatakan fakta yang sudah terjadi, bukan harapan.
  3. Event consumer harus idempotent.
  4. Event schema harus versioned.
  5. Outbox record harus berada dalam transaksi yang sama dengan perubahan aggregate.
  6. Replay tidak boleh merusak state saat ini.

Invariant ini akan terus muncul. Kalau kamu bisa menjaga invariant ini, desain sistemmu naik kelas.


8. Why Camunda 7 Is in the Architecture

Camunda 7 kita gunakan bukan karena semua hal harus jadi BPMN. Kita gunakan karena CPQ/OMS punya proses long-running yang natural:

  • quote approval,
  • discount exception handling,
  • order orchestration,
  • fulfillment retry,
  • manual fallout,
  • escalation,
  • SLA monitoring,
  • compensation,
  • operational recovery.

Namun ada batas penting:

Camunda mengorkestrasi proses. Domain service tetap menjaga invariant domain.

Jangan menaruh semua logic bisnis di BPMN. BPMN bagus untuk alur, dependency, wait state, retry, task, escalation, dan compensation. Tetapi validasi aggregate, consistency rule, dan domain transition harus tetap berada di service domain.

8.1 Camunda 7 Placement

Ada beberapa pola deployment:

PolaDeskripsiKapan Cocok
Embedded engine per serviceEngine berjalan di aplikasi serviceCocok untuk service ownership kuat, tetapi operasional bisa tersebar.
Shared workflow serviceCamunda engine sebagai service terpisahCocok untuk platform orchestration yang dipakai quote/order.
Remote engine via RESTService domain memanggil Camunda RESTCocok jika ingin domain service tidak embed engine.

Untuk seri ini, baseline kita:

workflow-service owns Camunda 7 engine integration
quote-service/order-service own domain state
Camunda process instance references business key
external task/service task calls domain commands

Artinya, workflow-service bukan “God service”. Ia hanya memfasilitasi orchestration.


9. Why OpenAPI-first and Schema-first

CPQ/OMS adalah sistem lintas service, lintas tim, dan lintas channel. Kalau contract tidak eksplisit, integrasi menjadi rapuh.

OpenAPI-first berarti:

  1. API contract ditulis sebelum implementation detail.
  2. Endpoint, request, response, status code, error model, dan versioning didesain sebagai public contract.
  3. Code generation boleh digunakan, tetapi generated code harus punya boundary jelas.
  4. Breaking change harus terlihat di review.
  5. Contract test menjadi quality gate.

Schema-first berarti:

  1. payload event punya schema eksplisit,
  2. command payload punya schema eksplisit,
  3. validation rule di contract tidak tersembunyi di controller,
  4. schema evolution dipikirkan sebelum production,
  5. consumer bisa memvalidasi compatibility.

9.1 Contract Layers

Perhatikan boundary-nya:

  • API DTO bukan domain model.
  • JPA entity bukan domain model untuk semua kasus.
  • Event payload bukan internal entity dump.
  • OpenAPI contract bukan tempat semua business rule kompleks.

Contract-first bukan berarti contract menjadi domain. Contract adalah perjanjian integrasi.


PostgreSQL menjadi source of truth untuk aggregate penting:

  • catalog version,
  • product offering,
  • configuration rule metadata,
  • price rule metadata,
  • quote,
  • quote line,
  • quote revision,
  • order,
  • order line,
  • outbox,
  • audit,
  • workflow correlation metadata,
  • read model tertentu.

EclipseLink JPA kita gunakan untuk service yang cocok dengan relational aggregate mapping. Tetapi kita tidak akan memakai ORM secara naif.

ORM akan bermasalah jika:

  • aggregate terlalu besar,
  • lazy loading bocor ke resource layer,
  • entity dipakai sebagai API response,
  • transaction boundary tidak jelas,
  • cascade dipakai tanpa memahami ownership,
  • optimistic locking diabaikan,
  • query operasional dipaksa lewat object graph.

Prinsip kita:

JPA for transactional aggregate persistence.
SQL/read model for operational query.
Outbox for reliable event handoff.
Explicit DTO for API and event contract.

11. Why Kafka

Kafka dipakai untuk menyebarkan fakta bisnis setelah transaksi domain selesai. Contoh event:

  • QuoteCreated
  • QuoteConfigured
  • QuotePriced
  • QuoteApprovalRequested
  • QuoteApproved
  • QuoteAccepted
  • OrderCreated
  • OrderDecomposed
  • OrderFulfillmentStarted
  • OrderLineFulfilled
  • OrderCompleted
  • OrderFalloutRaised

Kafka bukan pengganti database transactional. Kafka juga bukan tempat melempar command sembarangan agar service lain “nanti tahu sendiri”.

Pemisahan yang akan kita gunakan:

TypeMaknaContoh
CommandPermintaan melakukan sesuatuSubmitQuoteForApprovalCommand
EventFakta yang sudah terjadiQuoteSubmittedForApproval
QueryPermintaan membaca stateGetQuoteById
NotificationPesan delivery ke manusia/sistemApprovalReminderEmailRequested

Dalam desain enterprise, membedakan command dan event bukan formalitas. Ini mencegah sistem menjadi tidak deterministik.


12. Why Redis

Redis dipakai untuk state yang boleh hilang atau bisa dibangun ulang, atau state ephemeral yang memang punya TTL.

Contoh penggunaan yang masuk akal:

  • catalog lookup cache,
  • price preview cache,
  • idempotency key dengan TTL,
  • distributed rate limit,
  • short-lived quote editing session marker,
  • expensive rule result cache,
  • temporary workflow correlation helper.

Contoh penggunaan yang berbahaya:

  • menyimpan accepted quote final hanya di Redis,
  • menjadikan Redis sebagai source of truth approval,
  • distributed lock untuk menutupi desain transaction yang buruk,
  • cache tanpa invalidation event,
  • TTL yang menghapus bukti audit.

Prinsipnya:

Redis mempercepat dan membantu koordinasi sementara. PostgreSQL tetap menjaga kebenaran utama.


13. Runtime Transaction Model

Kita perlu membedakan transaksi lokal, workflow transaction, dan event propagation.

Hal penting:

  • API response tidak harus menunggu semua downstream selesai.
  • Commit database terjadi sebelum event dipublish.
  • Event dipublish melalui outbox, bukan langsung dari memory setelah entityManager.persist().
  • Workflow dimulai berdasarkan event atau explicit command, tetapi harus tetap idempotent.
  • Quote service tetap source of truth status quote.

14. System of Record vs System of Engagement vs System of Automation

Dalam CPQ/OMS, kita harus membedakan tiga peran:

PeranContohFungsi
System of RecordPostgreSQL per domain serviceMenyimpan state otoritatif.
System of EngagementUI/BFF/APIInteraksi user dan partner.
System of AutomationCamunda 7, Kafka consumers, schedulersMenjalankan proses, reaksi, retry, escalation.

Masalah besar muncul ketika system of automation dianggap system of record. Contoh buruk:

Order dianggap completed karena BPMN token mencapai end event,
padahal order aggregate belum menyimpan semua fulfillment result.

Yang benar:

BPMN mencapai step completion → memanggil order command → order aggregate transition ke COMPLETED → event OrderCompleted dipublish.

Workflow engine boleh menggerakkan proses, tetapi domain aggregate yang memutuskan state bisnis final.


15. Canonical User Journeys

Kita akan memakai beberapa journey sebagai test bed sepanjang seri.

15.1 Happy Path Quote-to-Order

Sales creates quote
→ adds customer
→ selects product offering
→ configures product
→ validates configuration
→ prices quote
→ submits for approval
→ manager approves
→ sales sends quote document
→ customer accepts
→ order is created
→ order is decomposed
→ fulfillment succeeds
→ order is completed

15.2 Discount Exception

Sales applies manual discount above threshold
→ pricing detects policy impact
→ quote requires approval
→ approval BPMN starts
→ approver requests justification
→ sales adds justification
→ approver approves/rejects

15.3 Expired Quote

Quote priced on day 1
→ quote expires on day 15
→ customer attempts acceptance on day 20
→ system rejects acceptance
→ sales must reprice or create revision

15.4 Partial Fulfillment Fallout

Order contains 3 lines
→ line 1 fulfilled
→ line 2 pending external inventory
→ line 3 fails due to invalid downstream data
→ order enters PARTIAL_FALLOUT
→ case worker fixes mapping
→ workflow retries line 3
→ order continues

15.5 Duplicate Submit

User double-clicks Accept Quote
→ two requests arrive
→ idempotency key or aggregate guard prevents duplicate order
→ same result returned or conflict handled safely

These journeys are more valuable than abstract architecture diagrams. Architecture is correct only if it survives these journeys.


16. Domain Event Map

Awal event map:

Event map ini bukan sekadar dokumentasi. Ini akan menjadi dasar:

  • topic design,
  • outbox table,
  • consumer idempotency,
  • read model projection,
  • audit trail,
  • operational dashboard,
  • replay policy.

17. Data Ownership Map

DataOwner ServiceRead byUpdate by
Product OfferingCatalogConfig, Pricing, Quote, BFFCatalog only
Configuration RuleConfigurationQuote, BFFConfiguration only
Price RulePricingQuotePricing only
QuoteQuoteBFF, Workflow, Search, DocumentQuote only
Approval PolicyApproval PolicyQuote, WorkflowApproval Policy only
Process InstanceWorkflowAdmin, OpsWorkflow/Camunda only
OrderOrderBFF, Workflow, SearchOrder only
Audit RecordAuditAdmin, ComplianceAppend-only via Audit
Search ProjectionSearchBFF, AdminProjection consumers
Document ArtifactDocumentQuote, Order, BFFDocument only

Jika service lain perlu data, ia harus membaca lewat API, event projection, atau replicated read model. Ia tidak boleh diam-diam join tabel milik service lain.

Dalam implementasi lokal/monorepo, mungkin semua tabel berada di satu PostgreSQL instance untuk kemudahan development. Tetapi secara ownership, schema harus diperlakukan terpisah.


18. First Repository Shape

Struktur awal:

learn-enterprise-cpq-oms-camunda7/
  README.md
  docs/
    architecture/
      context-map.md
      adr/
      diagrams/
    api/
      openapi/
      schemas/
    process/
      bpmn/
      dmn/
  platform/
    docker-compose.yml
    postgres/
    kafka/
    redis/
    camunda7/
  services/
    catalog-service/
    configuration-service/
    pricing-service/
    quote-service/
    approval-policy-service/
    order-service/
    workflow-service/
    document-service/
    notification-service/
    audit-service/
    search-service/
    admin-service/
  libs/
    common-api/
    common-errors/
    common-observability/
    common-outbox/
    common-security/
  tests/
    contract-tests/
    integration-tests/
    e2e-scenarios/
    performance-tests/

Kita tidak mulai dari membuat semua service sekaligus. Kita mulai dari vertical slice:

catalog → configuration → pricing → quote → approval workflow → order

Service lain muncul ketika dibutuhkan oleh lifecycle.


19. Build Order

Urutan implementasi akan seperti ini:

StageFokusOutput
1Domain skeletonEntity, value object, command, state machine.
2Contract skeletonOpenAPI, schema, generated DTO boundary.
3Persistence skeletonPostgreSQL schema, EclipseLink mapping, migration.
4Quote vertical sliceCreate/configure/price quote.
5Approval workflowBPMN/DMN quote approval.
6Event outboxPublish quote events reliably.
7Order creationAccepted quote → order aggregate.
8Order orchestrationCamunda order fulfillment process.
9Fallout and recoveryIncident, retry, manual fix, compensation.
10Production readinessObservability, testing, ops, performance, security.

Ini sengaja bukan urutan “buat semua CRUD”. Kita membangun melalui skenario yang memaksa desain menjadi benar.


20. Architecture Fitness Functions

Architecture fitness function adalah cara menguji apakah arsitektur masih sehat.

Untuk seri ini, fitness function awal:

Fitness FunctionCara Menguji
API compatibilityContract diff tidak boleh breaking tanpa version bump.
Event compatibilitySchema evolution test harus lulus.
Quote immutabilityAccepted quote revision tidak berubah setelah catalog update.
Pricing traceabilitySetiap displayed price punya trace.
Idempotent order creationDuplicate acceptance tidak menciptakan order ganda.
Workflow-domain separationProcess completion tidak langsung dianggap domain completion.
Outbox reliabilityDB commit tanpa event publish bisa dipulihkan oleh publisher.
Consumer idempotencyReplay event tidak menggandakan side effect.
Audit completenessApproval/override/acceptance punya actor, timestamp, reason/context.
Operational recoveryFailed fulfillment bisa masuk fallout dan dilanjutkan.

Kalau fitur baru merusak salah satu fitness function ini, fitur itu belum production-grade.


21. Failure Classes

Enterprise platform harus mengklasifikasikan failure.

Failure ClassContohRespons Sistem
Validation failureProduct option tidak validReject command, return 400/domain error.
Business conflictQuote sudah accepted, masih dieditReject transition, return conflict.
Policy failureDiscount butuh approvalMove lifecycle ke approval required.
Transient technical failureInventory timeoutRetry with budget.
Persistent integration failureDownstream rejects payloadFallout/manual intervention.
Duplicate commandDouble submit orderIdempotent result / safe conflict.
Data corruptionMissing required historical snapshotBlock process, raise incident.
Workflow incidentJob failed repeatedlyIncident queue + recovery action.
Event poisonConsumer cannot parse/process eventDLQ + schema/data investigation.

Failure classification harus muncul di code, API error model, BPMN incident, logs, metrics, dan runbook.


22. The First Slice We Will Eventually Build

Minimal production-shaped slice:

Setiap step ini akan punya:

  • API contract,
  • command model,
  • domain validation,
  • persistence transaction,
  • outbox event,
  • audit trail,
  • idempotency consideration,
  • failure behavior.

23. Anti-Patterns yang Akan Kita Hindari

Anti-PatternKenapa BerbahayaAlternatif
Quote as cartTidak cukup untuk revision, approval, expiry, traceQuote as commercial proposal aggregate.
Order as copied quoteFulfillment lifecycle berbeda dari quote lifecycleOrder as fulfillment intent with commercial snapshot.
BPMN owns all stateSulit audit domain dan integrasiDomain aggregate owns state; BPMN orchestrates.
Entity exposed as APIContract bocor dan migration sulitDTO/API model explicit.
Event as entity dumpCoupling tinggi dan schema rapuhPurpose-built integration event.
Cache as truthData hilang/stale merusak bisnisPostgreSQL as truth, Redis as acceleration.
Direct DB access across serviceOwnership rusakAPI/event/read model.
Approval hardcoded in controllerPolicy tidak auditable dan sulit berubahApproval policy + DMN/process.
Retry everywhereSide effect gandaRetry budget + idempotency + failure class.
Search from OLTP aggregate tables onlyQuery lambat dan coupling UIProjection/read model.

24. Decision Log Awal

DecisionBaselineRationale
API styleREST with OpenAPI-firstCocok untuk internal/external integration contract.
REST implementationJAX-RS/JerseyExplicit resource/filter/mapper model.
PersistencePostgreSQL + EclipseLink JPARelational transactional core dengan ORM terkendali.
WorkflowCamunda 7Cocok untuk BPMN/DMN, human task, long-running process.
EventsKafka + outboxReliable asynchronous propagation.
CacheRedisEphemeral cache/idempotency/rate-limit helper.
Service decompositionDomain capability boundaryMenghindari table-driven microservices.
Source of truthPer-service PostgreSQL schemaOwnership jelas meski development pakai satu instance.
SearchProjection/read modelMenghindari query lintas aggregate yang mahal.
AuditDedicated append-oriented audit modelRegulatory defensibility.

Decision ini belum final selamanya. Tetapi setiap perubahan harus lewat alasan arsitektural, bukan preferensi tool.


25. What “Good” Looks Like

Part ini berhasil jika kamu bisa menjelaskan sistem tanpa menyebut framework lebih dulu.

Ciri pemahaman yang benar:

  • Kamu tahu beda catalog, configuration, pricing, quote, order, workflow, dan fulfillment.
  • Kamu tahu kenapa quote harus punya revision dan price trace.
  • Kamu tahu kenapa accepted quote harus immutable.
  • Kamu tahu kenapa order bukan sekadar copy quote.
  • Kamu tahu kenapa Camunda tidak boleh menjadi domain database.
  • Kamu tahu kenapa Kafka event harus keluar dari outbox.
  • Kamu tahu kenapa Redis tidak boleh menjadi source of truth.
  • Kamu tahu kenapa OpenAPI DTO tidak boleh langsung menjadi JPA entity.
  • Kamu tahu failure mana yang harus diretry, mana yang harus menjadi fallout, dan mana yang harus ditolak.

Kalau ini belum terasa natural, jangan lompat ke code dulu. CPQ/OMS enterprise gagal paling sering bukan karena kurang code, tetapi karena model awalnya salah.


26. Latihan Desain

Sebelum lanjut, jawab sendiri pertanyaan ini:

  1. Jika product catalog berubah setelah quote dikirim ke customer, apakah quote lama berubah?
  2. Jika discount rule berubah setelah quote approved, apakah approval lama masih valid?
  3. Jika customer klik accept dua kali, apa yang mencegah order ganda?
  4. Jika Camunda process instance selesai tetapi order aggregate gagal update, state mana yang dipercaya?
  5. Jika Kafka consumer memproses event yang sama dua kali, apa yang terjadi?
  6. Jika Redis kehilangan semua key, fitur mana yang boleh terganggu dan fitur mana yang tidak boleh rusak?
  7. Jika approver menyetujui quote revision 3, lalu sales membuat revision 4, approval itu masih berlaku?
  8. Jika order line 2 gagal fulfillment tetapi line 1 sukses, apakah order failed, partial, atau completed?
  9. Jika price calculation memakai data catalog version 10, apa yang harus disimpan di price trace?
  10. Jika auditor meminta alasan manual discount enam bulan kemudian, data apa yang harus tersedia?

Pertanyaan ini akan menjadi benang merah seri.


27. Summary

Kita sudah menetapkan peta awal:

  • sistem adalah platform CPQ/OMS enterprise-grade,
  • domain lifecycle lebih penting daripada framework,
  • service boundary mengikuti capability dan invariant,
  • PostgreSQL menjadi source of truth,
  • EclipseLink JPA dipakai secara terkendali,
  • OpenAPI/Schema-first menjaga contract,
  • Camunda 7 mengorkestrasi proses long-running,
  • Kafka menyebarkan fakta bisnis secara asynchronous,
  • Redis membantu cache/ephemeral coordination, bukan truth,
  • audit, idempotency, failure classification, dan recovery adalah bagian inti sejak awal.

Di part berikutnya kita masuk lebih dalam ke domain: CPQ/OMS Domain From First Principles. Kita akan membongkar apa sebenarnya product, configuration, price, quote, order, fulfillment, dan lifecycle—tanpa terjebak dalam istilah vendor atau template CRUD.


References

Lesson Recap

You just completed lesson 01 in start here. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.