top of page

Digital Lending Journey for all loan types Retail/SME/Agri-rural/education/green loan

  • Writer: Anand Nerurkar
    Anand Nerurkar
  • Sep 30
  • 8 min read

Digital lending journey is not re-written for each loan type — we design a core reusable skeleton, and then enable/disable steps based on loanType + productConfig + rules.

Let’s define this properly:

🔹 Core Digital Lending Journey (Common to All)

  1. Loan Application Submission

    • Borrower submits application (UI → Loan Service).

    • Captures borrower info, loan type, product code.

    • Persisted in loan_application (Postgres) with correlationId + idempotencyKey.

    • Outbox → event LOAN_INITIATED.

  2. Consent & Document Upload

    • eConsent (data sharing, credit bureau access, AML checks).

    • Upload KYC docs, income proofs, collateral papers.

    • Events: CONSENT_GIVEN, DOC_UPLOADED.

  3. Parallel Verification Services

    • KYC Service: Aadhaar/PAN/Passport → KYC_REQUESTED, KYC_DONE/KYC_FAILED.

    • Credit Service: Bureau check, alternate scoring → CREDIT_REQUESTED, CREDIT_DONE/CREDIT_FAILED.

    • Fraud/AML/FinCrime Services: Blacklists, suspicious activity → REQUESTED, DONE/*_FAILED.

    • Collateral/Property Service (conditional): Valuation, legal, insurance.

    • RTO/Dealer APIs (conditional): Vehicle ownership for auto loans.

    • GST/Bank Statement Analytics (conditional): SME/MSME loans.

  4. Aggregation & Decisioning

    • Orchestrator waits for all required events (depends on loan type).

    • Runs Drools Excel-based decision table (business editable).

    • Emits: LOAN_APPROVED, LOAN_REJECTED, LOAN_MANUAL_REVIEW.

  5. Loan Agreement & e-Sign

    • eMandate for EMI deduction.

    • Digital signature of agreement.

  6. Disbursement

    • Core banking integration.

    • Events: DISBURSEMENT_INITIATED, DISBURSEMENT_DONE, DISBURSEMENT_PARTIAL (e.g. home loan staged disbursements).

  7. Post-Disbursement Monitoring

    • For BNPL/Consumer Durable: repayment tracking, zero-cost EMI.

    • For SME/Agri: seasonal repayment tracking.

    • For Corporate: milestone-based monitoring.

🔹 Variations by Loan Type (Additional Steps)

1. Retail / Consumer Loans

  • Personal Loan: skip collateral; instant disbursement possible after e-KYC + alternate scoring.

  • Auto Loan: add RTO check, dealer/insurance integration.

  • Home Loan: add property verification + valuation + legal.

  • BNPL: lightweight KYC, instant bureau/alternate scoring; minimal documents.

2. SME / MSME Loans

  • Working Capital / Term Loan: add GST analytics, cash flow analysis.

  • Invoice Discounting: add invoice upload + buyer confirmation.

  • Merchant Cash Advance: add POS/UPI transaction data integration.

3. Agri & Rural Loans

  • Crop Loan / KCC: add land records check + seasonal repayment config.

  • Equipment Financing: add dealer + subsidy scheme integration.

4. Corporate / Institutional Loans

  • Project Finance: add multi-party approval workflow; milestone-based disbursement.

  • Syndicated Loan: add multi-lender participation workflow.

  • Trade Finance / LC: add customs/trade APIs, bank guarantee checks.

5. Specialized / Emerging Products

  • Education Loan: add co-applicant consent, university admission verification.

  • Green Loans: add renewable project validation, subsidy check.

  • Microfinance: add group lending + community verification.

  • P2P Lending: add platform-level matching engine + lender consent.

🔹 How We Enable / Disable Steps

  • Product Config Table (product_config):

    • loan_type = HOME_RESALE → requires propertyVerification=true, legalOpinion=true.

    • loan_type = AUTO → requires rtoCheck=true, dealerIntegration=true.

    • loan_type = PERSONAL → requires collateral=false.

  • Rules Engine (Drools Excel):

    • Maps credit score, fraud, income/EMI ratio → APPROVED, REJECTED, REVIEW.

  • Event-driven choreography:

    • Each microservice listens to loan-status (LOAN_INITIATED).

    • Based on product_config, orchestrator waits for only those checks.

✅ So the digital lending journey is ONE skeleton, and loan type decides extra hops.For example:

  • Amit R → Personal Loan: skip property/legal. Approved in < 10 mins.

  • Rama → Auto Loan: after credit + KYC, also need RTO + insurance.

  • Shyam → Home Loan (Resale): adds property + legal + valuation.

  • Radha → Education Loan: adds co-applicant consent + university validation.


Perfect 👍 Let’s do this step-by-step.I’ll show the full text event sequence (UI → DB → Outbox → Kafka → Services → Decision) for each loan type.We’ll reuse the same skeleton, but highlight where steps differ.

🔹 1. Amit R – Personal Loan (Unsecured)

Flow:

  1. UI → Loan Service

    • Insert into loan_application (loanType=PERSONAL).

    • Insert into outbox_event → event_type=LOAN_INITIATED, status=PENDING.

  2. Poller → Kafka

    • Publishes LOAN_INITIATED to topic loan-status.

  3. Consumers

    • KYC Service → inserts KYC_REQUESTED → after Aadhaar → KYC_DONE.

    • Credit Service → CREDIT_REQUESTED → fetch bureau → CREDIT_DONE (score=750).

    • Fraud Service → FRAUD_CHECK_REQUESTED → ML → FRAUD_DONE.

    • AML Service → AML_REQUESTED → FATCA/OFAC → AML_DONE.

  4. Orchestrator

    • Waits for [KYC_DONE, CREDIT_DONE, FRAUD_DONE, AML_DONE].

    • Runs Drools → approves.

    • Inserts into outbox → LOAN_APPROVED.

    • Poller → publishes LOAN_APPROVED to loan-status.

  5. Disbursement Service

    • Consumes LOAN_APPROVED.

    • Calls CBS → disburses → DISBURSEMENT_DONE.

🔹 2. Rama – Auto Loan (Secured)

Flow:

  1. Loan Service: LOAN_INITIATED.

  2. Parallel Services

    • KYC → KYC_DONE.

    • Credit → CREDIT_DONE.

    • Fraud/AML → DONE.

    • RTO Service → RTO_CHECK_REQUESTED → RTO_VERIFIED.

    • Insurance Service → INSURANCE_CHECK_REQUESTED → INSURANCE_VERIFIED.

  3. Orchestrator

    • Waits for [KYC, Credit, Fraud, AML, RTO_VERIFIED, INSURANCE_VERIFIED].

    • Runs Drools (loan-to-value ratio, income/EMI).

    • Inserts → LOAN_APPROVED.

  4. Disbursement

    • Dealer account credited.

    • Event: DISBURSEMENT_DONE.

🔹 3. Shyam – Home Loan (Resale Property)

Flow:

  1. Loan Service: LOAN_INITIATED.

  2. Parallel Services

    • KYC, Credit, Fraud, AML → same.

    • Property Service → PROPERTY_VERIFICATION_REQUESTED → PROPERTY_VERIFIED.

    • Valuation Service → VALUATION_REQUESTED → VALUATION_DONE.

    • Legal Service → LEGAL_OPINION_REQUESTED → LEGAL_OPINION_DONE.

  3. Orchestrator

    • Waits for [KYC, Credit, Fraud, AML, PROPERTY_VERIFIED, VALUATION_DONE, LEGAL_OPINION_DONE].

    • Runs Drools (LTV ratio, legal status).

    • Inserts → LOAN_APPROVED.

  4. Disbursement

    • Staged disbursement: DISBURSEMENT_PARTIAL events.

🔹 4. Radha – Education Loan

Flow:

  1. Loan Service: LOAN_INITIATED.

  2. Parallel Services

    • KYC, Credit, Fraud, AML.

    • Co-Applicant Service → COAPPLICANT_CONSENT_REQUESTED → CONSENT_DONE.

    • University Validation Service → UNIVERSITY_CHECK_REQUESTED → UNIVERSITY_VERIFIED.

  3. Orchestrator

    • Waits for [KYC, Credit, Fraud, AML, COAPPLICANT_CONSENT, UNIVERSITY_VERIFIED].

    • Rule check (parent income, university rating).

    • Emits LOAN_APPROVED.

  4. Disbursement

    • Direct to university or staged per semester → multiple DISBURSEMENT_PARTIAL.

🔹 5. Ramesh – Consumer Durable / BNPL Loan

Flow:

  1. Loan Service: LOAN_INITIATED.

  2. Parallel Services

    • e-KYC → instant OTP-based → KYC_DONE.

    • Alternate credit scoring (mobile data, payments history) → CREDIT_DONE.

    • Fraud light check.

  3. Orchestrator

    • Only needs [KYC_DONE, CREDIT_DONE].

    • Approves instantly.

  4. Disbursement

    • Merchant settlement instantly.

    • Event: DISBURSEMENT_DONE.

Key Insight:

  • Same skeleton journey (Application → Verification → Decision → Disbursement).

  • Loan Type → decides which extra services must publish DONE events before Orchestrator approves.

  • Kafka Topics remain generic:

    • loan-status → loan events

    • kyc-status → kyc events

    • credit-status → credit events

    • etc.


Postgres table schemas (loan_application, outbox_event, consent, loan_document, loan_state) and show how each event updates these tables step by step for (say Amit R’s personal loan)? That would give you DB + event trace together.


Perfect 👍 Let’s take Amit R – Personal Loan and walk through the full DB + Outbox + Kafka trace.I’ll define the Postgres tables first, then show how rows evolve step by step as Amit’s journey progresses.

🗂️ Postgres Schema

1. Loan Application

CREATE TABLE loan_application (
    loan_id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    loan_type VARCHAR(50) NOT NULL,
    amount NUMERIC(15,2),
    status VARCHAR(50) NOT NULL,  -- e.g. INITIATED, APPROVED, REJECTED
    created_at TIMESTAMP DEFAULT now(),
    updated_at TIMESTAMP DEFAULT now()
);

2. Outbox Event

CREATE TABLE outbox_event (
    event_id UUID PRIMARY KEY,
    loan_id UUID,
    event_type VARCHAR(100) NOT NULL,  -- e.g. LOAN_INITIATED, KYC_DONE
    payload JSONB,
    status VARCHAR(20) DEFAULT 'PENDING', -- PENDING/PROCESSED
    created_at TIMESTAMP DEFAULT now()
);

3. Consent

CREATE TABLE consent (
    consent_id UUID PRIMARY KEY,
    loan_id UUID,
    service_name VARCHAR(50),   -- e.g. KYC, Credit, Fraud
    status VARCHAR(20),         -- REQUESTED, DONE, FAILED
    created_at TIMESTAMP DEFAULT now(),
    updated_at TIMESTAMP DEFAULT now()
);

4. Loan Document

CREATE TABLE loan_document (
    document_id UUID PRIMARY KEY,
    loan_id UUID,
    doc_type VARCHAR(50),    -- Aadhaar, PAN, BankStatement, etc.
    status VARCHAR(20),      -- UPLOADED, VERIFIED, REJECTED
    created_at TIMESTAMP DEFAULT now(),
    updated_at TIMESTAMP DEFAULT now()
);

5. Loan State (latest snapshot)

CREATE TABLE loan_state (
    loan_id UUID PRIMARY KEY,
    current_state VARCHAR(100),   -- e.g. KYC_DONE, FRAUD_DONE
    last_updated TIMESTAMP DEFAULT now()
);

🔹 Step-by-Step Journey – Amit R (Personal Loan)

Step 1: Loan Initiation

  • Insert loan

INSERT INTO loan_application (loan_id, customer_id, loan_type, amount, status)
VALUES ('L001', 'C001', 'PERSONAL', 500000, 'INITIATED');
  • Outbox entry

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E001', 'L001', 'LOAN_INITIATED', '{"amount":500000,"loanType":"PERSONAL"}');

📤 Poller picks → Kafka → Topic loan-status → Event: LOAN_INITIATED.

Step 2: KYC Service

  • Insert consent

INSERT INTO consent (consent_id, loan_id, service_name, status)
VALUES ('CN001', 'L001', 'KYC', 'REQUESTED');
  • After Aadhaar validation

UPDATE consent SET status='DONE' WHERE loan_id='L001' AND service_name='KYC';
  • Outbox event

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E002', 'L001', 'KYC_DONE', '{"aadhaar":"xxxx","pan":"xxxx"}');

📤 Kafka → Topic kyc-status → Event: KYC_DONE.

Step 3: Credit Service

INSERT INTO consent (consent_id, loan_id, service_name, status)
VALUES ('CN002', 'L001', 'CREDIT', 'REQUESTED');

UPDATE consent SET status='DONE' WHERE loan_id='L001' AND service_name='CREDIT';

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E003', 'L001', 'CREDIT_DONE', '{"score":750}');

📤 Kafka → Topic credit-status.

Step 4: Fraud Service

INSERT INTO consent (consent_id, loan_id, service_name, status)
VALUES ('CN003', 'L001', 'FRAUD', 'REQUESTED');

UPDATE consent SET status='DONE' WHERE loan_id='L001' AND service_name='FRAUD';

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E004', 'L001', 'FRAUD_DONE', '{"risk":"LOW"}');

📤 Kafka → Topic fraud-status.

Step 5: AML Service

INSERT INTO consent (consent_id, loan_id, service_name, status)
VALUES ('CN004', 'L001', 'AML', 'REQUESTED');

UPDATE consent SET status='DONE' WHERE loan_id='L001' AND service_name='AML';

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E005', 'L001', 'AML_DONE', '{"watchlist":"CLEAR"}');

📤 Kafka → Topic aml-status.

Step 6: Orchestrator → Loan Decision

  • Orchestrator waits until KYC, CREDIT, FRAUD, AML are DONE.

  • Then updates loan:

UPDATE loan_application SET status='APPROVED' WHERE loan_id='L001';
  • Insert event:

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E006', 'L001', 'LOAN_APPROVED', '{"approvedAmount":500000}');

📤 Kafka → Topic loan-status.

Step 7: Disbursement

  • CBS called, money transferred.

INSERT INTO outbox_event (event_id, loan_id, event_type, payload)
VALUES ('E007', 'L001', 'DISBURSEMENT_DONE', '{"txnId":"TXN123","amount":500000}');

📤 Kafka → Topic disbursement-status.

Trace Summary for Amit R

  1. Loan Application → LOAN_INITIATED

  2. KYC → KYC_DONE

  3. Credit → CREDIT_DONE

  4. Fraud → FRAUD_DONE

  5. AML → AML_DONE

  6. Orchestrator → LOAN_APPROVED

  7. Disbursement → DISBURSEMENT_DONE

Every step:

  • Row in consent/loan_application/loan_state.

  • Row in outbox_event.

  • Published to Kafka.


DB + Event Trace style walkthrough for the other journeys (Auto, Home, Education, BNPL) as well, or should I also give you a small runnable Spring Boot + Kafka POC codebase skeleton that implements this pattern?


Got it ✅Let’s do both for you in structured way:

🏦 1. Digital Lending Journey – Multiple Loan Types

We keep the same pattern (DB → Outbox → Poller → Kafka → Consumer → Next Step) for all loan types.Differences come from what extra checks/services are involved.

🔹 Personal Loan (Amit R – already shown in detail)

Steps: Loan Initiation → KYC → Credit → Fraud → AML → Decision → Disbursement.Events: LOAN_INITIATED, KYC_DONE, CREDIT_DONE, FRAUD_DONE, AML_DONE, LOAN_APPROVED, DISBURSEMENT_DONE.

🔹 Auto Loan / Two-Wheeler Loan

Extra services: RTO check, Insurance validation.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • CREDIT_DONE

  • RTO_VERIFIED

  • INSURANCE_VERIFIED

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 Home Loan

Extra services: Property Valuation, Legal Check.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • CREDIT_DONE

  • PROPERTY_VALUATION_DONE

  • LEGAL_OPINION_DONE

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 Consumer Durable Loan / BNPL

Lightweight – only basic checks.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • ALTERNATE_CREDIT_SCORE_DONE

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 SME Loan (Working Capital)

Extra services: GST Verification, Bank Statement Analysis.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • GST_VERIFIED

  • BANK_STATEMENT_ANALYZED

  • CREDIT_DONE

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 Agri Loan (Crop Loan)

Extra: Land Record Check, Subsidy Check.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • LAND_RECORD_VERIFIED

  • SUBSIDY_ELIGIBILITY_DONE

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 Education Loan

Extra: University Verification, Co-borrower KYC.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • CO_BORROWER_KYC_DONE

  • UNIVERSITY_VERIFIED

  • CREDIT_DONE

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 Green Loan

Extra: Project Verification (e.g. Solar, EV).Events:

  • LOAN_INITIATED

  • KYC_DONE

  • PROJECT_VERIFIED

  • CREDIT_DONE

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🔹 Corporate Loan (Project Finance)

Extra: Syndication, Collateral Valuation, Legal & Compliance.Events:

  • LOAN_INITIATED

  • KYC_DONE

  • COLLATERAL_VALUATION_DONE

  • LEGAL_COMPLIANCE_DONE

  • SYNDICATION_APPROVED

  • LOAN_APPROVED

  • DISBURSEMENT_DONE

🛠️ 2. Runnable Spring Boot + Kafka POC (Skeleton)

I’ll keep this light but production-style so you can extend.We’ll focus on Loan Orchestrator + Outbox + Poller + Event Publishing.

@Entity
@Table(name = "loan_application")
public class LoanApplication {
    @Id
    private UUID loanId;
    private String customerId;
    private String loanType;
    private BigDecimal amount;
    private String status; // INITIATED, APPROVED, REJECTED
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}
@Entity
@Table(name = "outbox_event")
public class OutboxEvent {
    @Id
    private UUID eventId;
    private UUID loanId;
    private String eventType; // e.g. LOAN_INITIATED, KYC_DONE
    private String payload;   // JSON
    private String status;    // PENDING, PROCESSED
    private LocalDateTime createdAt;
}
@Service
public class LoanService {
    private final LoanRepository loanRepo;
    private final OutboxRepository outboxRepo;

    public LoanService(LoanRepository loanRepo, OutboxRepository outboxRepo) {
        this.loanRepo = loanRepo;
        this.outboxRepo = outboxRepo;
    }

    @Transactional
    public void initiateLoan(String customerId, String loanType, BigDecimal amount) {
        UUID loanId = UUID.randomUUID();
        LoanApplication loan = new LoanApplication(loanId, customerId, loanType, amount, "INITIATED");
        loanRepo.save(loan);

        OutboxEvent event = new OutboxEvent(
            UUID.randomUUID(), loanId, "LOAN_INITIATED",
            "{\"amount\":" + amount + ",\"loanType\":\"" + loanType + "\"}",
            "PENDING"
        );
        outboxRepo.save(event);
    }
}
@Service
public class OutboxPoller {
    private final OutboxRepository outboxRepo;
    private final KafkaTemplate<String, String> kafkaTemplate;

    @Scheduled(fixedRate = 5000) // every 5s
    @Transactional
    public void publishEvents() {
        List<OutboxEvent> pendingEvents = outboxRepo.findByStatus("PENDING");
        for (OutboxEvent e : pendingEvents) {
            kafkaTemplate.send("loan-status", e.getEventType(), e.getPayload());
            e.setStatus("PROCESSED");
            outboxRepo.save(e);
        }
    }
}

application.yml

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/loandb
    username: loanuser
    password: loanpass
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

kafka:
  bootstrap-servers: localhost:9092

✅ With this skeleton:

  1. Start Postgres + Kafka (docker-compose).

  2. Call LoanService.initiateLoan() → Row inserted into loan_application + outbox_event.

  3. Poller picks PENDING → Publishes LOAN_INITIATED → Kafka.

  4. Other services (KYC, Credit, Fraud, etc.) follow same pattern with their own topics (kyc-status, credit-status, etc.).

 
 
 

Recent Posts

See All
Open Banking Vs Tradinal Banking

1. What is Open Banking? Open banking  is a system where banks allow secure sharing of financial data  with authorized third-party...

 
 
 
How To Validate Architecture

🧭 1️⃣ What Architecture Validation Means It’s the structured process of verifying that the proposed or implemented solution : Meets...

 
 
 

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
  • Facebook
  • Twitter
  • LinkedIn

©2024 by AeeroTech. Proudly created with Wix.com

bottom of page