Context: Searching for a new senior level software development job over a 9 week period in summer 2025.
- Focused mostly on data engineering and backend roles that are in-person or hybrid in the SF Bay Area.
- Leads from recruiters on LinkedIn were much more likely to lead to interviews+offers.
- The winning offer came through my personal network.
- I mostly used Hiring.cafe for prospecting. They’re a scraper with an interface I didn’t hate.
Hey, congratulations on the employment!
Interesting. I recently was job hunting in 2025, January to June. In US. I was looking for remote only jobs.
My stats:
- Number of jobs applied to: 53
- Number of rejections: 52
- Number of jobs that rejected me with an internal referral: 4
- Number of offers: 1
- Search duration: 24 weeks
I guess I was applying to 2.2 per week. I was also mixing in studying and preparing for interviews during that time. Still slow though.
16 applications per week. Nice! Good job!
It seems like personal networks are still, by far, the most likely way to get a job. Having an internal reference helps you bypass so many filters.
It makes sense for employers, too, because a confirmed human that really wants the job is already better than the majority of the crap they have to sift through.
man… over 400 applications, something like 5 interviews, no offers, i gave up ._. entry level is fucked
I find this kind of graph a bit misleading/ambiguous. I intuitively want to follow horizontal association between in and out. For example, Recruiter at the bottom splits into three at the bottom.
Not sure if there’s a better way to do this. Disconnect in-bar and out-bar with a condensed point/circle to indicate non-conformity?
If you know something better I’d like to give it a spin.
The better option is to keep colors from the original input stream for the flows instead of making the flows an uniform color.
In the input on the left you have pink, green and blue.
Keep these colors throughout the graph.
Except of the input, all of the other stages only ever split up and never merge, so keeping this single set of colors is enough.
The other option would be to get rid of the “leads” stage, since it actually doesn’t change any state. All the other stages are an action that happens (e.g. “Applied” changes the state of the application from being just a lead to being an open application and it also filters out data for being e.g. abandoned). But the “leads” stage means the same thing as the first stage. So drop the “leads” stage and instead make flows go from all three input stages directly into “bad lead”, “abandoned” or “applied”.
Combine both to get the best result.
Is there any site that does this?
Don’t know if there’s a ready-made site for stuff like that, but it’s not hard to do.
Here’s a quick and dirty AI generated piece of trash code as a proof of concept:
# sankey_hiring_funnel_direct.py # Requires: plotly # Install: pip install plotly import plotly.graph_objects as go # Node labels (unique) labels = [ "Network", # 0 "Hiring.cafe", # 1 "Abandoned Lead", # 2 "Applied", # 3 "Rejected", # 4 "No Response", # 5 "Screener", # 6 "Rejected by Screen", # 7 "Full Round", # 8 "Rejected by Panel", # 9 "Offer", #10 "Accepted", #11 "Declined" #12 ] # Colors for the two source groups (consistent) network_color = "rgba(31,119,180,0.8)" # blue-ish hiring_color = "rgba(255,127,14,0.8)" # orange-ish sources = [] targets = [] values = [] link_colors = [] def add_link(src_idx, tgt_idx, val, color): sources.append(src_idx) targets.append(tgt_idx) values.append(val) link_colors.append(color) # Direct flows from Network and Hiring.cafe into Abandoned Lead and Applied add_link(0, 2, 1, network_color) # Network -> Abandoned Lead (1) add_link(1, 2, 58, hiring_color) # Hiring.cafe -> Abandoned Lead (58) add_link(0, 3, 11, network_color) # Network -> Applied (11) add_link(1, 3, 70, hiring_color) # Hiring.cafe -> Applied (70) # Applied -> Rejected, No Response, Screener (split by original group) add_link(3, 4, 5, network_color) # Applied -> Rejected (network 5) add_link(3, 4, 40, hiring_color) # Applied -> Rejected (hiring 40) add_link(3, 5, 3, network_color) # Applied -> No Response (network 3) add_link(3, 5, 15, hiring_color) # Applied -> No Response (hiring 15) add_link(3, 6, 4, network_color) # Applied -> Screener (network 4) add_link(3, 6, 15, hiring_color) # Applied -> Screener (hiring 15) # Screener -> Rejected by Screen, Full Round add_link(6, 7, 1, network_color) # Screener -> Rejected by Screen (network 1) add_link(6, 7, 5, hiring_color) # Screener -> Rejected by Screen (hiring 5) add_link(6, 8, 3, network_color) # Screener -> Full Round (network 3) add_link(6, 8, 10, hiring_color) # Screener -> Full Round (hiring 10) # Full Round -> Rejected by Panel, Offer add_link(8, 9, 1, network_color) # Full Round -> Rejected by Panel (network 1) add_link(8, 9, 7, hiring_color) # Full Round -> Rejected by Panel (hiring 7) add_link(8, 10, 2, network_color) # Full Round -> Offer (network 2) add_link(8, 10, 3, hiring_color) # Full Round -> Offer (hiring 3) # Offer -> Accepted, Declined add_link(10, 11, 1, network_color) # Offer -> Accepted (network 1) add_link(10, 12, 1, network_color) # Offer -> Declined (network 1) add_link(10, 12, 3, hiring_color) # Offer -> Declined (hiring 3) # Sanity check assert len(sources) == len(targets) == len(values) == len(link_colors) # Node colors (visual guidance) node_colors = [ "rgba(31,119,180,0.9)", # Network "rgba(255,127,14,0.9)", # Hiring.cafe "rgba(220,220,220,0.9)", # Abandoned Lead "rgba(200,200,200,0.9)", # Applied "rgba(220,180,180,0.9)", # Rejected "rgba(200,200,220,0.9)", # No Response "rgba(200,220,200,0.9)", # Screener "rgba(255,200,200,0.9)", # Rejected by Screen "rgba(210,210,255,0.9)", # Full Round "rgba(240,200,220,0.9)", # Rejected by Panel "rgba(200,255,200,0.9)", # Offer "rgba(140,255,140,0.9)", # Accepted "rgba(255,140,140,0.9)" # Declined ] fig = go.Figure(data=[go.Sankey( node=dict( pad=18, thickness=18, line=dict(color="black", width=0.5), label=labels, color=node_colors ), link=dict( source=sources, target=targets, value=values, color=link_colors, hovertemplate='%{source.label} → %{target.label}: %{value}<extra></extra>' ) )]) fig.update_layout( title_text="Hiring funnel Sankey — direct source flows (no Leads node)", font_size=12, height=700, margin=dict(l=20, r=20, t=60, b=20) ) fig.show() # To save as interactive HTML: # fig.write_html("sankey_hiring_funnel_direct.html", include_plotlyjs='cdn')
Couldn’t be bothered to write this by hand for just an online comment. There’s enough that can be improved with this, but I think it’s ok to show how it can be done quite easily.
i feel like that half of them did not even reply is like kind of really bad and if feels like these werent like real listings to begin with? I dont know but it feels and sounds incredible rude and unprofessional to not reply to all applications. Exspecially since it should just be an automated process, so it feels fishy when companies dont even do that.
We get 100s of automated applications per day for a position we recently opened. 99% are automated and no where near meeting the requirements. We try to give everyone a review and a reply but it is a massive task, unfortunately. We do not have dedicated personel to handle these matters so it costs engineering time. The current situation for online software dev job application sucks for everyone.
I guess what I am trying to say is: If you don’t get a reply to an application it is likely because you are drowning in noise and someone at the other end is struggling to keep up.
Interesting breakdown. Its a hard market.
My last Two jobs were both referrals.
Tell me about it. Took me 3x as many applications to land two interviews, and I wasn’t even looking for a specific field. My only requirement was $20/hr or more, the bare minimum needed to survive.
Finally settled on a $19/hr job after a six month struggle. I can’t afford groceries but at least I won’t go homeless.
Is the SF Bay Area still the place to be? It looks kinda cursed lately.
Nobody goes there anymore. It’s too crowded.
deleted by creator
@deegeese you applied 151 times? Are you in the USA? At least me in Europe / France / Paris, I do not apply more than three per round
Really depends.
I am in belgium and for Electronics engineering, there are very few jobs and a lot of candidates (and notoriously difficult to get around via car in belgium). I have 5 year of experience, recommendation letters, and good references.
20 applications. 9 ghosted, 4 auto rejections, 2 declined by me as not a good job, 1 rejection after hiring manager interview (too far, 1.5+ hour one way in traffic and they had closer candidates just as good), 2 rejections after final interview (one ghosted, the other wanted to take both me and the other candidate on, but couldn’t), 2 offers.
It is definitely rough in the engineering industry outside of defense.
On the flip side, I see hundreds of software jobs here and hundreds of electrical/building automation jobs.
If half of your applications never reply even to reject, when is the next round? Need more activity to keep your pipeline full.
I generally didn’t have more than 3 or so going on at once in the later stages.
I guess the approach is different.
I do 1-3 high quality applications and get invites to an in person meeting for all of them. Often times getting an offer from all as well and then I decide. Each one takes about 3-5 days in total including research on the company, completely custom cover letter, proof reading, getting feedback from friends that work in the field, and hand picked example code projects from my repo or even throwing together a quick prototype related to the job offer. Been doing it this way for 12 years.
If you do a shotgun approach with 160 low quality ones then it doesn’t surprise me that half don’t reply.
If I did 160 applications the way I usually do them, I would literally be writing them for nearly 2 (two!) years… thats the only reason I assume yours are low quality.
How old are you and when was the last time you looked for a job?
Been doing it this way for 12 years.
you can guess from this.
Last time was this year.
This sounds to me like we need to move to Germany. It’s not uncommon for people in the US to apply to hundreds, or even thousands, of jobs and get a single-digit number of interviews (or offers, in industries where interviewing is uncommon) out of it, regardless of effort put into the application. Most applications are rejected before a human ever reads them.
To be fair, I only worked at small/medium companies ( <100 people ) and a quarter of the time I had a contact there from some networking event.
That’s an entirely different situation then. That’s just the power of networking
Networking is 100% the easiest way to get a job. The people that have networking don’t need advice. 99% of the job hunting advice is with the assumption you don’t have a network you can rely on for finding jobs. Because if you did, you wouldn’t be having trouble finding a job
a quarter of the time
I’m pretty sure some places would just skip over your application (with some probability) because the sheer amount of applications they receive
My friend who works in marketing usually try to find out the hiring manager and also emailed them directly while also providing something similar to the commenter above (3-month marketing and content plan instead of a sample project) and it’s basically 100% success rate for getting a response for him.
Oh yes.
As the old joke goes:
“Well, we don’t want our future employee to be unlucky… *grabs half of the printed applications and tosses them in the trash*”
@deegeese it was a while back before covid, and stuff, And it rarely bounce at the first round, but I target precisely each email. Head hunters help too.
Beautiful graph. Good luck pal.
It only takes 1 opportunity to change your life.
For better or worse