← back home

Case studies

How the work
actually happened.

Choose an investigation for analytical depth or a builder story for product thinking. Each case shows the question, the evidence, the decision and the measurable result.

Investigation 01 · Zocket · 2024

The $22K wallet leak nobody could see.

SQLStripe APIFacebook Ads APIReconciliation
QuestionDo all three money ledgers agree?
ScopeEvery wallet · no sampling
Outcome$22K recovered

The tip-off

Customers fund ad wallets through Stripe. Spend flows out through the Facebook Ads API. Everyone assumed the two ledgers reconciled — nobody had actually checked. Then small gaps started surfacing in finance reviews.

"The wallet totals are off again this month. Can someone look into it? It's small, but it keeps happening."— finance review, one more time

The audit

No sampling. Every wallet, every movement, both directions — a transaction-level join across all three ledgers.

wallet_audit.sql
-- full-population reconciliation: no sampling
WITH stripe AS (SELECT wallet_id, txn_id, amount FROM stripe_charges),
     spend  AS (SELECT wallet_id, ad_id, spend  FROM fb_ads_spend),
     ledger AS (SELECT wallet_id, entry_id, delta FROM wallet_ledger)
SELECT w.wallet_id,
       SUM(s.amount)  AS funded,
       SUM(sp.spend)  AS spent,
       SUM(l.delta)   AS ledger_balance,
       funded - spent - ledger_balance AS drift   -- should be 0. always.
FROM wallets w LEFT JOIN stripe s  USING(wallet_id)
               LEFT JOIN spend  sp USING(wallet_id)
               LEFT JOIN ledger l  USING(wallet_id)
GROUP BY 1 HAVING drift != 0;

The find — exhibit A: duplicate entries

entry_idwallettypeamountcreated_at
e_88213w_1042top-up$500.0002:14:07.113
e_88214w_1042top-up$500.0002:14:07.891
e_88215w_2210top-up$1,200.0002:16:33.402
e_88216w_2210top-up$1,200.0002:16:34.008
e_88217w_0977top-up$350.0002:18:01.554

Retried webhooks written twice, ~800ms apart. Balances inflated; spending limits computed off the inflated number — the platform was quietly overcharging itself. Two bugs, individually invisible.

The fix

Documented the exact failure paths, handed engineering a reproducible case list, and added standing reconciliation checks — so the next drift shows up on a dashboard, not in a quarter-end surprise.

$0Krevenue recovered
2 bugsroot causes found
0 → 1standing reconciliation checks

Investigation 02 · Zocket · 2023–24

The MRR that was 15% too good to be true.

Root-cause analysisSQLRevenue modellingInvestor reporting
QuestionDoes reported MRR reconcile to cash?
ScopeDashboard → source events → payments
Outcome15% overstatement corrected

Two numbers that should agree

Reported revenue drove investor updates and leadership decisions. Cross-checked against money actually collected, the dashboard was running ~15% hot — and had been trusted for months.

Dashboard MRR
115
Cash collected
100

The trace

Every metric traced back to source tables — dashboard → revenue view → billing events → payments. The divergence wasn't in the data. It was in a definition.

lineage_trace.txt
investor_dashboard.mrr
  └── vw_monthly_revenue          ← definition lives here
        └── billing_events         ← counts *invoiced*, incl. failed & cancelled
              └── payments         ← what actually cleared
DIVERGENCE FOUND: vw_monthly_revenue ≠ SUM(payments.cleared)

The bug — it was the formula, not the data

-- vw_monthly_revenue (the fix) - SUM(CASE WHEN event IN ('invoiced','scheduled') THEN amount END) - -- counts revenue that never materialized: failed cards, - -- cancelled-in-trial, double-fired upgrade events + SUM(amount) FILTER (WHERE payment_status = 'cleared' + AND NOT is_duplicate_event) + -- one definition, reconciled to bank actuals monthly

The kind of bug that survives because everyone assumes someone else validated it.

The rebuild

Rebuilt the revenue logic from scratch, cleaned the underlying event data, reconciled reporting to actuals. Leadership and investor relations got an MRR they could defend in a diligence room.

0%overstatement corrected
100%reconciled to actuals
1source of truth for MRR

