Final StretchOrdered learning track

Enterprise Integration Patterns

Learn Enterprise CPQ OMS Camunda 7 - Part 058

Enterprise integration patterns for a production-grade Java microservices CPQ and order management platform integrating with CRM, ERP, billing, inventory, document, notification, and external fulfillment systems.

19 min read3714 words
PrevNext
Lesson 5864 lesson track5464 Final Stretch
#java#microservices#cpq#oms+10 more

Enterprise Integration Patterns

A CPQ/OMS platform rarely lives alone.

It sits between systems that all believe they own part of the truth:

  • CRM owns customer relationship and opportunity context.
  • Product catalog owns sellable product definitions.
  • Pricing owns commercial calculation and policy.
  • Inventory owns availability and reservation facts.
  • Billing owns billing accounts, invoices, charges, taxation, payment status, and receivables.
  • ERP owns financial/back-office execution in many enterprises.
  • Contract systems own signed legal commitments.
  • Fulfillment systems own provisioning, shipping, activation, installation, or service delivery.
  • Notification/document systems own customer-facing communication artifacts.
  • Data warehouse owns analytics, not operational truth.

The integration problem is not “how do we call another API?”

The real problem is:

How do we exchange facts and requests between systems without corrupting ownership, lifecycle, auditability, consistency, or recoverability?

This part builds the integration model for an enterprise CPQ/OMS platform.

We will not repeat generic Kafka, REST, or database fundamentals. The focus is integration structure: boundaries, contracts, anti-corruption layers, sync/async decisions, idempotency, reconciliation, and failure handling.


1. The Integration Thesis

The thesis:

Every integration must declare authority, direction, contract, consistency expectation, failure semantics, idempotency rule, and reconciliation path.

If an integration does not declare those things, it is not production-grade.

Bad integration description:

Order service integrates with billing.

Good integration description:

Order service sends BillingActivationRequested after order line reaches BILLING_READY.
Billing system is authority for billing account, invoice, charge activation, and payment status.
OMS is authority for order lifecycle and billing handoff state.
The handoff is asynchronous via Kafka with outbox publication.
Each request has a business idempotency key: tenantId + orderId + orderLineId + billingHandoffAttemptNo.
Billing returns accepted/rejected/unknown through callback event.
OMS reconciles pending handoffs every 15 minutes.
Manual fallout is created after SLA breach or explicit rejection.

The second description can be built, tested, operated, audited, and repaired.


2. Integration Is Ownership Negotiation

Before choosing REST or Kafka, decide ownership.

Business ConceptLikely AuthorityCPQ/OMS Relationship
Customer masterCRM / Customer masterReference and snapshot selected customer facts
Sales opportunityCRMAssociate quote to opportunity, do not own opportunity lifecycle
Product offeringCatalogSnapshot catalog version into quote/order
Product configurationCPQ configuration serviceOwn selected configuration evidence
Price resultPricing serviceOwn price evidence for quote revision
QuoteQuote serviceOwn commercial proposal lifecycle
OrderOrder serviceOwn fulfillment obligation lifecycle
Inventory availabilityInventory serviceRequest/check/reserve, do not own inventory truth
Billing accountBilling/account systemValidate/reference, do not own billing account truth
InvoiceBilling systemObserve/reference, do not generate invoice truth unless explicitly in billing domain
Contract signatureContract/document systemRequest/sign/reference accepted artifact
Shipment/provisioningFulfillment systemOrchestrate/handoff/observe, do not fake completion
Audit evidenceCPQ/OMS audit serviceOwn CPQ/OMS decision evidence

A system may store snapshots of facts it does not own. But it must label them as snapshots.

Example:

quote.customer_snapshot_name
quote.customer_snapshot_segment
quote.customer_snapshot_taken_at
quote.customer_authority_ref

That is different from owning the customer.


3. Integration Context Map

The diagram hides the important question: which arrows are command, query, event, or callback?

You must mark each integration direction.


4. Integration Taxonomy

Use a small taxonomy.

