Skip to content

5.3 Core data model

This page is the conceptual entity catalogue — what entities exist, how they relate, and the key fields each carries. For the concrete DDL with types, indexes, and constraints, see 5.9 Schema reference. For a single borrower’s data shape through every stage, see 5.11 Worked data example.

  • PostgreSQL — primary OLTP store; one logical schema per module.
  • Object storage (S3) — raw vendor responses, documents, evidence packages, V-CIP recordings, audit-log archives. Versioned + Object Lock for evidence.
  • Vault / KMS — clear-text PII (PAN, Aadhaar, mobile, email, bank account). Tokens in main DB.
  • Redis — cache (decision-engine policy, bureau-report TTL).
  • OpenSearch — log + free-text search indexes.
  • Event bus — Kafka / RabbitMQ for async coupling.
  • Warehouse — Snowflake / ClickHouse for analytics, fed by CDC.
Borrower ──┬── BusinessEntity ──┬── Promoter[]
│ └── BeneficialOwner (graph)
├── Lead ───── Channel / Partner / SubAgent
└── Application ──┬── ApplicationBankAccount[]
├── ExistingDebt[]
├── Consent[]
├── Document[]
├── KycRecord (via Promoter)
├── KybRecord (via BusinessEntity)
├── DataPull[] (bank, gst, bureau, tally, aa, mca)
├── DecisionRun[] (per policy version)
└── Sanction
├── IssuedDocument[] (KFS, agreement, DPN, PG)
├── EsignSession[]
├── EstampSession
├── Mandate
└── LoanAccount
├── LoanEvent[] (append-only)
├── ScheduleLine[]
├── Repayment[]
├── Charge[]
├── ClassificationSnapshot[] (daily)
├── Provision[]
├── LoanAllocation (if co-lent)
│ └── PartnerLender + DlgAgreement
├── CollectionCase[] (per delinquency episode)
├── Restructuring[]
├── Writeoff[]
└── GlPosting[] (accounting)
AuditEvent (cross-cutting; emitted by every state change; hash-chained)

Top-level identity of a customer.

  • type — individual / proprietorship / partnership / llp / pvt_ltd / pub_ltd / huf / trust / society.
  • display_name.
  • primary_mobile_token, primary_email_token, pan_token — all tokenised; clear text in vault.
  • kyc_status — pending / in_progress / verified / rejected.
  • risk_category — low / medium / high (drives KYC refresh cadence).
  • created_via_channel_id.

For non-individual borrowers.

  • borrower_id FK.
  • legal_name, trade_name.
  • gstin_token, udyam_no, cin_or_llpin, pan_token.
  • date_of_incorporation, date_of_commencement.
  • industry_nic_code, business_sub_category.
  • registered_address, principal_place_address, operational_locations[].
  • annual_turnover_self_declared, turnover_validated_from_gst.
  • num_employees, business_vintage_years, working_capital_cycle_days_estimated.

Natural persons controlling the entity.

  • business_entity_id FK.
  • name, dob, gender, nationality.
  • pan_token, aadhaar_ref_token, mobile_token, email_token.
  • role — director / partner / proprietor / authorised_signatory / karta / trustee.
  • shareholding_pct, din_or_pin.
  • permanent_address, current_address.
  • kyc_status, kyc_method.

Recursive graph for non-individual borrowers.

  • business_entity_id, parent_bo_id (nullable, for multi-tier).
  • bo_natural_person_promoter_id FK to ultimate natural person.
  • ownership_pct_direct, ownership_pct_effective.
  • verification_status.

Channel hierarchy for attribution.

  • channel.type — direct / dsa / ca / anchor / embedded / partner.
  • partner — concrete instance under channel.
  • sub_agent — individual under partner.

Top-of-funnel; converts to Application.

  • borrower_pan_token, mobile_token.
  • channel_id, partner_id, sub_agent_id, campaign_id.
  • utm_source, utm_medium, utm_campaign.
  • status, stage.

Central record of a loan request.

  • borrower_id, lead_id.
  • status — draft / submitted / under_review / approved / declined / withdrawn / disbursed.
  • loan_product_id, loan_amount_sought, tenure_sought, purpose_code.
  • channel_id, partner_id, sub_agent_id.
  • decision_engine_decision_id, sanction_id.
  • application_version.

