Gathered some stats about my recent job search.

Background and context

I am a scientist in academia with a PhD in physics. My domain is numerical modelling of quantum objects. I was looking primarily scientist openings inside and, lately, outside academia with a focus on quantum, machine learning, data science, and python software engineering. That said, I am mostly interested in quantum startups, academic software engineering companies and big software enterprises. Both on-site (the Netherlands) and remote work are in my sight.

My job seeking approach was mostly done through LinkedIn and my academic network. In addition, I was using job-seeking mentoring services offered by Delft university.

All interviews were done via video/audio calls.

Data sources and tools

Collected from my mailbox, calendar and LinkedIn chats. Processed and presented in python using pandas and matplotlib.

The data

I recovered 25 applications in total where I tracked the following 10 events:

  • Applying for the opening
  • Initial contacts by recruiters
  • “Cold” networking with employers and employees
  • Interviews
  • Re-applying for no-response or stale applications
  • Negative application outcome: reject
  • Positive application outcome: offer
  • Me accepting an offer
  • Me declining an offer
  • Ghosting from the employer side (i.e the absence of a response when I am no longer interested in the opening).

There is a small amount of applications which I was not able to track because of the absence of a feedback (for example, I applied through a web form and no confirmation email/follow-up is given). I estimate the number of such applications less than 10 for the period considered (years 2021 and 2022).

I decided to encode employers to be able to share more subjective and opinion-based information about the interview process. Accordingly, the data includes:

  • Academia (professor-level openings at universities)
  • FAANG (IT sector grands and their affiliated businesses)
  • Global businesses you may find on Wikipedia for example
  • Semi-global businesses up to few thousands international employees
  • Local Dutch businesses
  • Startups from North America
  • Local Dutch startups
  • Non-research companies where software engineers are needed
  • Stock market trading companies.

Following is the timeline of my job search with all events I was able to recover. timeline

Plotting function:

from matplotlib import pyplot
import numpy as np
from matplotlib.patches import Patch
from matplotlib.markers import MarkerStyle

def plot_timelines(groupby, ax=None, x="Date", c="Activity", sort=True,
                   legend=True, colors=None, default_color="#A0A0A0"):
    """
    Plots multiple timelines from a GroupBy object.
    
    Parameters
    ----------
    groupby
        The object to plot.
    ax
        Matplotlib axes to use.
    x
        Column name where dates can be found.
    c
        Column name to color-code.
    sort
        If True, sorts the timelines based
        on the earliest entry.
    legend
        If True, puts a legend for color-coding.
    colors
        An optional dictionary with color codes.
    default_color
        The default color for `colors`.
    """
    if ax is None:
        ax = pyplot.gca()
    
    _, sample = next(iter(groupby))
    c_dtype = sample[c].dtype
    if colors is None:
        prop_cycle = iter(pyplot.rcParams['axes.prop_cycle'])
        lookup_color = np.array([
            next(prop_cycle)["color"]
            for _ in range(len(c_dtype.categories))
        ])
    elif isinstance(colors, dict):
        lookup_color = np.full(len(c_dtype.categories), default_color)
        for k, v in colors.items():
            lookup_color[np.where(c_dtype.categories == k)] = v
    
    groupby_min = groupby[x].min()
    groupby_zipped = zip(groupby_min, groupby)
    if sort:
        groupby_zipped = sorted(groupby_zipped)
        
    ylabels = []
    for ix, (_, (label, history)) in enumerate(groupby_zipped):
        history = history.sort_values(x)
        # print(label, history)
        ax.axhline(y=ix, color="black", alpha=0.1)
        xdata = history[x].values
        cdata = lookup_color[history[c].cat.codes]
        ax.plot(xdata, [ix] * len(history), color="black")
        
        # dummy workaround for overlapping symbols (works for pairs only)
        left_half = np.concatenate([xdata[1:] == xdata[:-1], [False]])
        right_half = np.concatenate([[False], xdata[1:] == xdata[:-1]])
        neither_half = np.logical_not(np.logical_or(left_half, right_half))
        
        for mask, style in [
            (left_half, MarkerStyle('o', fillstyle='left')),
            (right_half, MarkerStyle('o', fillstyle='right')),
            (neither_half, 'o'),
        ]:
            ax.scatter(xdata[mask], [ix] * mask.sum(),
                       marker=style, color=cdata[mask], zorder=10)
        ylabels.append(label)
    ax.set_yticks(np.arange(ix + 1), labels=ylabels)
    if legend:
        ax.legend(handles=[
            Patch(facecolor=col, label=cat)
            for col, cat in zip(lookup_color, c_dtype.categories)
        ])

