The Principal IC Moat
The Goal
This started as a simple job search. One I didn't think should last long.
Twenty years as an engineer and architect in a highly regulated enterprise. Much of it as a full-stack developer in an industry allergic to them. Promoted for judgment, but held back by a lack of consistent formal authority. Useful, but underused in ways only people who have spent real time inside regulated industries can imagine.
What I didn't know going in: that long tenure, that deep understanding of a complex domain, often gets read as a strike against you. Especially from the middle of Kansas.
The Unintended Moat
After a few hundred listings, a pattern emerged.
Companies write Principal IC job descriptions that mix stack requirements, wishful leadership language, inherited organizational pain, and vague transformation goals until the actual work disappears. They attach titles that mean different things at every company. Then they screen by resume pattern-match against the very title and description they just made up. Dogfooding in reverse?
That isn't a filter for Principal-level judgment. It's a filter for resemblance to one snapshot in an ever-changing industry.
In 2026, a job description may say "Principal Engineer," but the content might look like any of the following:
- A hands-on senior engineer who still ships features
- A platform strategist expected to set direction
- A technical executive without authority
- A political consensus-builder
- A vendor evaluator
- A traveling salesman
What the hiring manager actually wants to buy is judgment. Judgment is hard to specify. So they reach for what they can see: title, logos, years, stack, scope, artifacts, interview fluency.
That's the moat. It isn't malicious, just what happens when you try to write a spec for something that resists being specified.
The Diagnostic
I quickly realized that one's resume, a document that once needed a bit of polishing now and then, had become a living artifact. A precision instrument whose only job is to get past a gauntlet of overworked humans, their software, their AI assistants, and the inboxes of hiring managers who get 50 more important emails per day.
What goes on a resume is no longer just the list of things you're best at, your expertise and biggest career achievements. Now it could also be anything you've been near that improves the odds of getting through that arbitrary gate. In the workplace, people attach their names to things they never intend to meaningfully participate in, just so they can tell themselves the bullet point is earned. On the receiving end, this means interviewing people who lack the exact thing you're looking for: sound judgment, decision ownership, and respect among both developers and executives, earned for the right reasons.
Unfortunately, this audition feels like it violates a core belief for some of us. So we "cope" in a few ways. I decided to build a few things.
What I Built
I'm not going to walk through the full implementation. What matters is the shape of the problem.
Embeddings alone overweighted vocabulary. They'd rank "Principal Engineer who runs Jira" right next to "Principal Engineer who ships," because the words match. Claude alone could read through the vocabulary on any single listing, but reading isn't ranking. Score a field of candidates one at a time with no shared baseline and the scores drift. Neither approach, on its own, could hold a stable line between resemblance and seniority.
What worked was running them against each other. Three retrieval strategies, same corpus, and the disagreements became the signal.
Embeddings only. MiniLM, vector cosine, no LLM in the loop. Fast, free to run, scales to thousands of listings. Good at "find postings that read like this one." Blind to whether the role is actually senior or just uses senior-sounding words.
Full Claude batch. Every listing and every resume read by Claude with a structured rubric: autonomy, scope, decision authority, hands-on vs. coordinating. Title and seniority language stripped before the model sees it. Expensive and slow, but it reads through the vocabulary in a way embeddings can't.
Hybrid. Embeddings on the listing side, Claude on the resume side. That imbalance is the point. Listings are noisy and abundant. You don't need precision on every one, you need a fast filter. Resumes are few and precious. That's where the Claude budget pays off. It's also where the disagreement lives. When the embedding rank and the Claude score split on the same candidate against the same listing, the gap is usually pointing at something real: vocabulary cosplay on one side, hidden judgment on the other.
Written in Go. Runs locally. Every pass versioned so I can rerun any mode against any snapshot.
The other move that mattered: forcing the role categories to come out of the data instead of me putting them there. Strip seniority and focus language, cluster what's left, and see what the postings actually want.
Across 555 listings, 45 carried the title "Principal Engineer." The model split them: 31 landed in Staff / Principal SWE, 12 in Principal SA, Enterprise. Two didn't cluster at all. The title isn't doing the work. The cluster is.
The clusters that emerged:
- Field CTO
- Staff / Principal SWE
- Staff ML
- Staff DevRel
- CTO / VP Engineering
- Principal SA, Enterprise
Six shapes, hiding behind the same handful of titles. The moat made visible.
Closing
Early on, my own system told me I was a strong fit for Anthropic. Top of the ranked list, across every cut. I was immediately certain that wasn't success. I'd been learning about Claude, MCP, vectors, rerankers, and agents for weeks. The embedding was measuring basic overlap with what I'd recently been talking about, not fit.
That moment was more useful than any positive result. It told me what I was actually building: not a search system, a measurement instrument that had to be calibrated against its own biases before it could say anything true.
Of the 555 listings looked at so far, all but one embedded cleanly. The failure: "Member of Technical Staff, Field Eng", which runs 5,526 chars, over MiniLM's 512-token limit. The canonical IC role was too long to fit in the model.
The unintended consequence of hiring for legibility is that the people most capable of doing Principal IC work are also among the most likely to spot that it doesn't add up and opt out. They read the description, and all they see is another potential for impossible scope, unclear authority, mismatched title, and generic leadership language.
Some of them route around it, some of them turn their own job hunt into a Go codebase.
-- Justin Higgins. Software Engineer, Midwest. Spent six months job-hunting and built a search engine instead.
Reactions, disagreements, war stories: jchigg2000.dev@gmail.com