Case study
Gapl
Live — no commercial usersTwo blind spots, one gateway: candidates can't see what the ATS screens for, and outbound can't see which email closed the deal.
The problem, in the user's words
"I keep tuning my resume against a checklist I can't verify, and I have no idea which email in the sequence made someone pay." Two separate blind spots, same root cause.
Job seekers optimise resumes against ATS heuristics they can't observe directly. On the business side, a paid conversion arriving days after an email sequence has no reliable link back to the message or channel that produced it. Both problems share the same fix: make the screening machine explain itself, and make the funnel traceable past the same-session window.
Why the obvious solution fails
The standard resume tool returns a score out of a hundred, computed once, by one model. That's fragile two ways: a single LLM provider's outage or rate limit takes the whole feature down, and a bare number gives no reviewer-facing reasoning to check it against.
The standard attribution approach is a same-session tracking pixel. It breaks the moment a click and a payment are separated by more than a browser session — which is the normal case for anything that isn't an impulse buy.
Architecture — one diagram
Resume parsing and ATS scoring run behind a multi-model gateway: Groq's Llama 3.3 70B first, with automatic failover to OpenAI and then Gemini on error or rate limit, so one provider's outage doesn't take scoring offline. Attribution runs separately, on Next.js Edge Middleware — every outbound link is a shortlink on a decoupled subdomain, click telemetry is logged at the edge, and a conversion is stamped to whichever click sits within a 30-day last-touch window.
Each provider call carries the same prompt contract; a failed or rate-limited call falls through to the next provider automatically. Email attribution runs as a separate edge pipeline: shortlink → click telemetry → 30-day last-touch stamp on conversion.
Three decisions worth defending
Failover instead of a single vendor
Resume scoring runs behind Groq first, with automatic fallback to OpenAI and then Gemini on error or rate limit. A single provider going down doesn't take the product down, and cost shifts automatically toward whichever provider is actually available.
Attribution lives at the edge, not in a pixel
Click-through is tracked on Next.js Edge Middleware against a decoupled subdomain, with a 30-day last-touch window instead of a same-session cookie. Conversions that land days after the email they came from still get credited correctly.
Billing and refunds were built before the first paying user
Razorpay billing is HMAC-verified end to end, with a one-click refund path inside an RBAC admin suite. It was built and tested against the full webhook lifecycle before there was any revenue to protect, so day-one revenue doesn't depend on last-minute payment work.
What shipped
Built and deployed: multi-model resume parsing and ATS scoring, edge-based attribution with 30-day last-touch stamping, HMAC-verified Razorpay billing, an RBAC admin suite with SPF/DKIM/DMARC health checks and anomaly alerts, and day-1/day-7 retention crons running in production. No commercial users yet, and the public API is intermittently erroring — that's why the live link stays off this page for now.
What I'd do differently
I built the billing and admin surface — refunds, RBAC, deliverability health — before the core scoring API was stable enough to demo confidently. Revenue infrastructure for a product with no users yet was the wrong thing to harden first.
I'd also publish the multi-model failover logic and per-provider cost breakdown on its own, separate from the resume-tool pitch — it's the most technically interesting part of Gapl and it's currently buried inside a case study about resumes.