Interviewer — reconciliation (VRM)
Candidate prompt: prompt. Method: Method.
Do not let the candidate read this file. Give numbers and product rules only when they ask, or when they are stuck after you have nudged them to ask.
This is an Engineering Manager loop. This problem is two systems of record, not a BI dashboard.
How to run it (45–60 min)
| Step | Time | Do not leave until |
|---|---|---|
| 1. Requirements | 8–10 min | Two pictures of the world, point-in-time T, tenancy, what’s worse |
| 2. APIs | 3–5 min | Run-at-T, list breaks, act on a break; authz |
| 3. High-level design | 12–15 min | Break is an entity; compare does not overwrite either ledger |
| 4. Deep dives | 12–15 min | Two of: snapshot/T, notice-as-explanation, idempotent compare, tenancy, heavy job |
| 5. EM close | 3–5 min | Workflow KPI, UX+backend staffing, not a generic dashboard |
If time dies, skip CDN and fancy charts. Keep agent vs lender truth and who can see whose breaks.
Step 1 — Requirements
Open
“Walk me through how you’d approach this. I’ll answer questions.”
If they start with a warehouse or Tableau: “What is the user trying to do at 4pm when cash doesn’t match?”
They should ask (nudge if silent)
- Who compares — lender, admin, trustee, agent?
- Compare what — positions, cash flows, both?
- At what time T? Live vs point-in-time?
- Where does the lender’s book come from?
- What is a “match”? Tolerance?
- What’s worse: stale, wrong, down, leaked?
- Does the platform already have agent notices? (yes)
Answers to give when asked
| Question | Give them |
|---|---|
| Users | Lender ops, loan admins, trustees. Agents want fewer inbound “what’s my position?” calls. |
| What to compare | v1: positions at time T. Most cash-flow mismatches are position discrepancies. Cash-flow detail can be v2. |
| Time T | Any point in time the user picks, plus “as of now.” Must be a snapshot, not two moving targets. |
| Lender book | Some lenders will upload/file/API their positions. Some only want to browse agent golden source and mark internal breaks. Both are in scope; v1 can be “compare file vs agent” or “agent vs what we last showed you” — make them pick, don’t invent a magic two-way sync. |
| Direction of truth | Agent books are what is. Lender book is “what I think.” The product explains the gap. It does not silently overwrite either side. |
| Notices | Agent notices (paydown, interest, draw, fee, etc.) exist on the data platform. Ops wants to see the notice that caused the break. |
| Scale | ~11k facilities, trillions in commitments. Compare jobs are spiky (month-end, after a notice burst), not 100k QPS. |
| Tenancy | Lender A never sees lender B’s breaks or positions. |
| Failure preference | Wrong/leaked worse than a slow compare. A spinner that claims they match is a product incident. |
| Cloud | Azure, single region to start. |
Gate
Do not start APIs until they have:
- Two inputs (agent golden source vs lender view)
- Compare at T
- Conflict as something you list, not an exception you swallow
- Authz / tenancy called out
If they say “we just sync them”: “Who wins when they disagree, and what does the screen show?”
Weak: One database, lender rows updated from the agent, UI shows green. Strong: Break is first-class; UI shows last compared at, mismatches, and a notice to inspect.
Step 2 — APIs
Want operations like:
POST /reconciliations— lender, as-of T, optional upload/sourceGET /reconciliations/{id}— status of the jobGET /reconciliations/{id}/breaks— list, filter, entitled onlyGET /breaks/{id}— including linked notice / “answer key”POST /breaks/{id}/ackor assign / comment (workflow)- Authz on every read
If they skip job status: “A compare across thousands of facilities is not a 50ms GET. What does the user see while it runs?”
Gate
Move on when there is a run, a list of breaks, and a read of one break with permissioning.
Step 3 — High-level design
Ask for one box at a time.
Boxes you want
- UI — break list, notice attached, human actions. Not a spinner that pretends they already match.
- Reconcile API
- Compare job — batch + on-demand; reads snapshots; does not live-lock the golden store
- Golden source (agent) and lender-provided positions — two inputs, one comparison
- Break store (first-class entity: ids, T, both sides, linked notice, status)
- Queue for heavy compare
- Observability on the job, not only the SPA
- Entitlements on list and detail
Push questions
- “Does JavaScript pick a winner?”
- “If we run compare twice for the same T, do we get two sets of breaks or one?”
- “How do you attach ‘the notice that caused it’ without scanning email?”
- “Month-end: 200 lenders hit Run. What happens to the golden-source DB?”
Traps
| Trap | Follow-up |
|---|---|
| Overwrite lender book with agent | “They still have to explain the break to their own accounting. What did we just destroy?” |
| Live join of two changing tables | “Both sides moved during the query. Is it a break or a race?” |
| Warehouse as the product | “Time-to-explain-a-break is the KPI. How does a star schema help the person on the phone?” |
| Same squad owns ingest + pretty grid | Conway: the hose loses. |
Gate
Break is stored and listed. Neither ledger is clobbered. Compare is off the request path if it is heavy.
Step 4 — Deep dives (pick 2–3)
A. Point-in-time snapshots
Want: freeze agent positions at T and lender file at T; compare immutably; as_of on the API.
B. Notice as answer key
Want: breaks link to the notice (or transaction) that moved the position. Don’t scrape Outlook. If the notice isn’t in platform yet, UI says unknown cause, not a guessed story.
C. Idempotent compare
Want: same lender + T + source version → same break set (or versioned rerun). Don’t duplicate a workflow ticket on every click.
D. Tenancy / leaked break list
Want: row-level authz; negative test; support users still scoped.
E. Poison / partial lender file
Want: reject the file with an operable error; don’t mark the whole book “matched.” DLQ for job failures; don’t block other lenders.
Stakeholder curveball: “It should just sync, like Excel reconciling itself.” Same EM spine as Temelio: outcome (stop duplicate confusion) without lying in the data model.
Step 5 — EM close
Listen for:
- v1: identify and explain position breaks at T; one lender cohort; notice link if we have it
- Not v1: two-way magic, generic BI, every cash-flow type
- Staffing: workflow product → UX + backend together; mapping/ingest is platform/dotted line
- KPI: time-to-explain-a-break, % breaks with a linked notice, entitlement false-allow = 0, compare lag — not tickets closed
- DoD: snapshot tests, tenancy tests, job metrics
- Exec: honest break list this month vs green dashboard that is wrong
Rubric
| Weak | Hireable | Strong | |
|---|---|---|---|
| Requirements | “A dashboard of positions” | Two sources + T | Break as the product; agent wins for “what is” |
| Design | Client-side merge | Job + break list | Snapshots, notice link, idempotent rerun |
| EM | More columns | Mentions ops user | KPI + staffing + refuses fake two-way |
Personal parallel: Temelio accounting mapping layer.