Per-section JSON blob for save-and-resume.

  • application_id, section_name, data_json, last_saved_at.

Declared / bureau-derived debts.

  • application_id, lender, outstanding, emi, tenure, vintage_months.
  • declared_or_bureau — source.

Borrower bank accounts attached to application.

  • application_id, bank, ifsc, account_number_token.
  • is_collection, is_disbursement.
  • verified_via_penny_drop, penny_drop_at.

Every consent ever granted.

  • borrower_id, purpose, data_categories[].
  • granted_at, expires_at, revoked_at.
  • version_of_policy, ip, device_fingerprint.
  • vendor (e.g., AA name), vendor_consent_ref (consent handle).

Borrower-uploaded artefacts (separate from generated documents).

  • application_id or loan_id, type, vendor_or_borrower_source.
  • object_store_uri, hash.
  • uploaded_at, verified_at, verified_by.

Per natural person.

  • promoter_id.
  • method — vcip / aadhaar_offline / digilocker / in_person.
  • ovd_type, ovd_proof_id.
  • ckyc_kin, ckyc_uploaded_at, ckyc_status.
  • sanctions_screen_id.
  • verified_at, next_refresh_due_at.

Per business entity.

  • business_entity_id.
  • gstin_verification_id, udyam_verification_id, mca_verification_id.
  • bo_graph_root_id.
  • verified_at, next_refresh_due_at.

Per V-CIP attempt.

  • kyc_record_id, vendor.
  • started_at, completed_at, outcome.
  • recording_uri, geo_tag_lat, geo_tag_lon.

Per screen, per subject.

  • subject_type (person / entity), subject_id.
  • vendor, screened_at, hits[].
  • disposition, disposition_by, disposition_at.

One row per pull request.

  • borrower_id, data_type (bank / gst / mca / bureau / tally / aa / itr / udyam / invoice / marketplace).
  • vendor, consent_ref.
  • requested_at, completed_at, status.
  • raw_object_uri, parsed_object_uri.
  • borrower_id, account_ref, period_start, period_end.
  • parser_vendor, parser_version.
  • parsed_metrics_json — ABB, MAB, turnover, bounces, EMIs, etc.
  • transactions_object_uri — full transactions in object store.
  • business_entity_id, gstin, period_start, period_end.
  • pulled_at, vendor.
  • gstr1_metrics_json, gstr3b_metrics_json, gstr2a_metrics_json.
  • business_entity_id, uploaded_at, object_uri.
  • parsed_at, parsed_metrics_json — P&L, BS, ageing, inventory.
  • subject_type (person / entity), subject_id.
  • cic (cibil / experian / equifax / crif), report_type (consumer / commercial / msme).
  • pulled_at, score, parsed_object_uri, enquiry_id_at_cic.

invoice / mca_snapshot / marketplace_settlement

Section titled “invoice / mca_snapshot / marketplace_settlement”

As needed per product set.

Versioned credit policy.

  • product_id, partner_id (nullable for own-book), version.
  • effective_from, effective_to.
  • rules_object_uri — full rule set, immutable per version.
  • created_by, approved_by.

Per execution of the engine.

  • application_id, policy_id.
  • inputs_snapshot_uri, outputs_json, trace_uri.
  • decision (approve / decline / refer / defer), reason_codes[].
  • recommended_sanction_amount, recommended_tenure, recommended_rate, risk_grade.
  • started_at, completed_at.

Per deviation request.

  • decision_run_id, reason, requested_by, requested_at.
  • approved_by, approved_at, status.
  • decision_run_id, valid_until.
  • amount, tenure, rate, fees_json.
  • accepted_at, accepted_via.
  • application_id, offer_id, sanctioned_at, sanctioned_by.
  • amount, tenure, rate, conditions_json, valid_until.
  • name, type, language, product_id, partner_id.
  • version, body_uri.
  • loan_id or sanction_id, template_version_id.
  • generated_at, object_uri.
  • document_id, signer_promoter_id.
  • vendor, started_at, completed_at.
  • aadhaar_esign_txn_ref, audit_uri.
  • loan_id or application_id, type (nach / enach / upi_autopay).
  • vendor, npci_ref, status.
  • borrower_account_id, max_debit_amount, frequency, valid_from, valid_to.