Raw numbers

  • Total applications: 25, including 16 own applications and 9 recruiter contacts
  • Applications with at least one interview: 14 (56%)
  • Among 16 own applications, interviewed for 6 openings (37.5%)
  • Total interview sessions: 29
  • Longest interview streak: 6 interviews
  • Mean interviews for interviewed openings: 2.1
  • Offers: 2 (8% of total applications or 14% of interviewed applications)
  • Mean application timeline: 51 days
  • Mean recruiter-initiated application timeline: 26 days

Some insights

  • It is difficult for me to maintain a large number of applications. I started seeking a new job actively in September 2021 and, since then, applied to 19 openings resulting in roughly 5 applications per month or one application per week.
  • A major reason for small application numbers are exhausting counts of interview sessions. With one application per week, I had to allocate approximately one interview slot (29 interviews per 25 applications). This is easier if you job-seeking full-time.
  • Both offers I had were from recruiters. If you do not know the details of your job seeking landscape responding to recruiters is probably a good idea. Especially if you were previously working for academia only.
  • It is relatively easy for me to get a first interview. Whether it is a thoughtful application choice or my profile, more than one third of my own applications resulted in an interview. In most cases, I also had a second interview.
  • Thus, my prospective employers need roughly two interviews to understand that I am a no-match. The second interview is typically technical-focused when they might realize that my skill set is not what they were expecting.
  • With a 14% success rate, my prospective employers were interviewing 7 persons on average. Assuming I was an average candidate.
  • I never got an interview for an academic position. Neither I had any success with FAANG.
  • Quantum startups are easy for me. They are numerous and hungry for backgrounds similar to mine.
  • It takes one-two months to complete one application. This is probably above-average for the technology sector.

Case studies

Employer titles refer to the plot above.

Local

It was a small research software company I was very familiar with. Given my familiarity, I made my bet when they announced new openings. After the first interview around September-October they ghosted. I did not expect anything from them until they popped up in December with some apologies and asking for the second interview. Weirdly, both technical interviews were rather similar in content as if they forgot that they were interviewing me earlier. In the end, they still rejected my application providing my overall background mismatch as the primary reason. I am still wondering if my CV is composed so badly that you need two interviews to figure out the basics?

Local 2

It took the prospective employer only one week and one interview session to understand that I am a no-match for them. They called me back saying that the primary reason for the rejection was an impression that I am not a team player. Lesson learned (and thank them for their honest feedback).

FAANG

A new lab in my domain was about to be opened in Amsterdam. This was a major opportunity to me which, unfortunately, did not work out. I’ve spent a whole lot of time trying to contact relevant people but, in the end, I was rejected without any particular feedback. Other FAANG companies similarly did not have any interest in my profile despite networking and referrals. I read it as my profile issue.

Startup 2

A recruiter from a North-American quantum technology startup proposed me to interview with their team. After an absolute-record six interviews they were able to send me a contractor offer. This was my first offer, yet, I declined it with very little hesitation. You may imagine how ungenerous it was. I am OK with contract work but I am not OK when it is supplemented with regular academic-level pays.

Local 3

