In modern personal finance, the biggest friction point is manual data entry.
If a user has to unlock their phone, open an app, select an account, type in an amount, and pick a category every single time they buy a cup of coffee, they will inevitably abandon the app within two weeks. Life gets busy, receipts get lost, and small cash outlays slip through the cracks.
In countries like India, financial institutions provide an ideal real-time data stream: transactional SMS alerts.
Every debit, credit, ATM withdrawal, and UPI payment immediately triggers an SMS notification from the bank containing the amount, the last four digits of the account, the merchant name, and the available balance.
Commercial expense apps capitalize on this convenience, but almost all of them do so by making a severe privacy compromise: they transmit raw SMS text messages to central cloud servers for remote natural language processing (NLP).
Here is how FinLedger architected a local, multi-tiered SMS parsing pipeline that recognizes transaction formats from more than 50 financial institutions entirely on the user's phone, without cloud telemetry.
The Cloud SMS Parser Anti-Pattern
To understand why on-device parsing matters, examine what a raw banking SMS message actually contains:
"Sent Rs. 1,450.00 from HDFC Bank A/C **4921 to ZOMATO on 24-OCT-26 via UPI Ref 429810291021. Avl Bal Rs 52,190.25. If not you, call 1800..."
flowchart TD
subgraph CloudVulnerability["The Remote Cloud Parser Privacy Leak"]
SMS["Raw Bank SMS"] --> AppClient["Commercial Finance App"]
AppClient -->|"Transmits Full Body + Device ID"| CloudAPI["Remote NLP API Server"]
CloudAPI --> Analysis["Cloud Extractors:
Extracts Amount, Merchant, Account Number, AND Bank Balance!"]
Analysis --> Profiler["Behavioral Ad Profiling & Big Data Brokerage"]
end
When an app uploads this raw string to a cloud server, it is not just sharing that you spent 1,450 rupees on food delivery. It is transmitting:
- The name of your financial institution (HDFC Bank).
- The last four digits of your private bank account (
4921). - Your total liquid bank balance at that exact minute (
52,190.25 rupees). - Unique payment reference identifiers (UTR numbers).
Even worse, commercial apps frequently request broad SMS permissions that expose two-factor authentication (2FA) one-time passwords (OTPs), personal conversations, and medical clinic appointments to remote cloud scrapers.
The FinLedger Local Pipeline Architecture
In FinLedger, raw SMS messages never touch a network socket. The parsing pipeline runs 100% on-device inside a specialized background processor:
flowchart TD
subgraph OnDevicePipeline["FinLedger On-Device SMS Pipeline"]
direction TB
Incoming["Incoming SMS Broadcast / Inbox Cursor"] --> Filter["1. Financial Sender Filter:
Match Bank Sender ID (e.g., AD-HDFCBK, VM-ICICIB)"]
Filter --> Cleanse["2. Spam & OTP Guard:
Instantly reject OTPs, balance queries, and marketing promos"]
Cleanse --> Extractor["3. Deterministic Field Extractor:
Regex Extraction for Amount, Currency, Account Suffix, UTR, Merchant"]
Extractor --> Registry["4. Bank Registry (50+ Banks):
Detect Institution, Card vs Bank, Transaction Type"]
Registry --> Matcher["5. Account Resolver:
Match Suffix Against User's Configured Local Accounts"]
Matcher --> Staging["6. Staging & Confirmation:
Insert as PENDING_CONFIRMATION (Never pollutes live balances)"]
end
Stage 1: The Bank Sender Registry (BankRegistry.kt)
In India, commercial bulk SMS headers follow Telecom Regulatory Authority of India (TRAI) alphanumeric prefix codes (such as AD-HDFCBK, VK-SBIINB, BZ-ICICIB).
- FinLedger maintains an offline bank registry mapping over 50 financial institutions, neo-banks, and digital payment providers (including SBI, HDFC, ICICI, Axis, Kotak, IndusInd, PNB, Standard Chartered, CRED, PhonePe, Paytm, and Google Pay).
- If an incoming SMS originates from a personal phone number or an unverified marketing sender, the pipeline ignores it immediately without parsing.
Stage 2: The Spam & OTP Hygiene Guard
Before running heavy regex extractors, the message passes through an ultra-fast string hygiene filter:
- Messages containing keywords like "OTP", "verification code", "one time password", "login", or "congratulations you won" are discarded in less than 50 microseconds.
- This ensures that sensitive authentication codes are never stored, logged, or parsed.
Stage 3: The Deterministic Field Extractor (DeterministicFieldExtractor.kt)
Financial alerts are written for human readability, resulting in dozens of syntactic variations:
- "debited by Rs. 500.00" vs "spent INR 500.00" vs "withdrawn Rs 500"
- Account suffixes formatted as "a/c **1234", "card ending 5678", or "A/c no. XX9012".
FinLedger's deterministic extractor uses calibrated regular expression pipelines that isolate:
- The numeric transaction amount and currency symbol.
- The transaction polarity: Debit (outflow) vs Credit (inflow).
- The account or card identifier (masked last 4 digits).
- The counter-party merchant name or VPA identifier.
- The unique transaction reference number (UTR or bank reference code) used for deduplication.
Stage 4: The Account Resolver (AccountResolver.kt)
Once fields are extracted, the candidate is compared against the user's locally created accounts:
- If the SMS references card suffix
4921, and the user has a credit card configured with those ending digits, the resolver routes the candidate to that card. - If multiple accounts match or no account matches, the resolver applies our strict "Never Guess" guard: the candidate is staged into
unresolved_sms_candidatesfor manual user assignment rather than corrupting an arbitrary account.
Performance: Zero Impact on Battery or Memory
Because the entire parsing pipeline is written in pure Kotlin using compiled java.util.regex.Pattern singletons:
- A single SMS parses in under 0.8 milliseconds on modern Android hardware.
- It consumes less than 150 KB of temporary heap memory, which is immediately reclaimed by the garbage collector.
- Background execution runs on
Dispatchers.IOvia an asynchronous BroadcastReceiver, ensuring zero battery drain and zero impact on foreground UI rendering.
Key Takeaway
Convenience and privacy are not mutually exclusive.
By building a robust, on-device regex extractor and bank registry, FinLedger delivers real-time automated transaction detection across 50+ financial institutions while ensuring that your private bank alerts never leave your device.
FinLedger is a privacy-first, offline-first personal finance application for Android that models bank accounts, credit cards, and cash without double-counting.
Explore FinLedger on Google Play: https://play.google.com/store/apps/details?id=com.devanshufinance.app

Top comments (0)