Case Study / Core Banking Systems

Money moves.
The ledger remembers.

LeCore is a service-oriented retail banking platform designed around financial correctness, recoverable payment workflows, and operational control.

Spring BootASP.NET CoreAngularKafkaPostgreSQL
9backend services
2banking portals
0unbalanced journals accepted

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.

Correctness

Prevent double spend, reject unbalanced journal entries, and derive balances from durable accounting records.

Recovery

Handle ledger timeouts without charging a customer twice or losing a payment between services.

Control

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.

Customer and KYC

Search customer records, inspect identity and address information, review KYC status, and approve verification evidence from a dedicated queue.

Accounts and Funding

Open accounts, inspect account ownership and balances, then post controlled funding entries against the system clearing account.

Payments and Controls

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.

Retail AngularAdmin Angular
API Gateway
auth, routing, rate limits
Identity
sessions
Customer
profiles
Account
ownership
Payment
idempotency
Ledger
double entry
Audit
event trail
Reconciliation
ASP.NET Core
PostgreSQLKafkaRedisOpenTelemetry

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

Customer owns Account
Account initiates Payment
Payment references Journal Batch
Journal Batch contains Debit + Credit Entries
Events produce Audit + Reconciliation Cases

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

  1. 1Customer submits a transfer with an idempotency key.
  2. 2Payment service validates ownership and creates a PENDING payment plus outbox event.
  3. 3Ledger posts balanced debit/credit entries in one local transaction, updates balances, and records its outbox event.
  4. 4Kafka publishes payment and ledger envelopes at least once.
  5. 5Audit stores immutable evidence; reconciliation correlates paymentId with ledger referenceId.
  6. 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_ADMIN role.

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.

Local

devctl starts Kafka, Redis, observability, Spring services, the .NET reconciliation service, and both Angular portals. PostgreSQL remains local by default.

Kubernetes

Kustomize deploys services, ingress, probes, non-root containers, resource limits, NetworkPolicies, HPA/PDBs, and service-specific configuration.

Production path

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?

CapabilityValue added
KYC / AML rulesIntroduce identity verification, sanctions screening, transaction monitoring, and compliance case management.
Holds and reservationsProtect available balance during authorization flows before final ledger settlement.
NotificationsPublish customer and operations alerts for transfers, exceptions, and account changes.
Database migrationsReplace startup schema scripts with versioned, reviewable, rollback-aware database evolution.
mTLS and workload identityReplace the shared internal token with stronger service-to-service identity.
Reconciliation resolution workflowLet operations assign, annotate, resolve, and audit exception cases.