Career OS

Build · Project 1

Recon — The Reconciliation Engine

Your headline portfolio project — and the one you can defend cold, because it’s your Ayris acceptance-testing world in code. Every payments company answers this question at 7am: does the bank’s record match ours, to the paisa?

What you’re building

A batch engine — Java 21, Spring Boot, PostgreSQL — that ingests two transaction feeds (a messy bank CSV + your clean ledger), matches them with an O(n) hashmap, classifies every discrepancy into 5 buckets, and produces a report finance can act on. Safe to re-run (idempotent), fast enough for 100k+ rows.

Why it lands jobs

💼 It’s the actual business

“I built a reconciliation engine” makes a fintech recruiter lean forward — it’s the unglamorous core of payments, not another CRUD app.

🛡️ You can defend it

It’s reconciliation = comparing two sources of truth = exactly acceptance testing. You’ve lived it.

📊 It has a real number

“Matched 100k×100k in M seconds with an O(n) hashmap” — a measured metric beats vague claims.

🧠 It uses your lessons

Hashmap matching, Big-O, SQL, idempotency — every green node cashed in.

The 5 buckets it classifies

BucketMeaning
matchedSame reference and amount in both feeds ✅
missing in bankLedger has it, bank doesn’t (recorded but not settled)
missing in ledgerBank has it, ledger doesn’t (money received, not recorded)
duplicateSame reference appears twice on one side
amount mismatchSame reference, amounts differ — even by 1 paisa

⚠️ 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? Do you 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. Same case or three different ones?

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.

Build plan — 6 milestones

M1Schema + a walking skeleton that matches 5 hand-made rows.
M2The normalizer: parse messy dates and “1,250.00” amounts to paise (BIGINT). Test the ugly cases.
M3The matcher at scale: map-and-stream on 100k rows — measure the time (your first resume number).
M4The classifier: all 5 buckets, including duplicates and 1-paisa drift → exceptions CSV.
M5Idempotent runs: hash the input, skip repeats, persist the run + summary.
M6Package + README a stranger can run.

Resume bullets it generates

Fill N and M from your own measured runs — never claim a number you didn’t measure.

🔨 The method

Build it with Claude for speed, but answer the 6 design questions yourself first, so you own every decision and can defend it live. Log your progress in the Journal.


Back to your Siemens roadmap →

Saves your progress on this device.