Matching
The job was never open
Aaron at Job Umbrella · September 11, 2026 · 9 min read
Spend an hour on a tailored application, send it, and hear nothing. That is normal and survivable. What is not survivable, in terms of a person’s willingness to keep going, is finding out later that the role had been filled for a month, or was never a real opening at all.
The published estimates vary but they all land in the same unpleasant range. Greenhouse has reported something like 18 to 22 percent of listings on its platform going stale each quarter. An analysis by Clarify Capital across 175,000 listings put it at roughly one in seven, rising past one in five for senior roles. Job seekers themselves usually guess higher.
This is the complaint I decided to answer first, because it is the one that wastes the most of a person’s life.
You cannot ask, so you have to infer
Nobody will tell you a posting is dead. The board does not know. The employer has no reason to update it. So the signal has to be built out of what is already in the data.
Two things turn out to be available for free on every listing, and I had been storing both and using neither. The first is the posting date. The second is how many different sources carry the same posting — the feed already deduplicates across boards, so the count of sources for one job is sitting right there.
Neither is meaningful alone. A job on five boards today is well distributed, which is what a real, urgent opening looks like. The same job on the same five boards ninety days later is what people mean when they say ghost listing. So age and breadth compound rather than add: breadth is only evidence once the posting is old.
Every unknown resolves in the listing’s favor. A posting with no parseable date earns no penalty at all, because “we could not read the date” is a fact about us, not about the job.
That rule matters more than the formula. Sources report data unevenly — some never give a date, some truncate the description. If a missing field quietly cost a listing points, this would not be a ghost-job detector. It would be a detector for sources with worse metadata, and it would bury real jobs from the boards that are least polished.
Saying why, out loud
Every match now shows its own arithmetic: which parts of the score came from where. An opaque match score is one of the loudest complaints against the big sites, and it is entirely self-inflicted — the number is computed, so it can be explained.
One honest wrinkle. The explanation is rebuilt at read time from the same pass that produced the score, so the two can never drift apart. But one input — your own history of saving and dismissing listings — cannot be cheaply recomputed, because that would mean loading a couple of hundred listing records on every page view. It is recovered as the residual between the parts and the stored total, and the panel says plainly when your profile has moved since the score was computed. I would rather show a small gap and name it than present a tidy breakdown that quietly does not add up.
Asking the posting directly, carefully
Alongside the inference there is a sweep that actually checks the link, and one rule decides everything: only an explicit 404 or 410 retires a listing.
Job boards answer 403 to anything that looks automated, 429 when they are throttling, and 503 more often than they would like to admit. Every one of those is tempting to read as “gone”. Treating any of them that way would quietly cost somebody a real application to a real opening, which is a far worse error than leaving a dead listing up for another day.
What happened after you applied
The other half of this release is about the silence. The site now tracks, across everyone using it, how often an employer actually responds — measured from real stage movements, not from reviews or opinions.
It stays completely invisible until an employer has at least five applications from at least three different people, so it can never expose one person’s activity. On current numbers that means it shows almost nowhere, which is correct.
And it was wrong on the first attempt, in a way worth confessing. Moving a job into “Applied” is itself a stage change, written milliseconds after the applied date. The code was reading that as the employer responding. Every employer would have published something close to a 100 percent response rate, on a feature whose entire claim is that it is measured rather than reviewed. Found before it shipped, by a functional pass against real accounts.
The migration that would have taken the site down
Back in July I put the database migration step inside the web service’s start command. One line in the app spec: run the migrations, then start the server. It is the shortest path and roughly every tutorial shows something like it. This week it nearly collected.
One of this release’s migrations added two columns without a guard against them already existing, and it sorts first alphabetically, so it runs before its neighbours. If it had applied halfway and been retried, the retry fails — and because migrations run inside the start command, a failed migration is not a failed job. It is a web service that never finishes starting, which the platform reports as the site being down.
It carries the existence guard now, like its neighbour already did. That is the patch. The real fix is to take migrations out of the boot path altogether, so that a bad migration fails the deploy and leaves the previous version serving. I am not shipping that on the same day as anything else.
Release notes
September 12, 202633 commits · 2 migrations · merge 2bc7b97 · applied 00:14 UTCShipped
- Ghost Job Score on every match: posting age and syndication breadth, compounded, with every unknown resolved in the listing's favor.
- Recency in the match score: full weight to 14 days, easing to a floor at 90 rather than to zero.
- Why this job scored what it did, rebuilt at read time from the same pass that produced the score.
- A sweep that checks whether a posting is still up, plus a button on the job page.
- Follow-up tasks on applications that have gone quiet.
- Employer response figures, measured from real stage moves and hidden below five applications from three people.
- Four more listing checks: pay stated in the description, remote the description argues with, staffing agency rather than the employer, and entry-level titles demanding years.
- Same-source reposts collapse to the newest, and the card says how many times it was posted.
- A Help Center page for every card on the landing page.
- Browser extension 0.4.0 cut for both stores.
Fixed before it shipped
- Profile saves returned a server error for every user. A new field was spread into the database write as a column that does not exist.
- Employer statistics read the act of applying as the employer's reply.
- A 306 KB document drove a process to 967 MB of memory in under a second, from an endpoint that needs no account.
- A 165 KB PDF blocked the event loop for 6.6 seconds, from the same endpoint.
- The link checker validated the hostname and never the address, so a public name pointing at the loopback address made the server dial itself.
- A migration added columns without a guard, and migrations run in the boot command, so a retry would have left a service that never starts.
- The data-export link spent its one-time token when a mail scanner followed it.
Copy
- A plain-language pass over the whole site. One name for one thing.
- The word kanban is retired. It was in the search snippet and the social card, read by the people least likely to know it.
- Two claims were simply wrong: dozens of boards against a real count of twelve.
- The ranking promise is stated as an invariant the product has to hold, not as marketing copy.
Still open
- Three of the four minimum-match filter options cannot match anything, because the score tops out near twelve and the options are set as if it were a percentage.
- Resume parsing still runs on the request thread. It needs a worker that can be terminated.
Everything here is free to use
AI resumes and cover letters, a fit check against any posting, search across 12 job boards plus government sites, and a Board that tracks every application. No employer can pay to reach the top of your list.