Architecture overview
Matcher architecture overview
Bounded contexts
Matcher has seven modules. Each owns its data and exposes clean interfaces to the others.
- Configuration: What you’re reconciling (contexts, sources, field maps, rules)
- Discovery: External data source connections, schema detection, and extraction orchestration with the embedded Fetcher engine
- Ingestion: Getting data in (parsing, validation, normalization)
- Matching: The engine (rule execution, confidence scoring)
- Exception: Handling unmatched items (workflow, routing, resolution)
- Governance: Audit trails (immutable logs for compliance)
- Reporting: Visibility (reports, exports, dashboards)
Configuration
Defines what you’re reconciling and how. Handles:- Contexts (what’s being reconciled)
- Sources (where data comes from)
- Field maps (translating external fields)
- Rules (how to match)
ReconciliationContext: The reconciliation scopeReconciliationSource: Source configurationFieldMap: Field translation rulesMatchRule: Matching logic
Discovery
The Discovery bounded context manages external data source connectivity, schema detection, and extraction orchestration with Fetcher’s embedded engine. Matcher hosts that engine in-process; Fetcher is not a remote service. Responsibilities:- Manage external data source connections
- Detect and cache source schemas
- Run in-process extractions and hand results directly to Ingestion
- Track connection and extraction lifecycles
FetcherConnection: External source connection managed locally by the embedded engineExtractionRequest: Tracks an extraction lifecycle run by the embedded engine
See Discovery for how Discovery connects to external databases with the embedded Fetcher engine.
Ingestion
The Ingestion bounded context handles data intake and normalization. Responsibilities:- Parse uploaded files (CSV, JSON, XML)
- Validate incoming data against configured schemas
- Normalize external data into a canonical representation
- Detect and handle duplicate records
- Emit domain events when ingestion completes
IngestionJob: Tracks ingestion lifecycle and statusTransaction: Normalized canonical transaction record
ingestion.completed: Indicates data readiness for matching
Matching
The Matching bounded context contains the reconciliation engine. Responsibilities:- Load applicable rules for a reconciliation context
- Execute matching strategies (exact, tolerance, date-based)
- Calculate confidence scores
- Create match groups and allocate transactions
- Identify unmatched transactions
MatchRun: Execution of a matching jobMatchGroup: Group of reconciled transactionsMatchItem: Individual transaction allocation
match_group.confirmed: A match group has been finalizedmatch_group.unmatched: A previously confirmed match was revertedtransaction.pending_review: A non-automatic candidate needs review
Exception management
The Exception bounded context manages unresolved transactions. Responsibilities:- Classify exceptions by severity
- Route exceptions to internal teams or external systems
- Support manual overrides and adjustments
- Track resolution status and SLAs
- Integrate with external workflow tools
Exception: An unresolved transactionResolution: Outcome of exception handlingRoutingRule: Routing and escalation logic
- JIRA for issue tracking
- Webhooks for custom workflows
Governance
The Governance bounded context preserves reconciliation traceability. Responsibilities:- Record instrumented auditable mutation workflows in immutable audit logs
- Provide queryable audit history
- Support regulatory and compliance reporting
AuditLog: Append-only record of instrumented auditable mutation workflows
Reporting
The Reporting bounded context provides operational visibility. Responsibilities:- Generate reconciliation reports
- Expose dashboard metrics
- Export reconciliation data in multiple formats
Report: Reconciliation summaryDashboard: Aggregated operational metricsExportJob: Asynchronous export execution
Data flow
Reconciliation follows a deterministic pipeline across bounded contexts:
1
Configuration
Reconciliation contexts, sources, field mappings, and rules are defined through the API.
2
Discovery
Discovery connects to external sources, detects their schemas, and runs extractions in-process with the embedded Fetcher engine. Extracted results are handed directly to Ingestion.
3
Ingestion
Uploaded files and data extracted by Discovery are parsed, validated, normalized, and deduplicated. An
ingestion.completed event is emitted.4
Matching
Matching rules are applied to eligible transactions, producing match groups with confidence scores on an integer scale of 0 to 100. EXACT and TOLERANCE groups with a confidence of at least 90 out of 100 can auto-confirm; FUZZY and DATE_LAG groups always require manual review. Unmatched items become exceptions.
5
Exception handling
Exceptions are classified, routed, and resolved either manually or via external systems. Resolution updates are propagated back to Matcher.
6
Governance
Instrumented auditable mutation workflows across the pipeline are recorded in immutable audit logs.
7
Reporting
Users access reports and dashboards showing reconciliation status, match rates, and exception aging.
Infrastructure components
Matcher relies on the following infrastructure services:
Database architecture
- Tenant-specific pool resolution in configured multi-tenant deployments for data separation
- Strong consistency for matching and exception state
- Eventual consistency for reporting views
Multi-tenancy
Matcher enforces strict tenant isolation:- With
AUTH_PROVIDER=plugin-auth, tenant identity is extracted fromtenant_idortenantIdJWT claims workos, single-tenant, and authentication-disabled deployments use the configured default tenant- Tenant identifiers are never accepted via request parameters
- Database access is scoped through the active tenant’s connection pool
- All queries are automatically constrained to the active tenant
This model prevents cross-tenant data access and supports regulatory and audit requirements.
Design patterns
Hexagonal architecture
Each bounded context follows the ports-and-adapters pattern:Cqrs-light
Write and read paths are separated at the service level:*_commands.gofor state mutations*_queries.gofor read operations
Outbox pattern
Matcher uses per-event delivery policies. Outbox-backed events persist an outbox record and are dispatched asynchronously; other events can use direct delivery with an outbox fallback when the circuit is open.Next steps
Quick start
Explore the architecture through a guided example.
Security
Review authentication, authorization, and tenant isolation mechanisms.

