1. What We Observed
Feature Eligibility (from codebase)
| Rule | Requirement |
|---|---|
| Fido Score | ≥ 500 |
| Loan state | ACTIVE (borrower is current, not in arrears) |
| Installments | Single installment only |
| Product | Not BNPL / Goods |
| Timing | Second half of loan term, up to 1 day before due date |
| Frequency | Max 1 postponement per client (lifetime) |
2. Aggregate DR: Postponed vs. Eligible Population
| Group | N | DR@DPD0 | DR@DPD7 | DR@DPD15 | DR@DPD30 |
|---|---|---|---|---|---|
| Postponed | 905 | 11.83% | 8.12% | 7.26% | 6.99% |
| Eligible, not postponed | 85,565 | 8.29% | 4.45% | 4.07% | 3.65% |
| Delta | +3.54pp | +3.67pp | +3.19pp | +3.34pp |
3. Bounding the True Impact
We can't observe the counterfactual (what postponers would have done without the option), but we can bound it using two extreme assumptions:
| Assumption | Benchmark | Postponed DR@DPD30 | Benchmark DR@DPD30 | Implication |
|---|---|---|---|---|
| Best case All postponers would have defaulted |
DPD0 missers (same LN/FS bucket) |
5–7% | 35–56% | Feature saves ~30pp of defaults |
| Worst case All postponers would have paid on time |
Full eligible population (same LN/FS bucket) |
5–7% | 3–4% | Feature adds ~3pp of defaults |
4. Segment-Level Detail
DR@DPD30 by LN and Fido Score bucket. Three benchmarks for each segment.
| Segment | Postponed N | Postponed DR | Eligible Pop DR | DPD0 Missers DR |
|---|---|---|---|---|
| LN21+ / FS 700+ | 350 | 5.3% | 2.6% | 37.4% |
| LN21+ / FS 600–699 | 160 | 4.6% | 3.9% | 34.7% |
| LN21+ / FS 500–599 | 86 | 7.1% | 5.9% | 37.2% |
| LN11–20 / FS 600–699 | 90 | 5.5% | 4.8% | 48.7% |
| LN11–20 / FS 500–599 | 142 | 14.0% | 5.9% | 55.6% |
| LN1–10 / FS 500–599 | 47 | 16.5% | 6.3% | 46.7% |
5. A/B Test Design
An experiment to measure the causal impact of postponement on default rate, repayment timing, and retention.
Hypothesis
Offering in-app loan postponement to eligible borrowers reduces net default rate (measured at DPD30) without materially increasing time-to-repayment for borrowers who would have paid on time.
Test & Control
Control (50%)
Postponement feature is hidden. Eligible borrowers see the standard loan page with no postponement option.
- No UI change
- No backend eligibility check surfaced
- Borrower experience identical to pre-launch
Treatment (50%)
Postponement feature is shown. Eligible borrowers see the postponement offer in the loan page (current behavior).
- Full postponement flow available
- All current eligibility rules apply
- No other changes
Randomization
| Parameter | Value | Rationale |
|---|---|---|
| Unit | Client ID | Ensures consistent experience across loans. Client-level avoids contamination if same person takes multiple loans. |
| Split | 50/50 | Maximizes statistical power. Given current adoption is ~1% of eligible loans, we need a large pool. |
| Stratification | LN bucket + Fido Score bucket | Ensures balanced segments — the observational data shows these are the strongest confounders. |
| Eligibility | All clients meeting current postponement criteria | Keep the same FS ≥ 500, single installment, ACTIVE state rules. |
Primary Metric
1 - SUM(REPAID_AMOUNT_DPD30) / SUM(DISBURSED_AMOUNT_DPD30)Measured on all loans disbursed during the test period that have reached DPD30 maturity. Compares treatment vs control at the population level (intent-to-treat).
Secondary Metrics
| Metric | Definition | Why It Matters |
|---|---|---|
| DR@DPD0 | Default rate at original due date | Measures on-time repayment. If treatment DR@DPD0 is higher, postponement may reduce urgency. |
| DR@DPD7, DPD15 | Default rate at 7 and 15 days past due | Repayment curve shape — are treatment borrowers catching up? |
| Time to repayment | Days from disbursement to full repayment | Even if DR is similar, postponement may delay cash collection. |
| Next-loan take rate | % who take another loan within 30d of repayment | Retention/engagement signal — does postponement improve loyalty? |
| Postponement adoption | % of treatment group who actually postpone | Feature usage rate. Expected ~1–2% based on current data. |
| Collection cost | Calls/SMS per loan in 0–30 DPD window | If postponement reduces delinquency, it should reduce outreach costs. |
Sample Size & Duration
| Parameter | Value | Notes |
|---|---|---|
| Baseline DR@DPD30 | 3.65% | From eligible population (Nov – Feb) |
| MDE (minimum detectable effect) | 1.0pp | Detect if treatment DR is ≥ 4.65% or ≤ 2.65% |
| Power | 80% | Standard |
| Significance | 5% (two-sided) | Standard |
| Required N per arm | ~7,000 loans reaching DPD30 | For proportions test on 3.65% base rate with 1pp MDE |
| Expected weekly eligible volume | ~5,000 loans/week | Based on ~85K eligible loans in ~17 weeks |
| DPD30 maturity lag | ~60–75 days from disbursement | Loan term (~30d) + 30 DPD observation |
| Enrollment period | 3 weeks | ~15K loans per arm |
| Total duration | ~13 weeks | 3 weeks enrollment + 10 weeks for last cohort to reach DPD30 |
Timeline
PostponementEligibilityService, stratified randomization, logging
Guardrails (stop the test if breached)
| Guardrail | Threshold | Action |
|---|---|---|
| Treatment DR@DPD7 vs control | > 3pp worse at week 6 | Stop test, revert to treatment-for-all |
| SRM (sample ratio mismatch) | Chi-square p < 0.01 | Investigate randomization bug |
| Control group complaints | Support tickets mentioning missing feature | Monitor; tolerable if < 5 tickets/week |
Implementation Notes
- Randomization point: Add a check in
PostponementEligibilityService.isEligible(). Before returningtrue, check if the client is in the treatment group. If not, returnfalse. This keeps all other eligibility logic intact. - Assignment persistence: Hash
client_id + experiment_saltto deterministically assign groups. No need for a lookup table — same client always gets the same group. - Logging: Log the assignment (
postponement_ab_group: control/treatment) on every eligibility check, even for control. This lets us measure intent-to-treat. - Stratification: Pre-stratify by LN bucket (1–10, 11–20, 21+) and FS bucket (500–599, 600–699, 700+). Hash-based assignment naturally balances if volume is sufficient, but verify with a balance check at week 1.
6. Decision Framework
How to interpret results and what to do with them.
| Outcome | Treatment DR vs Control | Action |
|---|---|---|
| Clear win | Treatment DR significantly lower | Roll out to 100%. Postponement prevents defaults. Consider relaxing the 1-per-lifetime cap. |
| Neutral | No significant difference | Keep the feature — it's not hurting credit and likely improves retention/engagement. Measure next-loan take rate as the tiebreaker. |
| Mild negative | Treatment DR 1–2pp higher | Segment analysis: keep for LN21+ (low risk, high value), tighten for lower-tenure segments. |
| Clear negative | Treatment DR >2pp higher | Disable feature or restrict to FS ≥ 650 / LN ≥ 20. Redesign the UX to reduce moral hazard. |
7. Methodology
Data source: GHANA_PROD.ML.LOAN_INFO_TBL — installment-level FDR columns.
Population: Disbursed single-installment loans, Fido Score > 500, Nov 1 2025 – Feb 23 2026.
Postponed group: LOAN_POSTPONEMENT_DATE IS NOT NULL (N=905). DR measured from the new (extended) due date.
DPD0 missers: Non-postponed loans where REPAID_AMOUNT_DPD0 < 95% of DISBURSED_AMOUNT_DPD0.
Eligibility rules: Verified from PostponementEligibilityService.java in the fido-loan codebase.
Key limitation: All observational comparisons suffer from selection bias. The A/B test is the only way to establish causation.