TypeMeaningExample
QueryAsk another authority for current informationCheck billing account status
CommandAsk another system to perform an actionReserve inventory
EventPublish a fact that already happenedQuoteAccepted
CallbackAnother system reports result of a prior commandInventoryReservationConfirmed
SnapshotStore selected external facts at decision timeCustomer segment on quote
ProjectionDerived read model for UI/reportingOrder operations dashboard
ReconciliationLater compare local state with external authorityBilling handoff status check
Control plane syncPublish configuration/policy/catalog changesCatalog version activation

Do not blur these.

The common bug is treating an event as a command.

Bad:

Billing system consumes OrderCreated and automatically bills customer.

Better:

OMS emits OrderCreated as a fact.
OMS later emits BillingActivationRequested when domain state reaches billing-ready and required evidence exists.
Billing emits BillingActivationAccepted/Rejected.

5. Sync vs Async Decision Framework

Do not choose synchronous REST because it is easy. Do not choose Kafka because it is fashionable.

Choose based on business semantics.

QuestionSync Query/CommandAsync Event/Command
Does user need immediate answer?Often yesUsually no
Is operation long-running?Usually noYes
Can external system be temporarily unavailable?Maybe blocks userDecouple and recover
Does operation create side effect?Needs idempotency/timeout handlingNeeds outbox/inbox/reconciliation
Is stale answer acceptable?Maybe noOften yes with projection lag
Must result be incorporated in workflow?Can be sync gateOften async wait state

5.1 Synchronous Integration Is Fine When...

Use sync when:

  • answer is needed to continue current user action,
  • latency is bounded,
  • dependency is highly available,
  • operation is idempotent or read-only,
  • fallback semantics are clear,
  • timeout creates safe user-visible state.

Examples:

  • product eligibility check during quote configuration,
  • billing account validation during quote acceptance,
  • customer search in BFF,
  • retrieving document artifact metadata.

5.2 Asynchronous Integration Is Better When...

Use async when:

  • operation is long-running,
  • dependency availability should not block user flow,
  • external side effect may complete later,
  • retry/reconciliation is required,
  • workflow needs wait state,
  • high throughput is needed,
  • consumers are independent.

Examples:

  • order fulfillment,
  • inventory reservation confirmation,
  • billing activation,
  • document rendering,
  • notification sending,
  • data warehouse ingestion,
  • external provisioning.

6. Anti-Corruption Layer

An anti-corruption layer protects your domain from external models.

The ACL is responsible for:

  • translating external identifiers,
  • mapping status semantics,
  • validating response schema,
  • converting external error codes,
  • normalizing retryability,
  • preserving raw external reference for audit,
  • hiding vendor-specific fields from domain,
  • enforcing idempotency key conventions,
  • detecting impossible transitions.

6.1 Bad Domain Leakage

Bad:

if (sapStatus.equals("REL") || sapStatus.equals("TECO")) {
  orderLine.markFulfilled();
}

Better:

FulfillmentStatus status = fulfillmentGateway.getStatus(externalRef);
orderLine.applyFulfillmentObservation(status.toDomainObservation());

External status names should not spread across the domain.


7. Canonical Model vs Local Model

Many enterprises try to define one canonical model for all systems.

This can help at integration boundaries, but it becomes dangerous when treated as domain model.

Use this rule:

Canonical integration models are exchange contracts. Local domain models are decision models.

A canonical ProductOrder might describe order items, related parties, and state.

Your OMS local model still needs:

  • order lifecycle invariants,
  • fulfillment plan,
  • compensation state,
  • fallout state,
  • billing handoff status,
  • evidence hashes,
  • idempotency records,
  • state transition log.

Do not force local domain invariants into a generic canonical schema.


8. Integration Contract Shape

Every integration contract should document:

Name:
Purpose:
Owner:
Authority:
Direction:
Protocol:
Trigger:
Input schema:
Output schema:
Idempotency key:
Correlation id:
Tenant propagation:
Timeout:
Retry policy:
Error mapping:
State impact:
Audit evidence:
Replay behavior:
Reconciliation path:
Security control:
Operational dashboard:

