2026-09-02

It's getting harder to get hired on HN

Two Hacker News threads, counted since 2014. In January the seekers outnumbered the openings for the first time.

(sorry but i did manually edit this somewhat, otherwise tried to keep it free from humanslop)

the-threads

A bot posts two threads on the first of every month: Ask HN: Who is hiring? and Ask HN: Who wants to be hired? One comment is roughly one opening or one person looking. No survey, no revisions, no seasonal adjustment. Just a comment count going back to 2011.

I pulled all of it.

the-counts

who is hiring (openings) who wants to be hired (people)
Comments per thread, per month. Last point dashed: September was one day old when I pulled it.

Feb 2017 was the peak: 1,222 openings against 102 people looking. May 2018 had 1,179 openings and 64 people.

2021 is flat, so the cheap money never showed up here. From late 2022 the blue line falls and keeps falling. Aug 2026: 383 openings, 573 people.

the-ratio

HN itself grew over these years, so the raw counts are confounded. Dividing one by the other drops that out.

Seekers per opening. Above the dashed line there are more people than jobs.

Under 1.0 for eleven years. Closest it got was Apr 2020, at 0.84. It crossed in Jan 2026 (403 openings, 404 people) and has not come back. Aug 2026 is 1.50.

the-code

Algolia indexes HN, so the bot's whole twelve years comes back in one request.

# every story the whoishiring bot ever posted, in one request
import json, re, urllib.request, collections

URL = "https://hn.algolia.com/api/v1/search_by_date" \
      "?tags=author_whoishiring,story&hitsPerPage=1000"
MONTHS = "January February March April May June July August " \
         "September October November December".split()

rows = collections.defaultdict(dict)
for h in json.load(urllib.request.urlopen(URL))["hits"]:
    t = h["title"]
    m = re.search(r"\((\w+)\s+(\d{4})\)", t)          # "(May 2018)"
    if not m or m.group(1) not in MONTHS: continue
    key = (int(m.group(2)), MONTHS.index(m.group(1)) + 1)
    low = t.lower()
    if "who is hiring" in low:        rows[key]["hiring"]  = h["num_comments"]
    elif "wants to be hired" in low: rows[key]["seeking"] = h["num_comments"]

for (y, mo), r in sorted(rows.items()):
    if "hiring" in r and "seeking" in r:
        print(f"{y}-{mo:02d}  {r['hiring']:5d}  {r['seeking']:5d} "
              f" {r['seeking'] / r['hiring']:.2f}")

num_comments counts replies too, so both threads read a bit high. The ratio is less affected than the raw counts.

all 145 paired months
monthhiringseekingratio

caveats

One forum, mostly US, mostly software, around 500 self-selected commenters a month. It is not a labor market.

Apr and May 2015 are missing because the threads were not posted; the lines span the gap. Pairs start Jul 2014, before which the seeker thread ran irregularly.

For what it is worth, this turned down in the second half of 2022. The layoffs hit the news in Jan 2023.