Prevent double spend, reject unbalanced journal entries, and derive balances from durable accounting records.
01 / Overview
A bank-shaped system, built around the hard parts.
LeCore lets customers register, review accounts, and send transfers while operations staff open and fund accounts, investigate payment states, review immutable events, and reconcile payment outcomes against ledger postings.
It is a portfolio-grade platform, not a claim of regulated production readiness. The engineering goal was to make the invisible controls of a financial system explicit: balanced books, idempotent commands, trustworthy event history, and failure-aware operations.
02 / Problem Statement
“Transfer successful” is not a sufficient answer.
Handle ledger timeouts without charging a customer twice or losing a payment between services.
Give operations a searchable audit trail and an independent payment-to-ledger reconciliation view.
03 / Admin Operations Portal
The operational counterpart to retail banking.
The Angular admin portal gives authorized operations staff a separate, role-protected control desk. It is intentionally distinct from the customer experience: its purpose is to make support, risk review, and financial controls visible without exposing internal tooling to retail users.
Every privileged workflow passes through the same gateway controls and is recorded in the audit trail, creating evidence for customer support and operational review.
Search customer records, inspect identity and address information, review KYC status, and approve verification evidence from a dedicated queue.
Open accounts, inspect account ownership and balances, then post controlled funding entries against the system clearing account.
Search payment history, investigate transaction state, review reconciliation exceptions, and trace privileged actions through immutable audit events.
03 / Architecture Diagram
One public edge. Small, accountable services.
auth, routing, rate limits
sessions
profiles
ownership
idempotency
double entry
event trail
ASP.NET Core
Browsers reach only the gateway. Each service owns its responsibility while PostgreSQL schemas, Kafka events, and Kubernetes policies keep boundaries visible.
04 / Why Spring Boot + ASP.NET Core?
Polyglot by service boundary, not by novelty.
Spring Boot powers the transactional core: identity, customers, accounts, payments, ledger, audit, and the gateway. It fits the Java/Maven ecosystem and makes transaction, JDBC, Kafka, OpenAPI, and Actuator concerns consistent.
ASP.NET Core
Both runtimes share infrastructure contracts, not source code: Kafka envelopes, PostgreSQL, health endpoints, OpenTelemetry, Kubernetes, and internal authorization headers.
05 / Domain Model
A payment is an instruction and lifecycle record. A journal batch is the financial source of truth. Account balances are projections updated atomically with the journal posting.
06 / Microservices And Patterns
Boundaries chosen for change and control.
Microservices
Identity, customer, account, payment, ledger, audit, and reconciliation each have a bounded responsibility. The gateway remains a routing and policy edge, not a business-logic sink.
CQRS
Writes create durable domain records and outbox events. Read models such as account balance projections, audit events, and reconciliation cases are optimized for operational queries.
Saga Pattern
The payment workflow is a pragmatic choreography: create payment, request ledger posting, publish state events, then retry transient failures. It avoids distributed database transactions.
Idempotency
Payment idempotency keys return the original payment. Ledger reference IDs return the original journal batch. Kafka consumers store event IDs before applying state.
07 / Event Flow
- 1Customer submits a transfer with an idempotency key.
- 2Payment service validates ownership and creates a
PENDINGpayment plus outbox event. - 3Ledger posts balanced debit/credit entries in one local transaction, updates balances, and records its outbox event.
- 4Kafka publishes payment and ledger envelopes at least once.
- 5Audit stores immutable evidence; reconciliation correlates
paymentIdwith ledgerreferenceId. - 6Delayed counterparts remain pending through a grace period; the safety sweep raises an exception only when overdue.
08 / Security
Trust is explicit at every hop.
- Opaque sessions and bcrypt password hashes.
- Gateway-only browser access and Redis-backed authentication/payment rate limits.
- Downstream APIs require an internal token; trusted customer and role headers are set only by the gateway.
- Kubernetes default-deny ingress policies allow only documented paths.
- Admin audit and reconciliation views require the
OPS_ADMINrole.
09 / Observability And Performance
Trace the transfer.
Spring Boot Micrometer and ASP.NET OpenTelemetry instrumentation expose health, Prometheus metrics, and distributed traces. Prometheus, Grafana, Jaeger, and an OpenTelemetry Collector run locally for service visibility.
Key operational signals: outbox backlog, Kafka consumer health, rate-limit fallback, reconciliation exceptions, payment retry rate, and API latency.
Test the limits.
PostgreSQL Testcontainers integration tests cover balanced postings, idempotent payment creation, and audit deduplication. Reconciliation unit tests cover matching, mismatched values, failed payments, and out-of-order delivery.
Before production, execute realistic load tests against payment creation, ledger locking, Kafka lag, and retry storms; use the results to tune HPA thresholds, connection pools, and partition count.
10 / Deployment
Local confidence. Cluster-ready boundaries.
devctl starts Kafka, Redis, observability, Spring services, the .NET reconciliation service, and both Angular portals. PostgreSQL remains local by default.
Kustomize deploys services, ingress, probes, non-root containers, resource limits, NetworkPolicies, HPA/PDBs, and service-specific configuration.
Use managed PostgreSQL, Kafka, Redis, and secret management. Run the non-destructive production preflight before applying manifests.
11 / Lessons Learned
Financial correctness belongs in the domain model. Double-entry validation and idempotent references are not infrastructure details.
Events need enough facts for independent controls. Reconciliation required ledger events to carry debit and credit totals, not merely a journal ID.
Eventual consistency needs a clock. A grace period and safety sweep prevent short delivery delays from becoming false operational incidents.
Operational screens are product features. Audit and reconciliation queues make a distributed system supportable by humans.
12 / Next Capabilities
What would make LeCore stronger?
| Capability | Value added |
|---|---|
| KYC / AML rules | Introduce identity verification, sanctions screening, transaction monitoring, and compliance case management. |
| Holds and reservations | Protect available balance during authorization flows before final ledger settlement. |
| Notifications | Publish customer and operations alerts for transfers, exceptions, and account changes. |
| Database migrations | Replace startup schema scripts with versioned, reviewable, rollback-aware database evolution. |
| mTLS and workload identity | Replace the shared internal token with stronger service-to-service identity. |
| Reconciliation resolution workflow | Let operations assign, annotate, resolve, and audit exception cases. |