Example:

Name: Inventory Reservation Request
Purpose: Reserve physical/service capacity for order line before fulfillment execution
Owner: OMS owns request; Inventory owns reservation truth
Direction: OMS -> Inventory
Protocol: Async command event + callback event
Trigger: Order line enters RESERVATION_REQUIRED
Input schema: InventoryReservationRequested.v1
Idempotency key: tenantId + orderId + orderLineId + reservationAttemptNo
Correlation id: orderLineFulfillmentStepId
Timeout: 15 minutes to first response
Retry: no blind duplicate command; query status before retry after timeout
State impact: pending -> confirmed/rejected/unknown/fallout
Audit: request payload hash, external reference, callback evidence
Replay: callback replay allowed; command replay forbidden without recovery mode
Reconciliation: scheduled reservation status query
Security: producer ACL, signed callback, tenant validation
Dashboard: pending count, age, rejection code, unknown count

This is the minimum useful level of precision.


9. CRM Integration

CRM integration usually covers:

  • customer lookup,
  • account/contact reference,
  • opportunity association,
  • sales stage update,
  • quote visibility back to CRM,
  • accepted quote/order notification.

9.1 Ownership Rule

CRM owns customer relationship context. CPQ owns quote commercial evidence.

CPQ may snapshot:

  • customer id,
  • customer name,
  • segment,
  • account owner,
  • credit classification indicator,
  • opportunity id,
  • legal entity reference.

But CPQ should not silently mutate CRM customer master.

9.2 Common Failure

CRM says customer segment is ENTERPRISE at quote creation. Later CRM changes segment to SMB.

Question: should existing quote approval change?

Answer: only if policy says so.

Design:

  • quote stores customer segment snapshot,
  • quote stores external customer reference,
  • quote may detect segment drift before acceptance,
  • policy decides whether drift invalidates price/approval,
  • drift creates revalidation requirement, not silent mutation.

9.3 Integration Pattern

CRM read at quote creation is usually synchronous because user needs immediate validation. Later CRM updates should not mutate quote truth without explicit revalidation.


10. Product Catalog Integration

Catalog integration is foundational.

10.1 Ownership Rule

Catalog owns sellable definitions. CPQ owns selected configuration evidence.

At quote time:

  • CPQ reads catalog version,
  • configuration engine validates selected offering/options,
  • quote stores catalog snapshot references and relevant denormalized facts,
  • price result references catalog version.

10.2 Catalog Versioning Pattern

catalog_version = 2026.07.01-enterprise-v3
product_offering_id = broadband-pro-1g
offering_version = 14
constraint_set_hash = sha256:...

Quote should be reproducible even if catalog changes tomorrow.

10.3 Catalog Publish Event

When catalog publishes a new version:

{
  "eventType": "CatalogVersionPublished",
  "tenantId": "tenant-1",
  "catalogVersion": "2026.07.01-enterprise-v3",
  "effectiveFrom": "2026-07-15T00:00:00Z",
  "publicationHash": "sha256:..."
}

Consumers may:

  • warm Redis cache,
  • rebuild eligibility projections,
  • mark draft quotes as needing revalidation if policy requires,
  • update BFF catalog read models.

Do not mutate accepted quotes just because catalog changed.


11. Pricing Integration

Pricing may be internal service or external pricing engine.

11.1 Ownership Rule

Pricing owns price calculation logic and price result. Quote owns commercial lifecycle using a price result snapshot.

11.2 Price Request Contract

Price request should include:

  • tenant,
  • quote id/revision,
  • customer snapshot reference,
  • catalog version,
  • configuration result,
  • quantity/term,
  • channel,
  • contract context,
  • requested overrides,
  • pricing policy version if fixed,
  • correlation id.

Price response should include:

  • price result id,
  • component list,
  • totals,
  • rounding details,
  • discount policy outcomes,
  • approval triggers,
  • calculation trace hash,
  • validity window,
  • deterministic input hash.