Builder case 01 · Apex — told as a notebook

Every founder rebuilds the same revenue spreadsheet. So I killed it.

Open the project dossier →
apex_demo.ipynb · kernel: revenue · trusted

Why this notebook exists

Years of analyst work, same scene everywhere: founders wrangling revenue exports in spreadsheets before every board meeting — getting subtly different answers each time (see Investigation 02). Apex turns that ritual into one import.

In [1]:
import apex df = apex.load("stripe_export_2026.csv") # any payments export
Out[1]:
✓ 48,712 transactions · 14 columns auto-detected · 3 data issues fixed (2 currency, 1 date format)
In [2]:
apex.mrr_movements(df, month="2026-06") # every $ classified
Out[2]:
movementcustomersΔ MRR
new84+$12,440
expansion31+$5,210
reactivated9+$1,180
contraction17−$2,050
churned42−$6,890
net+$9,890
In [3]:
apex.cohorts(df).plot(metric="revenue_retention")
Out[3]:
cohort revenue retention, month 0 → 6 (each row = a signup cohort)
In [4]:
apex.board_pack() # the whole reason this exists
Out[4]:
✓ 12 investor-ready views generated in 3.2s — MRR bridge, NRR, cohorts, new-vs-repeat, geo.

Who it helps: founders who can't justify a data hire; finance teams tired of month-end. Honest gaps: live Stripe/Razorpay sync (today: file upload), multi-tenant workspaces, peer benchmarks. Hours of board prep → minutes.

Builder case 02 · Statement Wizard

PDF parsers lie on page 40. Mine doesn't.

Bank & credit-card statement PDFs → clean Excel, with reconciliation as a built-in guarantee: opening balance + transactions must equal closing balance — or it tells you exactly where the break is.

Working buildPythonIndian banks first
statement-wizard.app
Statement Wizard product preview
"Worked perfectly on the 2-page sample. Row 1,847 of the real statement? Gone. Silently."— every generic PDF parser
"The AI tool returned different totals for the same file, twice."— the reason 'AI-powered' isn't a guarantee
"I just re-typed all of March."— an accountant, defeated

How it works

Upload PDFany size, any page count Detect bank layoutformat-aware, per bank Extract rowstuned parser, not generic Reconcilevs. the statement's own totals Clean Excelor the exact break location

The principle

  • The statement's own opening/closing balances are ground truth — never trust the parser.
  • Per-bank parsers are boring and 10× more reliable than clever generic ones.
  • Fail loudly with a location; never export silently-wrong data.

Built for

  • Accountants & bookkeepers processing statements at volume
  • Analysts doing reconciliation work
  • Exactly where the "works on a sample" tools break down

Honest roadmap

  • More bank layouts — the long tail is long
  • Batch API for accounting firms
  • Direct Tally / QuickBooks export

Builder case 03 · SchemaSight

Every company's database is tribal knowledge. I made it a map.

Paste a schema — get every relationship, key and column type as an explorable ER diagram. No walkthrough from the one senior engineer who remembers.

Working buildTypeScriptGemini AI
schemasight.app
SchemaSight product preview
"Which table has the real revenue?"— every new analyst, week one
"Ask Ramesh, he set it up in 2019."— tribal knowledge as architecture
"The ER diagram in Confluence is four migrations old."— documentation, in practice

How it works

Paste schema / DDLany SQL dialect Parse tables & keysexplicit FKs first Infer the restuser_id → users, by convention Explorable graphclick a table, see its world AI explains"what is this cluster for?"

The insight

  • Naming conventions encode 80% of the relationships FKs never declare.
  • The graph is easy; progressive disclosure (not 200 tables at once) is the design problem.
  • "What is this table for?" is an AI-shaped question.

Built for

  • New analysts and engineers in week one
  • Data teams documenting legacy systems
  • Onboarding that shouldn't need archaeology

Honest roadmap

  • Live database connections (today: pasted schema)
  • Team sharing & annotations
  • Schema-drift diffing between versions

Keep going

Browse every project.

The full catalog — expandable dossiers with flows, screenshots and honest detail.

projects →

Or just

Say hello.

gautham2597@gmail.com — Chennai, India.

contact →