This diagram shows the complete microservice architecture of the CreditX platform, including all services, infrastructure components, and their interactions.
architecture-beta
group infra(cloud)[Infrastructure Layer]
group services(cloud)[Microservices Layer]
group data(database)[Data Layer]
service kafka(server)[Kafka Message Broker] in infra
service zipkin(server)[Zipkin Tracing] in infra
service oracle(database)[Oracle Database] in data
service mainServ(server)[creditMainServ 8080] in services
service holdServ(server)[creditHoldServ 8081] in services
service postingServ(server)[creditPostingServ 8082] in services
service promoServ(server)[creditPromoServ 8083] in services
mainServ:B --> T:oracle
holdServ:B --> T:oracle
postingServ:B --> T:oracle
promoServ:B --> T:oracle
mainServ:R --> L:kafka
holdServ:R --> L:kafka
postingServ:R --> L:kafka
promoServ:R --> L:kafka
mainServ:T --> B:zipkin
holdServ:T --> B:zipkin
postingServ:T --> B:zipkin
promoServ:T --> B:zipkin
mainServ:R --> L:holdServ
postingServ:L --> R:mainServ
promoServ:L --> R:mainServ
sequenceDiagram
participant Client
participant MainServ as creditMainServ<br/>(8080)
participant HoldServ as creditHoldServ<br/>(8081)
participant Kafka as Kafka<br/>(holds, transactions topics)
participant PostingServ as creditPostingServ<br/>(8082)
participant PromoServ as creditPromoServ<br/>(8083)
participant Oracle as Oracle DB<br/>(Separate Schemas)
Note over Client,Oracle: Transaction Creation Flow
Client->>MainServ: POST /api/transactions<br/>(Create Transaction)
MainServ->>Oracle: Save Transaction (PENDING)
MainServ->>HoldServ: POST /api/holds<br/>(Create Hold/Authorization)
HoldServ->>Oracle: Check fraud, blocklist, balance
HoldServ->>Oracle: Create Hold record
HoldServ-->>MainServ: Hold Response (AUTHORIZED/DECLINED)
MainServ->>Oracle: Update Transaction status
MainServ->>Kafka: Publish transaction.authorized event<br/>(transactions topic)
MainServ-->>Client: Transaction Response (AUTHORIZED/DECLINED)
Note over Kafka,PromoServ: Async Event Processing
Kafka->>PostingServ: transaction.authorized event
PostingServ->>Oracle: Save Posting record
PostingServ->>MainServ: POST /api/transactions/{id}/commit<br/>(Commit Transaction)
MainServ->>Oracle: Update Transaction (POSTED)
MainServ->>Kafka: Publish transaction.posted event<br/>(transactions topic)
Kafka->>HoldServ: transaction.authorized event
HoldServ->>Oracle: Mark Hold as VOIDED
HoldServ->>Kafka: Publish hold.voided event<br/>(holds topic)
Kafka->>PromoServ: transaction.posted event
PromoServ->>Oracle: Check eligible promotions
PromoServ->>Oracle: Calculate cashback
PromoServ->>MainServ: POST /api/transactions/cashback<br/>(Create Cashback Transaction)
MainServ->>Oracle: Create cashback transaction
PromoServ->>Oracle: Save promotion application
Note over HoldServ,Oracle: Hold Expiry (Scheduled)
HoldServ->>Oracle: Check expired holds (every 5 min)
HoldServ->>Oracle: Mark expired holds
HoldServ->>Kafka: Publish hold.expired events<br/>(holds topic)
Kafka->>MainServ: hold.expired event
MainServ->>Oracle: Update Transaction (EXPIRED)
Role: Transaction orchestration and workflow management
REST Endpoints:
POST /api/transactions- Create inbound transactionPOST /api/transactions/{id}/commit- Commit transaction (internal)POST /api/transactions/cashback- Create cashback transaction (internal)
Kafka Producers:
- Publishes to
transactionstopic:transaction.authorizedeventstransaction.postedeventstransaction.failedevents
Kafka Consumers:
- Listens to
holdstopic:hold.createdeventshold.expiredeventshold.voidedevents
HTTP Clients:
- Calls creditHoldServ to create holds
Database: Oracle schema MAIN (managed by Flyway flyway_schema_history_cms)
Role: Hold authorization, fraud detection, and blocklist enforcement
REST Endpoints:
POST /api/holds- Create hold/authorization (internal)
Kafka Producers:
- Publishes to
holdstopic:hold.createdeventshold.expiredeventshold.voidedevents
Kafka Consumers:
- Listens to
transactionstopic:transaction.authorizedeventstransaction.postedeventstransaction.failedevents
Scheduled Jobs:
- Hold expiry checker (runs every 5 minutes - 300,000ms)
- Publishes expired holds via outbox pattern
Database: Oracle schema HOLD (managed by Flyway flyway_schema_history_chs)
Role: Transaction settlement and posting
Kafka Consumers:
- Listens to
transactionstopic:transaction.authorizedevents
Kafka Producers:
- Publishes to
transactionstopic (via outbox pattern)
HTTP Clients:
- Calls creditMainServ to commit transactions
POST /api/transactions/{id}/commit
Database: Oracle schema POST (managed by Flyway flyway_schema_history_cps)
Role: Promotion evaluation and cashback calculation
Kafka Consumers:
- Listens to
transactionstopic:transaction.postedevents
Kafka Producers:
- Publishes to
promotionstopic (via outbox pattern)
HTTP Clients:
- Calls creditMainServ to create cashback transactions
POST /api/transactions/cashback
Database: Oracle schema PROMO (managed by Flyway flyway_schema_history_cprs)
-
Topics:
transactions- Transaction lifecycle eventsholds- Hold lifecycle eventspromotions- Promotion/cashback events
-
Pattern: Event-driven architecture with transactional outbox pattern
-
Replication: Single broker setup (replication factor 1)
- Service: FREEPDB1
- Schemas: Separate schema per microservice (MAIN, HOLD, POST, PROMO)
- Migration: Flyway for schema versioning
- Initialization: Custom init scripts in
/docker-entrypoint-initdb.d/
- Purpose: Distributed tracing across all microservices
- Integration: Spring Cloud Sleuth with 100% sampling
- Storage: In-memory (for development)
All services use an outbox table to ensure reliable event publishing:
- Events are saved to DB in same transaction as business logic
- Background scheduler polls outbox and publishes to Kafka
- Ensures at-least-once delivery guarantee
- Asynchronous: Services communicate via Kafka events
- Synchronous: REST calls only for request-response patterns (Hold creation, Commit, Cashback)
Each microservice has its own Oracle schema:
- Loose coupling and independent deployment
- Schema migrations managed independently via Flyway
Transaction flow implements choreography-based saga:
- MainServ orchestrates initial authorization
- PostingServ commits authorized transactions
- PromoServ applies promotions to posted transactions
- Compensating transactions for failures (hold.expired, transaction.failed)
- No service registry (Eureka/Consul)
- Direct service-to-service HTTP calls via environment variables
- Container networking via Docker Compose
- Client → MainServ: Create transaction
- MainServ → HoldServ: Create hold (HTTP)
- HoldServ → Kafka: Publish hold.created
- MainServ → Kafka: Publish transaction.authorized
- MainServ → Client: Return response
- Kafka → PostingServ: Consume transaction.authorized
- PostingServ → MainServ: Commit transaction (HTTP)
- MainServ → Kafka: Publish transaction.posted
- Kafka → HoldServ: Consume transaction.authorized
- HoldServ: Mark hold as voided
- HoldServ → Kafka: Publish hold.voided
- Kafka → PromoServ: Consume transaction.posted
- PromoServ: Calculate eligible cashback
- PromoServ → MainServ: Create cashback transaction (HTTP)
- MainServ: Process cashback as new transaction
- HoldServ Scheduler: Check expired holds
- HoldServ → Kafka: Publish hold.expired
- Kafka → MainServ: Consume hold.expired
- MainServ: Update transaction to EXPIRED
- Language: Java (Spring Boot)
- Framework: Spring Cloud Stream, Spring Data JPA, Spring Web
- Messaging: Apache Kafka (Confluent Platform)
- Database: Oracle Database 23c Free
- Schema Migration: Flyway
- Tracing: Zipkin + Spring Cloud Sleuth
- API Documentation: OpenAPI 3.0 (Springdoc)
- Build Tool: Maven
- Containerization: Docker + Docker Compose