11.3 Price Freshness

A quote should not be accepted using a stale price result unless business explicitly allows it.

Freshness can be invalidated by:

  • quote line change,
  • quantity/term change,
  • customer segment change,
  • price book change,
  • promotion expiry,
  • manual override change,
  • catalog version change,
  • approval policy change.

12. Inventory and Availability Integration

This was covered as a domain part earlier. Here we focus on integration style.

12.1 Three Different Questions

Do not collapse these:

QuestionIntegration TypeMeaning
Is product likely available?QueryNon-binding quote-time check
Can we hold capacity?CommandReservation request
What is actual installed/available inventory?Query/eventInventory authority observation

12.2 Timeout Means Unknown

If reservation request times out, do not assume failure.

Unknown is a first-class state.

12.3 Idempotency Key

Reservation idempotency key:

tenantId + orderId + orderLineId + reservationPurpose + attemptNo

Do not use a random key generated per retry. That defeats idempotency.


13. Billing Integration

Billing is often where OMS boundaries get corrupted.

13.1 Ownership Rule

Billing owns:

  • billing account,
  • invoice,
  • charge activation,
  • taxation in billing context,
  • payment posting,
  • receivables,
  • billing cycle.

OMS owns:

  • order state,
  • billing handoff readiness,
  • evidence sent to billing,
  • handoff status from OMS perspective.

OMS should not fake invoice status or mutate billing account state.

13.2 Billing Handoff Pattern

13.3 Billing Contract Must Include Evidence

Billing request should include:

  • order id,
  • order line id,
  • customer/billing account reference,
  • product offering snapshot,
  • charge components,
  • effective date,
  • contract term,
  • tax context if relevant,
  • quote/order evidence hashes,
  • accepted document reference,
  • idempotency key.

Billing may reject if:

  • billing account invalid,
  • charge code unknown,
  • effective date invalid,
  • tax jurisdiction missing,
  • product mapping missing,
  • duplicate/inconsistent request.

Rejection is a business failure, not a technical exception.


14. ERP Integration

ERP integration often handles downstream financial/logistical processes.

Examples:

  • sales order creation,
  • purchase order request,
  • revenue recognition handoff,
  • stock movement,
  • shipment request,
  • project creation,
  • cost center validation.

14.1 ERP Is Usually Slow and Strict

ERP systems often have:

  • rigid master data requirements,
  • batch windows,
  • strict posting periods,
  • long response times,
  • complex error codes,
  • eventual status callbacks,
  • manual correction queues.

So ERP integration should normally be asynchronous with strong reconciliation.

14.2 ERP Adapter Pattern

The ERP adapter should translate:

OMS domain request -> ERP-specific API/file/message
ERP response/error -> normalized domain observation

Do not let ERP status codes pollute order state.

Bad:

order.status = SAP_DOC_CREATED_BUT_NOT_RELEASED

Good:

fulfillment_step.status = EXTERNAL_ACCEPTED
fulfillment_step.external_status_code = SAP_REL_PENDING
fulfillment_step.external_status_label = "Release pending"

Domain status remains stable. External details remain evidence.


15. Contract and Document Integration

Quote acceptance often depends on document generation and signature.

15.1 Ownership Rule

Document service owns artifact generation. Contract/signature service owns signature ceremony. Quote/order owns whether accepted evidence is sufficient to proceed.

15.2 Signed Artifact Pattern

QuoteRevision -> GenerateProposalDocument -> CustomerSigns -> SignatureCompleted -> QuoteAccepted -> OrderCreated

The signed artifact should capture:

  • quote id/revision,
  • artifact id,
  • artifact hash,
  • template version,
  • render input hash,
  • signer identity/reference,
  • signature timestamp,
  • signature provider reference,
  • acceptance terms.

Acceptance must validate that signed artifact corresponds to current quote revision and price/approval evidence.


16. Notification Integration

Notifications should not be emitted directly from random services.

16.1 Notification as Derived Side Effect

Domain emits fact:

