[{"data":1,"prerenderedAt":241},["ShallowReactive",2],{"work-matchpro-en":3,"work-og-matchpro":159},{"id":4,"title":5,"bars":6,"blurb":7,"body":8,"color":132,"contacts":133,"date":133,"dateModified":133,"description":134,"extension":135,"featured":136,"groups":133,"kicker":137,"meta":138,"metrics":139,"n":133,"navigation":136,"openTabs":133,"path":149,"progress":133,"readTime":133,"reading":133,"role":150,"rules":133,"running":133,"seo":151,"ships":133,"slug":152,"stack":133,"started":133,"status":133,"stem":153,"streak":133,"tag":154,"tagColor":133,"tagline":156,"tasks":133,"timeline":133,"topics":133,"week":133,"year":157,"__hash__":158},"en\u002Fwork\u002Fmatchpro.md","matchpro.io",4,"a niche job-board that actually matches people, not keywords. rebuilt the matching engine this spring.",{"type":9,"value":10,"toc":124},"minimark",[11,15,25,28,31,41,44,48,77,79,83,110,121],[12,13,14],"p",{},"¶ case study — 01 · shipped spring '26 · timeline: 11 weeks · team: 1\ntags: matching · search · postgres",[16,17,19,20,24],"h2",{"id":18},"the-old-engine-matched-keywords-the-new-one-reads-the-whole-résumé","the old engine matched ",[21,22,23],"em",{},"keywords",". the new one reads the whole résumé.",[12,26,27],{},"by evgeniy · apr 18, 2026 · ~8 min read",[12,29,30],{},"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.",[32,33,34],"blockquote",{},[12,35,36,37,40],{},"\"matching is not search. search rewards precision. matching rewards being ",[21,38,39],{},"interestingly close",".\"",[42,43],"hr",{},[16,45,47],{"id":46},"how-it-went-down","how it went down",[49,50,51,59,65,71],"ol",{},[52,53,54,58],"li",{},[55,56,57],"strong",{},"throw away the ranker"," — kept the data, dropped the model. started from a blank ipynb.",[52,60,61,64],{},[55,62,63],{},"embed everything"," — résumé + job text → small multilingual model, cached in pg_vector.",[52,66,67,70],{},[55,68,69],{},"re-rank with signals"," — location, seniority, years-in-stack. boring features still win.",[52,72,73,76],{},[55,74,75],{},"shadow-run for 3 weeks"," — a\u002Fb on recruiters' clicks. watched dashboards more than family.",[42,78],{},[16,80,82],{"id":81},"results-11-weeks-later","results — 11 weeks later",[84,85,86,92,98,104],"ul",{},[52,87,88,91],{},[55,89,90],{},"match-quality (recruiter 👍)"," — 41% → 78% (+37 pp)",[52,93,94,97],{},[55,95,96],{},"time-to-first-click"," — 9.2s → 3.1s (−6.1s)",[52,99,100,103],{},[55,101,102],{},"weekly placements"," — 12 → 28 (×2.3)",[52,105,106,109],{},[55,107,108],{},"latency (p95)"," — 640ms → 180ms (−72%)",[111,112,117],"pre",{"className":113,"code":115,"language":116},[114],"language-text","› bench --cohort=q1-recruiters\n  running 2,140 matches…\n  ✓ v3 beats v2 on 78% of pairs\n  ! 4 regressions — investigating\n› deploy prod\n","text",[118,119,115],"code",{"__ignoreMap":120},"",[12,122,123],{},"● published · 41kb · 2 figures · 6 footnotes",{"title":120,"searchDepth":125,"depth":126,"links":127},2,3,[128,130,131],{"id":18,"depth":125,"text":129},"the old engine matched keywords. the new one reads the whole résumé.",{"id":46,"depth":125,"text":47},{"id":81,"depth":125,"text":82},"var(--red)",null,"matchpro.io — a niche cyprus job-board that matches people, not keywords. rebuilt the matching engine in spring '26.","md",true,"▸ CH.04 \u002F matchpro · currently shipping v3",{},[140,143,146],[141,142],"jobs","1.2k\u002Fmo",[144,145],"placements","~180",[147,148],"revenue","profitable","\u002Fwork\u002Fmatchpro","solo · design + code + ops",{"title":5,"description":134},"matchpro","work\u002Fmatchpro",{"label":155,"color":132},"featured","job-board · it · cyprus","2021 → now","W3ME2VGgLsDw_xeEtEdOafRhHRaJK22QoMt28U1AVBc",{"id":4,"title":5,"bars":6,"blurb":7,"body":160,"color":132,"contacts":133,"date":133,"dateModified":133,"description":134,"extension":135,"featured":136,"groups":133,"kicker":137,"meta":234,"metrics":235,"n":133,"navigation":136,"openTabs":133,"path":149,"progress":133,"readTime":133,"reading":133,"role":150,"rules":133,"running":133,"seo":239,"ships":133,"slug":152,"stack":133,"started":133,"status":133,"stem":153,"streak":133,"tag":240,"tagColor":133,"tagline":156,"tasks":133,"timeline":133,"topics":133,"week":133,"year":157,"__hash__":158},{"type":9,"value":161,"toc":229},[162,164,168,170,172,178,180,182,200,202,204,222,227],[12,163,14],{},[16,165,19,166,24],{"id":18},[21,167,23],{},[12,169,27],{},[12,171,30],{},[32,173,174],{},[12,175,36,176,40],{},[21,177,39],{},[42,179],{},[16,181,47],{"id":46},[49,183,184,188,192,196],{},[52,185,186,58],{},[55,187,57],{},[52,189,190,64],{},[55,191,63],{},[52,193,194,70],{},[55,195,69],{},[52,197,198,76],{},[55,199,75],{},[42,201],{},[16,203,82],{"id":81},[84,205,206,210,214,218],{},[52,207,208,91],{},[55,209,90],{},[52,211,212,97],{},[55,213,96],{},[52,215,216,103],{},[55,217,102],{},[52,219,220,109],{},[55,221,108],{},[111,223,225],{"className":224,"code":115,"language":116},[114],[118,226,115],{"__ignoreMap":120},[12,228,123],{},{"title":120,"searchDepth":125,"depth":126,"links":230},[231,232,233],{"id":18,"depth":125,"text":129},{"id":46,"depth":125,"text":47},{"id":81,"depth":125,"text":82},{},[236,237,238],[141,142],[144,145],[147,148],{"title":5,"description":134},{"label":155,"color":132},1777071043022]