Skip to content
Works

Graduate Matching Platform

A recruitment platform where the operator's own introductions had to stay first-class alongside self-serve matching, and where the leakage problem in success-fee pricing was solved socially rather than by surveillance.

Period
May 2023 – May 2026
Team
One or two developers most months, more during delivery pushes
Role
Backend and frontend development, later leading delivery
Scale
63 tables · 44 web screens · a student and employer mobile app
Stack
TypeScript · NestJS · TypeORM · MySQL · Socket.io · Next.js · React Native · Firebase · Google Cloud Run · Cloud SQL · Cloud Build

Problem

The client's business was built on a student audience. They had spent years running advisory services for students entering the job market, which left them holding what recruitment companies pay for: a large pool of people, and those people's trust.

The obvious way to monetise that is to introduce those students to employers, and they were already doing it by hand — staff who knew both sides making the connection. What they wanted was that same business running as a product.

The constraint came with it. Students and companies would be able to find each other directly, but the introductions the operator made could not become a second-class path in the process. The relationships were the asset the business was built on, and a platform that routed around them would have been worth less than the manual work it was meant to carry.

Approach

Both routes to a match end in the same place. A student who finds a company through search and a student the operator introduces are, from that point on, having the same conversation, so an introduction is delivered into the same chat rather than into a parallel system alongside it. What separates them is a flag on the record: the fact that a match began as an introduction survives and can be traced afterwards, without the product splitting into two half-built versions of the same thing.

Self-serve matches and operator introductions converge into the same conversation, distinguished only by a flag on the record rather than by separate systems. TWO WAYS IN They find each other student or employer searches The operator introduces staff who know both sides ONE CONVERSATION Chat thread + introduced: true/false WHAT THE FLAG BUYS Attribution survives the match Introductions stay traceable One product, not two halves The operator's introductions were the asset the business was built on, so they could not become a second-class path. Routing both into the same thread, and separating them with one flag, keeps them equal without duplicating the product.
Both routes end in the same conversation. One flag keeps the difference without splitting the product.

The mobile app carries the two market sides — students and employers — while the operator's own administration is web only. That asymmetry was deliberate. Someone using the app is doing something occasional and personal: checking messages, reading a profile, answering an approach. The operator is working across many candidates at once, which is desk work, and building that for a phone would have cost real effort for a workflow nobody wanted to do on a phone anyway.

Getting students to show up at all is a separate problem from matching them, and the answer was not to argue that the platform was worth visiting. Students entering the job market need a CV before they need anything else, so CV writing lives inside the app, and the operator's staff can work on it with them there. That is the same advisory service the business was already known for, now happening somewhere that leaves a profile behind. The reason to open the app is something the student wanted independently of us.

The client had also built an audience on YouTube, which most projects would have treated as marketing that happens elsewhere. I wired routes between the two instead, so the channel feeds the service rather than sitting beside it.

Hosting is Google Cloud throughout: Cloud Run in front of Cloud SQL, deployed from Cloud Build on a push to main, with the production migrations running as part of the rollout.

Trade-offs

Employers pay either a monthly subscription or a fee when they hire. The second model has an obvious hole: a company can meet a student on the platform, move to email or a video call, hire them, and never mention it.

The technical answer to that is surveillance. Watch for contact details being exchanged, flag invitations to other channels, restrict what a message may contain. I did not build it. It is expensive, it degrades the product for everyone in order to catch a minority, and it does not work anyway, because two people who want to talk somewhere else will.

What served instead was already in the business. Employers submit the offer letter as part of the process, and students have their own obligation to report when they accept a position. Those are two independent routes to the same fact, and a company concealing a hire has to survive both — including a student who has no reason to know the hire was meant to be quiet, reporting it as a matter of course. The operator's closeness to its students, which is why the business existed at all, is also what made that reporting reliable.

So enforcement is a policy standing on two reporting duties rather than a monitoring layer. It leaks a little. It also costs nothing to run, it does not punish the people using the platform honestly, and the leak is smaller than what the surveillance would have cost — in engineering, and in how the product would feel to use.

My scope

I was on this for three years, but not in the same capacity throughout. It began as my second project: I was leading the groupware build at the time, and this was where my remaining hours went. When the schedule started slipping, I moved across as the main developer to pull it back, and stayed the primary one from 2024 onwards.

The team was rarely more than one or two people at a time, occasionally larger around a delivery. My own work split almost evenly across the three codebases — the mobile app, the web frontend and the NestJS server — which is what happens when the team is small enough that whoever is there does whatever is next.

Outcome

How much the product changed the shape of the business is not something I can answer from where I sat. That sits with the operator, and I was not the one reading those numbers.

What I can say is that it works and is still working. The platform is live on the app stores and remains in maintenance three years after it started, and matches are being made through it — both the ones people find for themselves and the ones the operator makes. The path that had to stay first-class still is.