A financial transaction processing and reconciliation engine built incrementally to explore financial correctness, distributed systems, reliability, and backend architecture.
LedgerFlow is an engineering simulation rather than a production payment processor. The project models the core problems found in financial transaction platforms while keeping the system testable, observable, and suitable for experimentation.
Client
|
v
Transaction API
|
v
Validation
|
v
Idempotency
|
v
Transaction State Machine
|
v
Transaction Processing
|
+--------------------+
| |
v v
Ledger Events
| |
| v
| Retry / Recovery
| |
v v
Reconciliation <--- Processing Results
|
v
Settlement
|
v
Audit Trail
|
v
Observability
Phases 1–5 — Transaction Processing Foundation, Persistent Ledger, State Machine, Events/Outbox, and Retry Recovery ✅
The first five phases are complete and merged. They establish the transaction API, validation, idempotency, balanced double-entry ledger creation, PostgreSQL persistence, explicit transaction state transitions, transactional outbox processing, retry scheduling, bounded backoff, and dead-letter recovery.
Phase 6 adds a durable reconciliation engine that compares completed internal transactions against an external settlement/input source.
Current reconciliation capabilities include:
- Deterministic matching by internal transaction identifier
- Matched transaction results
- Missing internal transaction detection
- Missing external transaction detection
- Amount mismatch detection
- Currency mismatch detection
- Duplicate external record detection
- Persisted reconciliation runs and results
- Idempotent reconciliation requests through
Idempotency-Key - Explicit discrepancy explanations
- Automated coverage for matched and mismatched scenarios
Current API surface includes transaction, reconciliation, settlement, fraud, audit, and health endpoints. The complete contract is maintained in docs/openapi.yaml.
POST /transactions
GET /transactions/{id}
POST /transactions/{id}/transitions
POST /transactions/{id}/retry
GET /transactions/{id}/recovery
GET /audit/transactions/{transactionId}
POST /reconciliation
GET /reconciliation/{id}
POST /settlements
GET /settlements/{id}
POST /settlements/{id}/process
POST /fraud/evaluate
GET /fraud/decisions/{transactionId}
GET /health
Example reconciliation request:
POST /reconciliation
Idempotency-Key: reconciliation-2026-09-17
Content-Type: application/json
{
"records": [
{
"externalTransactionId": "settlement-10001",
"transactionId": "00000000-0000-0000-0000-000000000000",
"amount": 100.50,
"currency": "USD"
}
]
}A reconciliation run produces explicit results such as Matched, MissingInternal, MissingExternal, AmountMismatch, CurrencyMismatch, and DuplicateExternal.
Start PostgreSQL:
docker compose up -d postgresRun the API:
dotnet run --project src/LedgerFlowThe application applies the PostgreSQL migration on startup.
Run the tests:
dotnet testThe test suite uses an isolated EF Core in-memory provider so API and domain tests do not require a running database.
The application exposes a health endpoint at GET /health.
OpenTelemetry is registered for ASP.NET Core traces and metrics, with custom LedgerFlow business instruments for transaction outcomes, processing duration, retries, dead letters, reconciliation results, settlements, and fraud decisions. Structured request logs include the correlation identifier.
No telemetry backend is required for local startup. To export telemetry to an OTLP-compatible collector, set OTEL_EXPORTER_OTLP_ENDPOINT before starting the application.
LedgerFlow/
├── src/
│ └── LedgerFlow/
│ ├── Application/
│ │ ├── TransactionService.cs
│ │ ├── RetryService.cs
│ │ └── ReconciliationService.cs
│ ├── Domain/
│ │ ├── DomainModels.cs
│ │ ├── RetryModels.cs
│ │ └── ReconciliationModels.cs
│ ├── Infrastructure/
│ │ ├── LedgerFlowDbContext.cs
│ │ └── TransactionRepository.cs
│ ├── Migrations/
│ │ ├── 202609061830_InitialPersistentLedger.cs
│ │ ├── 202609091000_AddTransactionStateTransitions.cs
│ │ ├── 202609101000_AddEventOutbox.cs
│ │ ├── 202609141000_AddRetryRecovery.cs
│ │ └── 202609171000_AddReconciliation.cs
│ ├── LedgerFlow.csproj
│ ├── Program.cs
│ └── appsettings.json
├── tests/
│ └── LedgerFlow.Tests/
│ ├── PersistentLedgerTests.cs
│ ├── EventDrivenProcessingTests.cs
│ ├── RetryRecoveryTests.cs
│ ├── ReconciliationTests.cs
│ ├── TransactionApiTests.cs
│ ├── TransactionDomainTests.cs
│ └── LedgerFlow.Tests.csproj
├── docker-compose.yml
└── README.md
The implementation is intentionally decomposed into domain, application, infrastructure, API, and test boundaries so later phases can build on stable financial primitives.
The following capabilities are planned as incremental work under the LedgerFlow epic.
- Introduce an external transaction/settlement input source
- Compare completed internal transaction records against external records
- Detect matched transactions
- Detect missing internal transactions
- Detect missing external transactions
- Detect amount mismatches
- Detect currency mismatches
- Detect duplicate records
- Persist reconciliation runs and results
- Make reconciliation requests idempotent
- Produce reconciliation results and discrepancy explanations
Implemented by Issue #19.
- Create settlement batches
- Define settlement lifecycle states
- Select eligible transactions for settlement
- Calculate settlement totals
- Simulate successful and failed settlement runs
- Make settlement operations idempotent
- Track settlement discrepancies
- Add configurable rule evaluation
- Add transaction threshold rules
- Add velocity checks
- Add account restrictions
- Record rule decisions
This phase is a simulation only and is not intended to represent production fraud detection.
- Record transaction creation
- Record state transitions
- Record ledger posting
- Record retries and failures
- Record reconciliation outcomes
- Record settlement actions
- Make audit records append-oriented and traceable
- Structured HTTP logging with correlation identifiers
- OpenTelemetry tracing for HTTP and key business operations
- OpenTelemetry metrics for transactions, processing duration, retries, dead letters, reconciliation results, settlements, and fraud decisions
- Request correlation IDs exposed through
X-Correlation-Id - Optional OTLP export through
OTEL_EXPORTER_OTLP_ENDPOINT - Transaction, retry, reconciliation, settlement, and fraud operations correlate with trace context
- Observability configuration remains backend-neutral
- Expand transaction, reconciliation, and settlement APIs
- Introduce consistent validation error responses
- Add an OpenAPI contract at
docs/openapi.yaml - Add settlement request/response examples to the API contract
- Add explicit settlement create, get, and process endpoints
- Keep local API execution and configuration unchanged
Create reproducible scenarios demonstrating the system's reliability characteristics:
- Duplicate transaction request
- Concurrent duplicate requests
- Duplicate event delivery
- Out-of-order event delivery
- Failed processing followed by retry
- Permanent failure routed to dead letter
- Missing event
- Duplicate external settlement record
- Ledger amount mismatch
- Partial settlement failure
- Successful recovery after transient infrastructure failure
Implemented by Issue #14 / PR #14.
The failure lab is covered by tests/LedgerFlow.Tests/FailureLabTests.cs. The scenarios use the existing transaction, outbox, retry, reconciliation, and settlement boundaries and assert observable invariants rather than relying on manual inspection. Concurrent duplicate requests are protected by a process-local idempotency gate plus the database unique constraint; the PostgreSQL path remains the correctness boundary across application instances.
For local PostgreSQL demonstrations, run docker compose up -d postgres, start the API, and exercise the examples in the Phase 12 issue/PR. Partial settlement is exposed through POST /settlements/{id}/process with failAfter to leave settled, failed, and pending items observable in the response.
LedgerFlow will treat financial correctness as a first-class concern.
Key invariants include:
- Every posted journal transaction must balance.
- Total debits must equal total credits.
- Amounts must be positive and valid.
- Source and destination accounts must be valid and distinct where required.
- A transaction must not create duplicate financial effects.
- Posted journal entries should be immutable.
- Financial operations that require atomicity must execute transactionally.
The project is intentionally designed to demonstrate realistic distributed-system trade-offs.
- Idempotency is preferred over assuming exactly-once processing.
- Consumers should tolerate at-least-once event delivery.
- External side effects should be idempotent.
- Database state and emitted events should be coordinated using an outbox pattern where appropriate.
- Failures should be observable and recoverable.
- Consistency requirements should be explicit rather than accidental.
Testing will evolve alongside the architecture.
Current coverage includes:
- Successful transaction creation
- Balanced debit/credit ledger creation
- Idempotency behavior
- Invalid amount validation
- Domain-level financial invariants
- Persistence of transactions and journal entries
- Reconciliation matching and discrepancy detection
- Reconciliation idempotency
Future coverage will include:
- Concurrent idempotency against PostgreSQL
- Duplicate events
- Out-of-order events
- Retry behavior
- Dead-letter behavior
- Settlement idempotency
- End-to-end recovery scenarios
- Failure-lab duplicate, retry, dead-letter, missing-event, reconciliation, and settlement scenarios
LedgerFlow does not aim to provide:
- Real payment-network integration
- Real banking settlement
- Production fraud detection
- Real customer financial data processing
- PCI compliance certification
- Production payment processing guarantees
- Real-money transfers
The complete roadmap is tracked in:
EPIC: LedgerFlow Transaction Processing & Reconciliation Platform
The implementation will continue through focused issues and pull requests rather than attempting to build the entire platform in a single change.
The end state is a coherent financial transaction processing simulation demonstrating:
Financial Correctness
+
Idempotency
+
Double-Entry Accounting
+
Distributed Processing
+
Failure Recovery
+
Reconciliation
+
Settlement
+
Auditability
+
Observability
The project is intended to provide a practical platform for exploring backend architecture, distributed systems, financial-domain modeling, consistency, reliability, and API design.