Étude de cas · Plateforme de référence
Double-Entry Ledger Platform
Un monolithe modulaire pensé production pour wallets et flux en partie double en fintech et paiements — postings équilibrés, commandes idempotentes, et une démo live sur la vraie API.
Pas un tableur de soldes. Stack Compose exécutable avec journaux append-only, outbox transactionnel, retraits maker/checker, et une UI showcase branchée sur les vrais endpoints.
Signaux
Append-only
Journal
Triggers Flyway bloquent UPDATE/DELETE sur journal_entries.
Idempotent
Commandes
Advisory locks scopés + clés d’idempotence dans les transactions de posting.
Outbox
→ Kafka
Events écrits avec le post, puis publiés par OutboxDispatcher.
Règle d’or du posting
Chaque mouvement d’argent est un ensemble de journal_entries équilibré. Retries et refs fournisseur en double dédupliquent via clés d’idempotence dans la transaction de posting. Les triggers DB rejettent UPDATE/DELETE sur le journal — les corrections sont de nouvelles écritures, jamais des edits silencieux.
Problème
Les produits wallet et paiement exigent des mouvements d’argent auditables sous retries, webhooks et pression ops. Soldes façon tableur et mises à jour destructives échouent en conformité. Sans idempotence, un timeout client ou un callback fournisseur en double crée un double post. Sans outbox, Kafka peut annoncer un état jamais commit.
Solution
Monolithe modulaire : domain, persistence, services applicatifs et adaptateur HTTP en modules Maven. Flux produit dans PaymentApplicationService — transfert P2P, paiement marchand (brut + commission plateforme), retrait (maker/checker optionnel), reversal, et settlement dépôt depuis webhooks fournisseur signés. UI démo live sur / qui exerce la vraie API.
Contraintes
- Postings équilibrés uniquement — verrouillage de comptes et gardes anti-passif négatif sur le chemin critique.
- Clés d’idempotence et refs fournisseur doivent dédupliquer dans la transaction de posting.
- Au-delà de ledger.withdrawal.approval-threshold-minor, les retraits renvoient 202 + id d’approbation pending.
- Faucet démo (/api/v1/demo/**) gated par DEMO_MODE_ENABLED — jamais en production.
- HMAC webhook (WEBHOOK_HMAC_SECRET) requis pour le settlement des dépôts fournisseur.
Flux d'architecture
- 01HTTP / Webhooks
- 02Services paiement
- 03Posting ledger
- 04Outbox / Kafka
- 05Réconciliation
Architecture
ledger-domain (types/modèles) → ledger-persistence (JPA, Flyway) → ledger-core (posting, paiements, wallet, outbox, réconciliation, vérif webhook) → ledger-platform (packaging Spring Boot, REST, security, OpenAPI). Compose : PostgreSQL 16, Redis 7, Kafka, Prometheus, Grafana. OTLP optionnel via Micrometer/OpenTelemetry.
Décisions
- 01
Monolithe modulaire, pas microservices
Frontières Maven claires sans la taxe ops des deployables découpés — extraction plus tard si besoin.
- 02
Journal append-only au niveau DB
Les triggers imposent l’immuabilité pour qu’un bug applicatif ne puisse pas réécrire l’historique en silence.
- 03
Transactional outbox
outbox_messages et le post commitent ensemble ; OutboxDispatcher publie vers Kafka.
- 04
Idempotence dans la transaction
Clés + advisory locks scopés pour qu’un retry ou une ref fournisseur en double ne double-poste pas.
- 05
Maker/checker sur gros retraits
Seuil en unités mineures ; COMPLIANCE / OPERATIONS / ADMIN approuvent ou rejettent.
- 06
UI démo sur la vraie API
Showcase statique bundlé avec login JWT, faucet, transferts, expand journal et call log — les reviewers voient du vrai HTTP, pas des mocks.
Compromis
Un monolithe modulaire est plus simple à faire tourner que des services découpés, mais la discipline des modules doit tenir. Append-only + locking déterministe achètent la correctness au prix d’une concurrence plus stricte sur les comptes chauds. Le mode démo accélère la revue et doit rester off hors sandboxes. Compose local inclut ZooKeeper pour Kafka — OK pour le lab, pas la topologie cible de prod.
Stack
Ce que la plateforme couvre déjà
- 01
Flux produit : P2P, paiement marchand avec split de frais, withdraw, reverse, settlement dépôt.
- 02
Ops : gel wallet/compte, balance d’essai, approvals pending, audit dans la couche service.
- 03
Intégrité : triggers d’immuabilité du journal, ordre de locks anti-deadlock, jobs de réconciliation + snapshots.
- 04
Observabilité : scrape Prometheus, dashboard Grafana provisionné, export OTLP optionnel.
- 05
Tests : mvn test sur tous les modules ; ITs Testcontainers quand Docker est dispo.
Vous cadrez un problème ledger ou wallet ?
Partagez invariants de posting, contraintes webhook et besoins ops — je cartographierai architecture, risques et une première tranche réaliste.
