Every developer job hunt I've watched up close starts with the same artifact: a clean Google Sheet. Company, role, link, date applied, status column with a dropdown. Maybe some conditional formatting if you're feeling fancy. By week three it's a graveyard of stale rows nobody has touched since the day they were created.
I build career tooling for a living, so I've seen a lot of these sheets. Mine included. I ran one during my own last hunt and it failed me in exactly the ways I'm about to describe. The problem isn't discipline. The problem is that a spreadsheet is structurally the wrong tool for the job, and it fails in a way that costs you interviews without ever telling you it's failing.
A spreadsheet is a log. A job hunt needs a queue.
Here's the core defect: a spreadsheet answers "what did I do?" A job hunt runs on "what do I do today?"
Those are different data structures. A log is append-mostly. You add a row when you apply, you update a cell when something happens. Nothing in it ever demands your attention. A queue surfaces the next action and its deadline whether you feel like looking or not.
So the follow-up email you meant to send five days after applying? It lives in your head, not in the sheet. The recruiter screen you should confirm? Same. The sheet records that you applied to 34 companies. It stays completely silent about the six of them where a two-line follow-up this week would actually move the needle.
Half of "I got ghosted" is you ghosting them
Developers talk about ghosting like it's something companies do to candidates. Having sat on both sides, I'll say the uncomfortable part: a lot of it runs the other way.
A recruiter replies Tuesday afternoon. You see it Thursday because it landed in a tab you don't check. You answer Friday evening. By Monday they've scheduled three other people, and your thread quietly dies. From your side it looks like ghosting. From their side, you were the slow one.
When I've hired, the candidates who made it to interviews came overwhelmingly from the first few days after the posting went live. That's not a policy anyone writes down. It's just how pipelines work: once a hiring manager has four promising screens booked, application number 80 on day 19 gets a skim at best. Your spreadsheet doesn't capture any of this timing. "Applied: Oct 14" tells you nothing about whether you applied on day one of the posting or day twenty, and that single fact predicts more than almost anything else in the row.
What a job application tracker actually has to store
Strip away the tooling debate and the requirements are short. If your tracker can't answer these four questions instantly, it's decorative:
- What's my next action for each live application, and when is it due?
- What did the posting actually say? (Postings get pulled. If you land an interview three weeks later, you'll want the exact text you applied against.)
- Which resume version did I send? The interviewer has it in front of them. You should too.
- How long did each application sit between "found it" and "applied"?
As a data model, it looks like this:
type Application = {
company: string;
role: string;
postingUrl: string;
postingText: string; // save the full text; the URL will 404 eventually
resumeSent: string; // the exact PDF you submitted, not "resume_final_v3"
status: "found" | "applied" | "screen" | "interview" | "offer" | "closed";
statusHistory: { status: string; at: Date }[]; // timestamps, not one mutable cell
nextAction: string; // "follow up with recruiter", "send thank-you note"
nextActionDate: Date; // the field your spreadsheet doesn't have
};
Notice what's absent from the typical sheet: statusHistory, nextActionDate, and postingText. Those three fields are the whole game. A single mutable "status" cell destroys the timing data you'd need to see that, say, every application you sent within 48 hours of posting got a reply and nothing older did. That pattern is invisible in a flat sheet, and it's the most useful thing your own hunt can teach you.
One side note on resumeSent: store the actual PDF you submitted, and submit PDF by default. It renders identically everywhere, which is exactly what you want when a hiring manager opens it on a machine you don't control.
The number your sheet hides: time from found to applied
Once you timestamp "found" separately from "applied", an ugly gap shows up for most people. The posting sat in a tab for four days. Why? Usually because applying properly meant tailoring the resume, and tailoring a resume by hand takes an evening you didn't have.
So you face the classic trade: send the generic resume fast and get filtered by the applicant tracking system (ATS) and the recruiter skim, or tailor it properly and apply on day five, after the pipeline already has its shortlist. Both options lose, just at different stages.
This is the exact problem I started Roleframe to fix, so I'm biased, but the premise is the same one this whole post argues: paste the posting, get a resume tailored to it in seconds instead of an evening, and track the application in the same place so the follow-up date exists somewhere other than your memory. Tailored and early stops being a trade-off. Discount my opinion accordingly and check the reasoning yourself.
If you keep the spreadsheet anyway
Fair enough. Spreadsheets are free and you already have one. Then make these changes tonight, because they fix the worst of it:
- Add
next_actionandnext_action_datecolumns. Sort the sheet by that date every morning. This single habit converts your log into a crude queue. - Add a
found_datecolumn next toapplied_date. Watch the gap between them. If it's regularly more than a day or two, that gap is where your interviews are leaking. - Paste the full posting text into a notes cell the moment you find the job. Thirty seconds now saves you a dead link before the interview.
- Record the exact PDF filename you sent per application, and keep those files.
- Every Sunday, close out dead rows honestly. A sheet full of zombie "applied" statuses makes you feel busy and tells you nothing.
That setup holds together up to maybe 15 or 20 live applications. Past that, in my experience, the manual sorting ritual is the first thing to go, and once it goes you're back to a log.
The deeper point stands regardless of tooling. A job hunt is a pipeline with time-sensitive state, and most rejections-by-silence aren't mysteries. They're missed follow-ups and late applications that no row in a sheet ever flagged.
What does your setup look like, and what broke first? I've heard everything from Notion boards to a Kanban of email labels to one person running theirs in a Postgres instance. Genuinely curious what survives contact with week three.

Top comments (0)