How daily job matching works (and why we built it that way)
- JobHawk Team
- Product
- 21 Apr, 2026
JobHawk matches you with jobs once a day based on your preferences. Here’s how the matching engine works, what signals it uses, and why we chose daily over real-time.
The short version
Every morning, JobHawk pulls new job postings from multiple sources, checks them against your preferences, and delivers a set of matches to your feed. Free accounts get five matches per day. Essential gets 25. Pro gets 60.
That’s the user-facing version. Here’s what’s going on underneath.
Where the postings come from
We aggregate listings from LinkedIn, Google Jobs, and other sources. A lot of the same role gets posted across multiple boards, so the first thing we do is deduplicate. If a Senior Product Manager opening at Stripe shows up on three different sources, you see it once.
New postings get collected overnight. By the time matching runs in the early morning, we have a fresh batch of listings to work with.
What “matching” actually means
When you set up JobHawk, you tell us what you’re looking for: target job titles, locations, salary range, career stage, work type (full-time, contract, remote-only), and a few other preferences. The matching engine uses those preferences to filter the full pool of new postings down to the ones that are relevant to you.
This is more nuanced than keyword search. A few examples of how the filtering works in practice:
If you set your target salary at $150,000, we don’t just look for postings that list exactly that number. We use an 85% threshold, so a posting with a range of $130,000-$160,000 still qualifies. And if a posting doesn’t list salary at all, we let it through by default rather than hiding it. Most postings don’t include salary, and filtering them all out would leave you with a thin feed. (You can override this and require salary data if you prefer.)
If you’re set to remote-only, we only show remote positions. But if you’ve listed target locations and you’re open to hybrid, we match on your cities while also letting through postings that don’t specify a location, since a lot of listings leave that field blank.
Career stage works the same way. If you mark yourself as senior-level, we’ll match on seniority labels like “senior,” “staff,” “lead,” and “principal.” Postings that don’t specify seniority still get through, because plenty of companies just don’t fill in that field.
The pattern across all of this: we’re strict about the things you’ve told us matter to you, and lenient about missing data. We’d rather show you a relevant posting that’s missing a salary field than hide it because the employer didn’t fill in every box.
What gets filtered out
Some filtering is preference-based, as described above. But some is always on, regardless of what you’ve set.
We exclude postings from companies you’ve told us to ignore. If you worked at a company and never want to see their listings, or if you’ve already decided a particular employer isn’t for you, those get filtered out permanently.
We also exclude postings you’ve already seen. The matching engine tracks a watermark timestamp for each user, so it only looks at postings that appeared after your last match run. You won’t see the same listing twice across different days.
And we only match against active listings. Postings that have been taken down or gone stale get swept out of the pool before matching even starts.
Then comes ranking
Matching gets the right postings in front of you. Ranking decides which ones go first.
On paid tiers (Essential and Pro), the matched postings go through a second pass where an AI reviews each one against your full profile: not just titles and locations, but your career stage, compensation targets, risk tolerance, top priorities, and any additional context you’ve provided. It picks the top matches and explains why each one is a good fit, including any concerns worth noting.
This ranking step runs separately from matching, about 30 minutes later. We split them intentionally. Matching is fast SQL filtering, and it can handle a large volume of postings quickly. Ranking involves an LLM call for each user, which is slower and more expensive. By decoupling them, if ranking has an issue on a given day, you still get your matches. And if matching runs thin for a day, ranking can look back at the last few days of unranked postings so there’s enough to work with.
Free tier users get matched postings sorted by recency. They skip the AI ranking step, but the filtering is identical.
Why daily, not real-time
We thought about this one for a while.
Real-time matching sounds better on paper. A job gets posted, you get notified immediately, you’re first to apply. In practice, it creates problems.
The obvious one is noise. If you’re looking for product management roles in three cities, you might get 15 to 20 new postings on a busy day. Getting pinged every time one shows up turns your phone into a distraction machine. Most people don’t want to stop what they’re doing to evaluate a job listing the moment it appears.
The less obvious problem is that real-time matching makes people anxious. It turns job searching into a reactive activity where you feel like you need to be “on” all the time, checking immediately, applying fast before someone else does. That’s not how good job searches work. The companies worth working for aren’t filling roles in the first 45 minutes after posting.
We also considered weekly, which has the opposite problem. A week is long enough that good postings get buried, and you lose the rhythm of checking in regularly.
Daily felt right. You check your feed once a day, see what’s new, save the ones worth pursuing, and move on. It creates a routine without creating pressure.
The tier limits
Free accounts get five matches per day. That’s enough to see the feature working and decide if it’s useful for your search. Essential gets 25, which covers most active job seekers. Pro gets 60, which is meant for people casting a wide net across multiple roles or locations.
These are per-run caps, not rolling quotas. The matching engine runs once in the morning, and the limit controls how many postings it pulls for you during that run. There’s no “saving up” unused matches.
We set the limits based on what felt useful without being overwhelming. (For how those tiers compare with what other tools charge, we lined up the pricing across the category.) Five matches is a quick scan. 25 is a focused review session. 60 is a deep browse for someone actively exploring a broad market. We’ll adjust these over time if the data tells us we got them wrong.
What we’re still working on
The matching engine today is preference-based. It knows what you’ve told it you want. The next thing we’re building is behavioral matching, where the system also learns from what you actually do. If you consistently save backend engineering roles at mid-size companies and ignore the enterprise ones, the matching should adapt to that pattern over time without you needing to update your preferences.
We’re also working on better handling of vague postings. A lot of job listings don’t include structured data about salary, seniority, or remote status. Right now those pass through our filters by default. We want to get better at inferring that missing information from the posting text so the filtering is more accurate even when the employer hasn’t been thorough.
If you want to try the matching, it’s available on all tiers. Set your preferences, and you’ll have your first matches by the next morning.
Try JobHawk free →