🛠 Build · Project 1
🔨 Recon — The Reconciliation Engine
Your headline portfolio project — the one you can defend cold, because it’s your acceptance-testing world in code.
Java 21 · Spring Boot · PostgreSQL · GitHub repo: add when it exists
The business problem
Every payments company answers one question at 7am: does the bank’s record match ours, to the paisa? A reconciliation engine ingests two transaction feeds — a messy bank CSV and your clean ledger — and finds every discrepancy before it becomes a customer complaint or an audit finding.
Why it lands jobs
“I built a reconciliation engine” makes a fintech recruiter lean forward — the unglamorous core of payments, not another CRUD app.
Reconciliation = comparing two sources of truth = exactly acceptance testing. You’ve lived it.
“Matched 100k×100k in M seconds with an O(n) hashmap” — a measured metric beats vague claims.
Hashmap matching, Big-O, SQL, idempotency — every concept used for real.
Requirements — the 5 buckets
| Bucket | Meaning |
|---|---|
| matched | Same reference and amount in both feeds ✅ |
| missing in bank | Ledger has it, bank doesn’t (recorded but not settled) |
| missing in ledger | Bank has it, ledger doesn’t (money received, not recorded) |
| duplicate | Same reference appears twice on one side |
| amount mismatch | Same reference, amounts differ — even by 1 paisa |
Architecture — the pipeline
Concept dependencies
What this build uses from Knowledge. A ✓ means you’ve already learned it — the rest are what to shore up.
⚠️ Design it yourself FIRST (on paper, before any code)
This is the part AI can’t do for you — and exactly what interviews test. Answer in writing:
1. What is your match key when a bank row’s reference is blank or malformed — drop it, bucket it, or fuzzy-match?
2. One pass or two? Load both feeds, or stream one against a map of the other — and which feed becomes the map?
3. The same reference can appear twice in the bank file, twice in the ledger, or once in each. One case or three?
4. What exactly makes a re-run idempotent — what do you key a “run” on so the same files produce no new state?
5. Can you hold 1,000,000 rows in a HashMap? Roughly how much memory, and what’s your plan if one feed is too big?
6. A 1-paisa mismatch on a matched reference — a “miss” or a “match with a warning”? State your product decision.
Roadmap — 6 milestones
Tick each as you finish it. Your current milestone is highlighted, and this drives your Dashboard.
Testing
Unit-test the normalizer on the ugly inputs first (blank refs, “1,250.00”, trailing spaces, DD/MM vs MM/DD). Then a fixture pair of small CSVs whose expected buckets you know by hand — that becomes your regression net for every refactor.
Performance
Measure the 100k×100k match with System.nanoTime around the matching pass, warm the JVM first, and record the number — that’s the metric on your resume. Prove the O(n) claim by also timing a naive nested-loop version on 10k rows and watching it explode.
Deployment
Package as a runnable jar with a one-command README (input dir → output CSV). A Dockerfile is a nice bonus; a stranger being able to run it in 2 minutes is the real bar.
Interview questions it earns you
- Why a HashMap here instead of two nested loops — what’s the complexity difference and the memory cost?
- A feed has 1,000,000 rows and won’t fit comfortably in memory. How does your design change?
- What makes your batch idempotent, and why do finance teams care?
- The same reference appears twice on the bank side — walk me through exactly how you classify it.
- Why paise as BIGINT instead of a floating-point rupee amount?
Resume bullets it generates
- Built a reconciliation engine in Java/Spring Boot matching & classifying N transactions across two feeds in M seconds using an O(n) hashmap instead of an O(n²) scan.
- Implemented a 5-way discrepancy classifier with paise-exact BIGINT arithmetic, producing an auditable exceptions report.
- Made the batch idempotent via input-content hashing, so re-runs are safe — a property finance teams depend on.
Fill N and M from your own measured runs — never claim a number you didn’t measure.
Build it with Claude for speed, but answer the design questions yourself first, so you own every decision and can defend it live. Log each milestone in the Journal — that’s your reflection trail and interview story.