You may imagine that there is something wrong with local Dutch businesses. Or maybe there is something wrong with my expectations from local Dutch businesses. This time, after a series of interviews I received a very embarrassing letter claiming that I am not flexible enough (in terms of my time management for their interviews). I think it was something dealing with the fact that in the middle of COVID-19 I was not very enthusiastic to show up on-site for another full-day in-person interview session. I wish their recruiter (who initiated the application) to master composing less embarrassing rejection letters.

Non-research

It was a regular no-thrill python-SQL remote job. As an academic, you will struggle even with those. What is worth noting is that interviewers (UK and India) were very friendly even when conducting interviews and in their rejection letter. In contrast to the previous case, they did their best to not ruin bridges after all.

Local startup

Three different recruiters contacted me regarding the same opening in an Amsterdam quantum startup company. I said “yes” to all of them. Two recruiters ghosted and one recruiter was able to tell me that the startup is under re-organization of some sort so they are not actually hiring right now. WTF?

Local startup 3

They asked me how old am I. Next day I realized that they were implicitly referring to a Dutch law stating a minimal salary for mid-aged professionals like myself. They were probably going to pay their future engineer less than a postdoc salary at their host university.

Trading

Their candidates are supposed to solve simple linear optimization problems using a paper and a pencil in a short time frame. In a browser-based test, you are supposed to score in the top 2%. I scored top 20%. I considered abusing their hiring tests with some sort of an advanced calculator app but desided to put it aside for the moment. The pay was nowhere near Wall street opportunities anyway.

Semi-global

It was an interview where I am supposed to present a by-heart knowledge of something that I was studying 15 years ago at the university. I should have just ignored them from the very beginning but instead I experienced a whole spectrum of feelings called “failing an oral exam”. My interviewers were speaking Russian.

Pays

This is a separate piece of data about typical pays you find in the Netherlands and abroad. Provided I am not sharing sources of this data, it should be read as my salary expectations rather than anything else. All amounts are in USD per year.

My previous work experience

  • EPFL: working as a PhD student, I earned an equivalent of 50-57k depending on the PhD year and USD/CHF exchange rate. I was earning a postdoctoral salary of 70-80k for a couple of months after defending my degree.
  • Caltech: I earned around 55k tax-free as a postdoc.
  • TU Delft: I earned around 55k (before taxes) as a postdoc.

As you can see, coming to the Netherlands significantly reduced my pay. This is very typical for those who migrate from US to Europe.

My salary expectations

Mean Amsterdam salary is close to 50k. Among expats, the average pay is higher towards 55k.

Dutch professor starts earning at about 65k. This is slightly above postdoctoral pays 50-55k. Salaries are regulated through the collective agreement which you may find online.

Finding a software engineering position for 50-70k is relatively easy, given matching experience. These are either government-funded (for example, working at the municipality) or small private companies. In either case, it is very difficult to negotiate anything above 80k at these companies. At FAANG, I expect pays starting in the range 100-120k (i.e. almost twice the lower edge). You may find more data about pays in this table; beware that it is heavily biased towards senior-level and contractor positions at international companies.

Startup compensations in the Netherlands range in 50-110k bracket. Most tend to stick to the corresponding pays in the IT sector with a slight underpay. Finding a 6-digit pay in a dutch startup tends to be a very difficult task: you have to be senior in a narrow domain with a large amount of a non-academic experience.

International quantum startups pay anything in the range 100-150k. There are catches, that may effectively reduce this amount, though. If you are focusing on remote options, as myself, you are likely to become a contract worker. You will have a much larger tax burden (for example, VAT), but also no paid holidays, insurance, etc. Without careful considerations, you may be tricked into a contract that will be equivalent to a permanent Dutch job with a twice as low compensation. Working for 90-130 USD/hour is considered normal in the IT sector, however, being offered a half of this amount is not uncommon.

Remote work for the bay area is one of viable options: the median base pay of a python software engineer there is around 165k.