Customer-month features from a card ledger.
This pipeline builds monthly customer features from a synthetic South African card ledger. It tracks spend mix, recurring debit orders and subscriptions, income stability, balance-stress flags, and a simple churn-risk label.
A local Spark job writes partitioned Parquet and the snapshot this page reads. The ledger is generated. It is not bank or client data.
Specimen, not client data.
Code available on request. Write to hello@cipherlabs.cc.
Latest feature month
Specimen, not client data. ZAR, 2025-03, 6 months in the run.
2 500
Customers
150 000
Transactions
9.3%
High churn-risk
Clear
Quality gates
Segment spend mix
Outgoing amount by customer segment and MCC group, latest feature month. Income credits are excluded.
Spend by segment and category
ZAR
| Segment | Category | Spend | Share |
|---|---|---|---|
| Affluent | Insurance | ZAR 279 130 | 12.8% |
| Affluent | Utilities | ZAR 271 192 | 12.4% |
| Affluent | Digital services | ZAR 236 444 | 10.8% |
| Affluent | Retail | ZAR 224 645 | 10.3% |
| Affluent | Groceries | ZAR 210 737 | 9.6% |
| Affluent | Fuel | ZAR 207 083 | 9.5% |
| Affluent | Recreation | ZAR 204 895 | 9.4% |
| Affluent | Transport | ZAR 193 740 | 8.9% |
| Affluent | Dining | ZAR 175 069 | 8.0% |
| Affluent | Health | ZAR 155 117 | 7.1% |
| Affluent | Telecoms | ZAR 29 388 | 1.3% |
| Established | Utilities | ZAR 838 984 | 12.8% |
| Established | Insurance | ZAR 828 909 | 12.7% |
| Established | Digital services | ZAR 697 033 | 10.7% |
| Established | Dining | ZAR 637 062 | 9.7% |
| Established | Health | ZAR 613 005 | 9.4% |
| Established | Retail | ZAR 596 465 | 9.1% |
| Established | Recreation | ZAR 595 701 | 9.1% |
| Established | Groceries | ZAR 555 594 | 8.5% |
| Established | Fuel | ZAR 553 551 | 8.5% |
| Established | Transport | ZAR 541 758 | 8.3% |
| Established | Telecoms | ZAR 88 269 | 1.4% |
| Everyday | Utilities | ZAR 1 669 442 | 12.7% |
| Everyday | Insurance | ZAR 1 646 048 | 12.5% |
| Everyday | Digital services | ZAR 1 315 362 | 10.0% |
| Everyday | Health | ZAR 1 239 278 | 9.4% |
| Everyday | Groceries | ZAR 1 238 986 | 9.4% |
| Everyday | Retail | ZAR 1 218 447 | 9.3% |
| Everyday | Transport | ZAR 1 210 101 | 9.2% |
| Everyday | Fuel | ZAR 1 177 637 | 8.9% |
| Everyday | Dining | ZAR 1 171 142 | 8.9% |
| Everyday | Recreation | ZAR 1 100 617 | 8.4% |
| Everyday | Telecoms | ZAR 179 387 | 1.4% |
Recurring payments
Same customer, merchant and type in two or more months, amount within 5 percent of the series median.
Detected series
ZAR
| Kind | Series | Median total |
|---|---|---|
| card purchase | 1 136 | ZAR 1 772 676 |
| debit order | 5 000 | ZAR 5 533 703 |
| subscription | 5 000 | ZAR 594 468 |
Churn-risk
Latest month only. High: missed salary, or overspend with a negative balance. Medium: unstable income or spend near income. The rest are low.
Customers by label
- low2 174 · 87.0%
- medium93 · 3.7%
- high233 · 9.3%
Pipeline run
Row counts after generate and feature build, then the checks that ran between those stages.
Row counts
| Table | Rows |
|---|---|
| customers | 2 500 |
| merchants | 360 |
| categories | 12 |
| transactions | 150 000 |
| customer month features | 15 000 |
Quality checks
| Stage | Check | Status | Detail |
|---|---|---|---|
| bronze | unique customer id | pass | 2500 distinct / 2500 rows |
| bronze | unique merchant id | pass | 360 distinct / 360 rows |
| bronze | unique transaction id | pass | 150000 distinct / 150000 rows |
| bronze | transaction keys present | pass | 0 transactions missing keys |
| bronze | currency zar | pass | 0 rows not in ZAR |
| bronze | salary credits positive | pass | 0 salary rows with non-positive signed amount |
| bronze | spend debits negative | pass | 0 spend rows with non-negative signed amount |
| bronze | transaction customer fk | pass | 0 transactions with unknown customer_id |
| bronze | transaction merchant fk | pass | 0 transactions with unknown merchant_id |
| gold | unique customer month | pass | 15000 distinct / 15000 rows |
| gold | feature keys present | pass | 0 feature rows missing keys |
| gold | churn label domain | pass | 0 rows with an unknown churn_risk label |
| gold | non negative money | pass | 0 rows with negative salary or spend |
If your numbers do not add up, a report is still built by hand, or your team has outgrown its tools, get in touch.
A few sentences on the situation are enough. We reply from the same address you see here.