ASafariMShowcase
04 /Case study

The matching engine behind a live, still-synthetic marketplace

EduMatch (edumatch.asafarim.com) is a real, deployed app today — accounts, bookings, tutor invites — running in showcase mode on synthetic data. This benchmark exists because the part worth inspecting closely, the ranking logic, is easier to trust in isolation than inside a full stateful app.

Synthetic data, safe demo mode. Every tutor and student here is invented for this benchmark — no real people, no real bookings, no real payments, no external side effects. Ranking runs entirely in your browser against committed fixtures. The runnable harness lives in benchmarks/edumatch.
01 /Evolution

What was ported, what wasn't

StageStackCore ideaWhere it hit a wall
Personal projectNext.js · Prisma/Postgres · Stripe Connect · geocodingA full tutoring marketplace: intake, tutor discovery, quotes, Stripe-split payments, disputes, verification, notifications.It grew into a real deployed app (edumatch.asafarim.com, Auth.js accounts, Postgres, a conversational Learning Brief flow) — but the matching algorithm's correctness and fairness are hard to see or argue with from inside a full stateful product.
This benchmarkPure JS engine · synthetic fixtures · client-side demoExtract a simplified version of the matching logic, make it explainable and adjustable, and prove it with deterministic tests you can run without a database.Deliberately no accounts, payments, or live infrastructure — and its weights are illustrative, not a live mirror of the production engine, which has since evolved to eight factors (see Method on the overview page).
02 /Architecture

How the benchmark is built

Constraints first, scoring second

Hard requirements (subject, level, language, availability, mode/distance) are checked before any scoring happens. A tutor who fails one is never ranked — and the reason is recorded, not discarded.

Explainable by construction

Every ranked result carries a factor-by-factor breakdown (value × weight = contribution) that sums exactly to its composite score — there is no hidden step between 'why' and 'what.'

One engine, two consumers

The engine is a single ESM module imported by the Node test suite, the fixture generator, and the Showcase's client-side Match Explorer — there is no second implementation to drift out of sync.

Damped rating

The legacy algorithm normalised rating as avg / 5, which let a single five-star review outrank a tutor with forty consistently strong ones. This version damps toward a neutral prior so review count matters.

03 /Tradeoffs

What we gave up, and why

Real app, but not a real marketplace yet

edumatch.asafarim.com is a live, working app, but every tutor profile is synthetic and checkout is a $0 mock — there is no real tutor supply and no real money moving. This benchmark's fixture-based demo makes the same honesty tradeoff on purpose, rather than dressing up synthetic data as a real marketplace.

Small, hand-reviewed fixture set

Twelve tutors and six needs are enough to demonstrate the method precisely — a deliberate twin pair, a tight-availability case, a no-qualified-tutor case — but they are not a statistically representative population.

04 /Lessons

Lessons from the legacy system

Explainability is a design decision, not a feature

The legacy scorer produced a single number. Retrofitting an explanation after the fact is much harder than building the factor breakdown as the primary output from day one, which is what this version does.

Fairness needs a provable test, not a policy statement

Saying "the algorithm doesn't use protected attributes" is a claim. A constraint-identical twin pair that must score identically is a test. See the Fairness page.

Toward a real production version
  • Real tutor supply: manually onboard the first verified tutors in a narrow subject/region niche instead of synthetic profiles, to solve the two-sided cold-start problem.
  • Live Stripe checkout in place of the $0 mock, and removal of the public 'showcase' disclaimer once real payments are wired up.
  • Guardian approval flow for minors — the data model (isMinor, guardianName, guardianEmail) and the safeguarding match filter exist, but the approval gate before payment is not built yet.
  • Localisation of the Learning Brief flow beyond English and Dutch (fr/de/lb currently fall back to English).
evidence-first