💳 Event-Driven Payments Platform Prototype
A high-throughput, resilient, Kotlin + Spring Boot system inspired by PSPs like Adyen and Stripe. Featuring outbox pattern, double-entry ledger, retries, observability, and Domain-Driven modular design.
A modular, event-driven, and resilient eCommerce backend prototype built with Kotlin + Spring Boot, demonstrating how to design a high-throughput payment and ledger system using Domain-Driven Design (DDD), Hexagonal Architecture, and exactly-once event flows.
- A single order may contain products from multiple sellers
- Each seller is paid independently (one
PaymentOrderper seller) - Payments flow through a PSP simulation with retries and exponential backoff (equal jitter)
- Successful PSP results trigger double-entry ledger postings with full audit trail
- All communication is decoupled via Kafka using transactional producers/consumers
- Observability (Prometheus + Grafana, ELK Stack) and fault tolerance (Outbox pattern, DLQ handling) are built in from day one
- Account balance aggregation is planned for near-term implementation
🧩 Completed main
payment-service,payment-consumers, andledgerflows.
🔨 Currently working on AccountBalanceConsumer and AccountBalanceCache - Aggregate balances from ledger entries with Redis caching (Issue #119)
🔜 Future modules:accounting-service,wallet-service,order,shipment
%%{init: {'theme':'default','flowchart':{'curve':'basis','nodeSpacing':70,'rankSpacing':80}}}%%
flowchart TB
subgraph Client["Client Apps"]
USER[User / Mobile App]
MERCHANT[Merchant Portal]
end
subgraph API["API Layer"]
REST[payment-service<br/>REST API<br/>Returns 202 Accepted]
end
subgraph PROCESSING["Async Processing"]
CONSUMERS[payment-consumers<br/>Kafka Workers<br/>6 specialized consumers]
PSP_CALL[PSP Calls<br/>Payment Gateway Integration]
end
subgraph MESSAGING["Event Bus"]
KAFKA[Kafka<br/>Event-Driven Architecture<br/>Transactional messaging]
end
subgraph DATA["Data Layer"]
DB[(PostgreSQL<br/>Payments, Orders<br/>Outbox, Ledger)]
REDIS[(Redis<br/>Retry Queue<br/>Cache)]
end
subgraph LEDGER["Ledger System"]
LEDGER_FLOW[Ledger Recording<br/>Double-Entry Accounting<br/>Balanced Debits/Credits]
end
subgraph OBS["Observability"]
PROM[Prometheus<br/>Metrics]
GRAFANA[Grafana<br/>Dashboards]
ELK[ELK Stack<br/>Logs + Traces]
end
USER -->|1. POST /payments| REST
MERCHANT -->|Query Balances| REST
REST -->|2. Save + Outbox| DB
REST -->|3. 202 Accepted| USER
DB -->|4. Outbox Polling| KAFKA
KAFKA -->|5. Payment Events| CONSUMERS
CONSUMERS -->|6. PSP Integration| PSP_CALL
PSP_CALL -.->|7. Response| CONSUMERS
CONSUMERS -->|8. Results| KAFKA
KAFKA -->|9. Finalized Events| LEDGER_FLOW
LEDGER_FLOW -->|10. Journal Entries| DB
CONSUMERS -->|Retry Scheduling| REDIS
REDIS -->|Retry Events| KAFKA
REST -.->|Metrics + Logs| PROM
CONSUMERS -.->|Metrics + Logs| PROM
PROM --> GRAFANA
REST -.->|Structured Logs| ELK
CONSUMERS -.->|Structured Logs| ELK
style API fill:#e3f2fd,stroke:#1976D2,stroke-width:3px
style PROCESSING fill:#fff9c4,stroke:#F57F17,stroke-width:3px
style LEDGER fill:#e8f5e9,stroke:#388E3C,stroke-width:3px
style DATA fill:#fef7e0,stroke:#FBBC05,stroke-width:3px
style MESSAGING fill:#f3e8fd,stroke:#A142F4,stroke-width:3px
For local setup and deployment on Minikube:
👉 docs/how-to-start.md
- Architecture Guide – System design overview
- Architecture Details – Deep implementation guide
- How to Start – Local setup and Minikube deployment
- Folder Structure – Module organization and naming conventions
ecommerce-platform-kotlin/
├── payment-domain/ # Core domain model, value objects, events
├── payment-application/ # Application services, schedulers, orchestrations
├── payment-infrastructure/ # Adapters (Kafka, Redis, DB, PSP) + auto-config
├── payment-service/ # REST API, Outbox Dispatcher
├── payment-consumers/ # Kafka consumers (Enqueuer, Executor, Ledger, Retry)
├── common/ # Shared contracts, event envelope, logging
├── common-test/ # Shared test utilities (test-jar for cross-module test helpers)
├── charts/ # Helm charts for deployment
├── infra/ # Local infra scripts (Minikube, monitoring, Keycloak)
└── docs/ # Architecture & how-to guides- Prometheus metrics for latency, retries, PSP call success rates, and consumer lag
- Grafana dashboards preconfigured in
infra/helm-values/ - ELK stack integration for JSON-structured logs, searchable by
traceId,eventId, orpaymentOrderId - Example Kibana query:
traceId:"abc123" AND eventMeta:"PaymentOrderPspCallRequested"
- Comprehensive Test Suite: Unit tests with MockK and integration tests with TestContainers
- Test Execution:
- Unit Tests:
mvn test(Maven Surefire,testphase - fast, runs on every build) - Integration Tests:
mvn verify(Maven Failsafe,integration-test+verifyphases - slower, runs before release) - Both:
mvn test && mvn verify
- Unit Tests:
- Test Organization: Lifecycle-based separation by filename pattern
- Unit tests:
*Test.kt(Surefire - fast feedback loop) - Integration tests:
*IntegrationTest.kt(Failsafe - comprehensive validation, all tagged with@Tag("integration"))
- Unit tests:
- Design Rationale: Surefire and Failsafe complement each other - unit tests provide fast CI/CD feedback, integration tests ensure comprehensive validation before releases
This project is a demonstration/learning prototype.
See LICENSE for details.
Built with ❤️ using Kotlin, Spring Boot, and Domain-Driven Design.