Entities — disbursement and LMS (event-sourced)

Section titled “Entities — disbursement and LMS (event-sourced)”
  • loan_id (set after first draw), sanction_id.
  • created_at, approved_at, executed_at.
  • amount, to_account_token, to_ifsc, to_account_name.
  • purpose, co_lender_share_json (for co-lent).
  • utr, status.
  • borrower_id, sanction_id, product_id.
  • activated_at, closed_at.
  • current_outstanding, current_classification, current_dpd_days — derived from events.

The event-sourced core.

  • loan_id, event_type (activate / disburse / accrual / repayment / allocation / charge / bounce / classification_change / provision / restructure / writeoff / close).
  • event_at, posted_at.
  • event_payload_json.
  • idempotency_key UNIQUE.
  • loan_id, due_date, principal_due, interest_due, total_due.
  • paid_principal, paid_interest, paid_at.
  • loan_id, received_at, amount.
  • source (nach / enach / upi_autopay / bank_transfer / pg / qr / manual).
  • allocation_json — breakdown per waterfall.
  • reconciled_with — sponsor bank ref.
  • idempotency_key.
  • loan_id, type (processing / servicing / late / bounce / penal / foreclosure / renewal / other).
  • amount, levied_at, gst_invoice_id.

Daily.

  • loan_id, snapshot_date.
  • class (standard / sma_0 / sma_1 / sma_2 / npa / sub / doubt / loss).
  • dpd_days, principal_overdue, interest_overdue.

Daily.

  • loan_id, snapshot_date, class, provision_amount.
  • Per event with approvals + before/after snapshots.
  • loan_id, opened_at, closed_at.
  • current_bucket, assigned_to.
Section titled “collection_call, field_visit, ptp, settlement_offer, legal_notice”

Per event; full agent / recording / disposition fields.

  • Master of recovery agents with training, ID, status.
  • name, master_co_lending_agreement_ref.
  • escrow_account_id, mis_format_config, status.
  • partner_lender_id, version, rules_object_uri.
  • loan_id, partner_lender_id.
  • originator_share_pct, partner_share_pct.
  • originator_share_outstanding, partner_share_outstanding.
  • partner_lender_id, pool_definition.
  • dlg_amount, instrument, instrument_ref.
  • valid_from, valid_to, invocation_rules_json.
  • partner_lender_id, period, direction.
  • amount, breakdown_json, executed_at, bank_ref.
  • gl_account — code, name, type (asset / liability / equity / income / expense).
  • gl_posting — transaction_date, description, source_module, source_ref, entries_json.
  • loan_id, charge_id, borrower_id.
  • invoice_no, invoice_date, taxable_value, cgst, sgst, igst, hsn_code.

tds_deduction, settlement, vendor_invoice, dsa_payout

Section titled “tds_deduction, settlement, vendor_invoice, dsa_payout”

Per event.

product / role / permission / user / user_role

Section titled “product / role / permission / user / user_role”
  • Standard admin master tables.
  • name, enabled, rollout_pct, tenant_scope, metadata_json.

Every state change.

  • actor_user_id or actor_service_id, action, resource_type, resource_id.
  • before_state_json, after_state_json.
  • request_ip, request_user_agent, timestamp.
  • prev_hash, this_hash — hash-chain integrity.
  • All amounts: NUMERIC(18, 2) in rupees (never FLOAT).
  • All rates: NUMERIC(6, 4), e.g., 0.1950 for 19.50%.
  • All timestamps: TIMESTAMPTZ (timezone-aware).
  • All identifiers: BIGSERIAL primary key + business-meaningful natural keys where useful (GSTIN, PAN tokens).
  • All *_token columns: opaque tokens; clear text in vault.
  • All *_uri columns: full S3 URIs.
  • All JSON fields: validated via JSON Schema where shape stability matters.

For full DDL, see 5.9 Schema reference.

For a worked example of what these entities actually look like for one borrower, see 5.11 Worked data example.