Skip to content

ADR-0002. TaxInfo is authoritative, sourced from Merchant CDC — not commerce metadata.tax

FieldValue
StatusAccepted
Date2026-04-08
Decidersinvoice-team, commerce-team
Supersedes

Context

  • Merchant tax identity (MST: taxCode, fullName, address, administrative codes) is entered in @nx/commerce as Merchant.metadata.tax.
  • The invoice service needs a normalized, queryable, relation-backed tax record (tax.TaxInfo) for issuance payloads and FE display.
  • metadata.tax is free-form jsonb on a foreign service — unsuitable as the authoritative record the invoice domain reads from.
  • Debezium's before-image is unreliable for change detection (depends on the table's REPLICA IDENTITY).

Decision

We will treat metadata.tax as input only and tax.TaxInfo (principalType=Merchant) as the authoritative record.

InvoiceWorkerService.handleMerchantCDC consumes the Merchant CDC topic; TaxInfoService.syncTaxInfo upserts TaxInfo. On op=u it diffs the incoming tax against the persisted TaxInfo (not the Debezium before-image) and skips when unchanged. The frontend reads the merchant.taxInfo relation, never metadata.tax.

Consequences

ProsCons
Single authoritative, relation-backed tax recordEventual consistency — depends on CDC lag
Change detection correct regardless of REPLICA IDENTITYExtra read (load persisted TaxInfo) per update
FE/issuance decoupled from commerce jsonb shapeTwo representations of "tax" exist (input + authoritative)
Idempotent re-delivery (unchanged → skip)Requires Debezium pipeline to be healthy

Alternatives Considered

OptionProsConsWhy rejected
Read metadata.tax directly at issuanceNo CDCCross-service jsonb coupling; no normalizationBrittle; FE can't relation-join
Trust Debezium before-image for diffsNo extra readUnreliable without FULL replica identityCauses false skips/updates
Sync HTTP call to commerce per issuanceAlways freshLatency + availability couplingDefeats event-driven design

References

  • src/services/invoice-worker.service.ts (handleMerchantCDC, _resyncMerchantTaxInfoIfChanged, _isTaxInfoUpToDate)
  • src/services/tax-info.service.ts (syncTaxInfo)
  • packages/core/src/models/schemas/tax/tax-info/schema.ts
  • See also: Integration §3.1

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.