¶ case study — 01 · shipped spring '26 · timeline: 11 weeks · team: 1 tags: matching · search · postgres
the old engine matched keywords. the new one reads the whole résumé.
by evgeniy · apr 18, 2026 · ~8 min read
for three years matchpro matched candidates to jobs the lazy way — a tf-idf over titles, with a sprinkle of rules. it was fine. not great. recruiters kept emailing me screenshots of obvious matches it missed. so this spring i sat down and rebuilt the whole thing.
"matching is not search. search rewards precision. matching rewards being interestingly close."
how it went down
- throw away the ranker — kept the data, dropped the model. started from a blank ipynb.
- embed everything — résumé + job text → small multilingual model, cached in pg_vector.
- re-rank with signals — location, seniority, years-in-stack. boring features still win.
- shadow-run for 3 weeks — a/b on recruiters' clicks. watched dashboards more than family.
results — 11 weeks later
- match-quality (recruiter 👍) — 41% → 78% (+37 pp)
- time-to-first-click — 9.2s → 3.1s (−6.1s)
- weekly placements — 12 → 28 (×2.3)
- latency (p95) — 640ms → 180ms (−72%)
› bench --cohort=q1-recruiters
running 2,140 matches…
✓ v3 beats v2 on 78% of pairs
! 4 regressions — investigating
› deploy prod
● published · 41kb · 2 figures · 6 footnotes