QuoteApproved
OrderFulfillmentFailed
BillingActivationRejected

Notification service decides:

  • recipient,
  • channel,
  • template,
  • localization,
  • preference/consent,
  • retry,
  • suppression,
  • audit.

16.2 Notification Idempotency

Notification idempotency key:

tenantId + notificationPurpose + sourceEventId + recipientRef

This prevents duplicate email/SMS on event replay or consumer retry.


17. Data Warehouse and Analytics Integration

Analytics is not operational authority.

17.1 Good Pattern

Publish sanitized events/projections to analytics:

  • quote created,
  • quote priced,
  • quote approved,
  • quote accepted,
  • order created,
  • order fallout created,
  • fulfillment completed.

Include:

  • stable identifiers,
  • timestamps,
  • state transitions,
  • dimensions,
  • monetary aggregates where allowed,
  • policy version/evidence hash references.

17.2 Bad Pattern

Operational services query data warehouse to decide whether quote can be approved.

Why bad:

  • stale data,
  • non-authoritative transformations,
  • weak transaction semantics,
  • poor incident recovery,
  • analytics access controls differ from operational controls.

Use operational read models for operational decisions.


18. File-Based Integration

Some enterprise systems still integrate via files.

Do not dismiss file integration as unprofessional. It may be required. But make it explicit and controlled.

File integration contract must define:

  • file naming convention,
  • schema version,
  • delimiter/format,
  • encoding,
  • checksum,
  • encryption,
  • signing,
  • delivery location,
  • schedule,
  • retry,
  • duplicate detection,
  • partial failure handling,
  • acknowledgement file,
  • reconciliation report,
  • retention.

18.1 File Batch Pattern

Every row needs a business key and idempotency key.


19. Integration State Modeling

Never store only an external reference.

Store integration lifecycle.

Example external_handoff table:

create table external_handoff (
  tenant_id uuid not null,
  handoff_id uuid not null,
  aggregate_type text not null,
  aggregate_id uuid not null,
  purpose text not null,
  target_system text not null,
  status text not null,
  idempotency_key text not null,
  external_reference text,
  request_hash text not null,
  last_response_hash text,
  attempt_count integer not null,
  next_retry_at timestamptz,
  last_error_code text,
  last_error_message text,
  created_at timestamptz not null,
  updated_at timestamptz not null,
  primary key (tenant_id, handoff_id),
  unique (tenant_id, target_system, idempotency_key)
);

Possible states:

This lets operations see where integration is stuck.


20. Error Mapping

External errors must be normalized.

External ConditionNormalized TypeDomain Impact
Validation failureBUSINESS_REJECTEDMove to fallout/rework
Duplicate same requestIDEMPOTENT_SUCCESS or DUPLICATE_CONFLICTResolve by comparing payload hash
TimeoutUNKNOWNReconcile before retrying dangerous command
5xx/transientTECHNICAL_RETRYABLERetry with backoff
UnauthorizedSECURITY_CONFIGURATION_FAILUREStop and alert
Unknown codeUNCLASSIFIED_EXTERNAL_FAILUREFallout + mapping update

Never let raw external error codes directly drive domain state without classification.


21. Idempotency Across Integrations

Idempotency must be business-key based.

Bad:

idempotencyKey = UUID.randomUUID() on every retry

Good:

idempotencyKey = tenantId + orderId + orderLineId + targetSystem + purpose + attemptNo

For commands that should be exactly one per lifecycle step, do not increment attempt number on retry. Use the same key.

Use new attempt number only when business explicitly creates a new attempt after previous attempt is terminally failed/cancelled.

21.1 Payload Hash

Store request hash with idempotency key.

If same key + same hash appears: return previous result.

If same key + different hash appears: reject as idempotency conflict.


22. Correlation and Traceability

Every integration message should carry:

  • correlation id,
  • causation id,
  • event id/message id,
  • tenant id,
  • aggregate id,
  • source service,
  • source version,
  • schema version,
  • business process key,
  • external reference if known.

Example:

{
  "eventId": "01J...",
  "correlationId": "corr-123",
  "causationId": "cmd-456",
  "tenantId": "tenant-1",
  "aggregateType": "ORDER_LINE",
  "aggregateId": "line-123",
  "processBusinessKey": "order:ord-9",
  "source": "order-service",
  "schemaVersion": "billing-activation-requested.v1"
}

Without this, debugging cross-system failures becomes archaeology.


23. Reconciliation as First-Class Design

Every integration that can become unknown needs reconciliation.

Reconciliation asks:

What does the external authority believe happened?
What do we believe happened?
Where do the states diverge?
What safe action resolves divergence?

23.1 Reconciliation Job Pattern

Reconciliation must use domain commands, not direct DB updates.

23.2 Reconciliation Result Types

ResultMeaningAction
MatchedLocal and external agreemark checked
External successExternal completed but callback missedapply success observation
External failureExternal failed but local pendingapply failure observation
External unknownExternal also does not knowkeep unknown / retry / fallout
Local impossibleLocal state cannot accept external resultcreate fallout

24. Camunda 7 Integration Boundary

Camunda orchestrates long-running work. It should not become the integration authority.

24.1 Good Boundary

Camunda process:

  • decides next orchestration step,
  • creates wait states,
  • handles timers,
  • routes business errors,
  • creates human task/fallout path.

Domain service:

  • validates command,
  • owns state transition,
  • writes outbox,
  • records audit,
  • interprets external callback.

24.2 External Task Worker Pattern

The worker does not call external system directly unless the domain explicitly delegates that adapter role and still persists integration lifecycle.


25. Integration With Outbox and Inbox

Use outbox for publishing facts/commands after local DB commit.

Use inbox for consuming external messages idempotently.

Consumer must be idempotent because Kafka and external systems can redeliver.

Inbox record should store:

  • message id,
  • source system,
  • schema version,
  • aggregate id,
  • received at,
  • processing status,
  • payload hash,
  • error code,
  • retry count.

26. Integration Security

Every integration needs security controls.

IntegrationSecurity Control
Synchronous API callmTLS/OAuth/service identity, scoped credentials, timeout
Kafka eventACL, schema validation, producer identity, topic ownership
Callback/webhooksignature, timestamp, replay protection, allowlist where useful
File transferencryption, signing/checksum, secure transport, retention
Admin-triggered replayprivileged role, approval, audit, blast radius limit
External adaptersecret isolation, credential rotation, least privilege

Do not use one shared integration credential for all systems.


27. Integration Observability

Integration dashboards should show business state, not only technical status.

Metrics:

  • request count by target system,
  • accepted/rejected/unknown count,
  • pending age,
  • callback latency,
  • retry count,
  • DLQ count,
  • reconciliation corrections,
  • duplicate message count,
  • idempotency conflicts,
  • external error code distribution,
  • SLA breach count,
  • fallout cases by target system.

Logs should include:

  • correlation id,
  • tenant id,
  • aggregate id,
  • handoff id,
  • target system,
  • idempotency key hash,
  • external reference,
  • normalized error code.

Do not log full sensitive payloads.


28. Integration Testing Strategy

Integration tests should cover behavior, not just happy path connectivity.

TestPurpose
Contract testRequest/response/event schema compatibility
Adapter mapping testExternal status/error maps correctly
Idempotency testRetry does not duplicate external side effect
Timeout testTimeout becomes unknown, not failure
Callback duplicate testDuplicate callback is safe
Callback before local wait testEarly callback handled or parked
Reconciliation testMissing callback repaired
Rejection testBusiness rejection creates fallout/rework
Security testInvalid signature/token rejected
Replay testReplay does not resend real notification/billing command
Tenant testTenant mismatch rejected

Use simulators for external systems that can produce:

  • success,
  • business rejection,
  • timeout,
  • delayed callback,
  • duplicate callback,
  • out-of-order callback,
  • malformed response,
  • unauthorized response,
  • unknown status.

29. Integration Runbook Template

Every integration should have a runbook.

Integration name:
Business owner:
Technical owner:
Target system owner:
Data classification:
Protocol:
Normal flow:
Known external statuses:
Retry policy:
Timeout policy:
Reconciliation job:
Dashboard link:
Alert thresholds:
DLQ handling:
Manual recovery actions:
Security credentials:
Secret rotation process:
Common incidents:
Rollback/disable switch:
Escalation contacts:
Audit evidence location:

If there is no runbook, the integration is not production-ready.


30. Common Integration Anti-Patterns

Anti-Pattern 1: Distributed CRUD

Services directly update each other’s records.

Why it fails:

  • no ownership,
  • no audit,
  • no lifecycle semantics,
  • impossible recovery.

Use commands/events with explicit ownership.

Anti-Pattern 2: Shared Database Integration

Billing reads OMS tables directly. OMS reads CRM tables directly.

Why it fails:

  • schema coupling,
  • bypassed authorization,
  • impossible versioning,
  • lock/performance risk,
  • unclear audit.

Use APIs/events/projections.

Anti-Pattern 3: Event as RPC

Producer emits event and expects immediate consumer side effect to proceed.

Why it fails:

  • hidden synchronous dependency,
  • no explicit timeout,
  • unclear failure semantics,
  • hard to reconcile.

If you need a command, model a command.

Anti-Pattern 4: Callback Trust

External callback directly completes order step.

Why it fails:

  • spoofing risk,
  • duplicate callback risk,
  • stale callback risk,
  • impossible transition risk.

Callback should create a domain observation. Domain decides transition.

Anti-Pattern 5: No Unknown State

Timeouts become failure.

Why it fails:

  • external system may have succeeded,
  • retry may duplicate side effect,
  • cancellation may conflict with already completed work.

Use UNKNOWN and reconciliation.

Anti-Pattern 6: Data Warehouse as Operational Source

Using analytics tables to decide order workflow.

Why it fails:

  • stale transformations,
  • no command semantics,
  • no operational SLA,
  • weak audit chain.

Operational decisions need operational authority.


31. Practical Integration Blueprint

For each external integration, create these code modules:

order-service/
  src/main/java/.../integration/
    billing/
      BillingPort.java
      BillingCommandService.java
      BillingHandoffRepository.java
      BillingHandoffEntity.java
      BillingOutboxMapper.java
      BillingCallbackConsumer.java
      BillingReconciliationJob.java
      BillingErrorMapper.java
      BillingAuditRecorder.java
      BillingSecurityVerifier.java

The names matter less than the separation:

  • port defines domain-facing contract,
  • command service controls lifecycle,
  • repository stores handoff state,
  • mapper builds external contract,
  • consumer handles callback idempotently,
  • reconciliation repairs unknowns,
  • error mapper normalizes external failures,
  • audit recorder preserves evidence,
  • security verifier validates external authenticity.

32. Capstone Example: Order to Billing + Inventory

Each transition corresponds to a domain command and integration evidence.

StepAuthorityIntegration Pattern
Validate order evidenceOMSLocal domain validation
Reserve inventoryInventoryAsync command + callback + reconciliation
Billing activationBillingAsync command + callback + reconciliation
FulfillmentFulfillment systemAsync command/external task/callback
FalloutOMSHuman recovery workflow

This is what production-grade integration looks like: explicit ownership, explicit waiting, explicit unknown handling, explicit recovery.


33. Mental Model

Do not think of enterprise integration as plumbing.

Think of it as treaty-making between authorities.

Every integration treaty must answer:

Who owns this fact?
Who may request action?
What is the contract?
What does success mean?
What does rejection mean?
What does timeout mean?
What is safe to retry?
How do we detect duplicates?
How do we reconcile disagreement?
What is audited?
Who can operate recovery?

If those questions are answered, protocol choice becomes much easier.

If those questions are not answered, even the best Kafka topic or REST API becomes a distributed failure generator.


34. References

Lesson Recap

You just completed lesson 58 in final stretch. 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.