A resume gets read twice, by two very different readers.
The first read is a screen. In TheLadders' eye-tracking study, recruiters spent about six seconds on a resume before a fit or no-fit decision, and most of that time went to six fields: name, current title and company, previous title and company, dates, and education (TheLadders, 2012). That study had thirty recruiters and was run by a company that sells resume rewrites, so I hold the exact number loosely. The shape of the finding matches every recruiter I have talked to.
The second read is an interview. Someone who has done the work picks a bullet and asks, "How did you measure that?" That read takes an hour, and it is where weak numbers die.
Most resume advice is written for the first read. This post is about the second. I rewrote my resume this month, and I treated it the way I treat a dataset I am about to publish: every claim is a row, and every row needs provenance.
A bullet is a claim with a missing lineage#
In a warehouse, a number on a dashboard is only as good as its lineage. Where did it come from? What was the baseline? Over what window? Did anything upstream change?
A resume number has the same questions, and one more that warehouses never ask: was it mine? "Cut review cycles 20%" invites four follow-ups:
- Measured how, and against what baseline?
- Over what period, and on how many reviews?
- What did you do, as opposed to the team or the platform?
- Would the person who owned the metric agree?
If I cannot answer all four in a sentence each, the number is not ready to ship. It is an untested model in production.
The audit#
So I ran an audit. I put every number on the old resume into a table with four columns: the claim, where it sits, the risk if someone probes it, and what to do. Most rows were fine. They had a clear baseline and I could tell the measurement story.
Two rows did not pass.
One number described a system I worked in, not the part I owned. It was a real figure for the client's whole platform. My pipelines were a part of that platform, and the bullet read as if the whole volume was mine. It was the most impressive number on the page, and it was the one most likely to end an interview. I removed it.
The other named the wrong mechanism for a real result. The speed-up happened, but the work behind it was ordinary: partitioning, file layout and rewritten SQL. The bullet named something more exotic. A specific, ordinary mechanism is more convincing than an exotic, vague one, because every part of it survives a follow-up. The bullet now names what I did.
Neither fix made the resume weaker. Each one removed a question I could not answer and left questions I am glad to get.
The missing column was scope#
The audit found a second problem, and it was bigger than any single number. Almost no bullet said how much was mine.
"Architected" could mean I did it alone, or that I sat beside a staff engineer who did. A reader cannot tell. Seniority is not read from tools. It is read from scope, ownership and the decisions you were trusted to make. Will Larson's Staff archetypes defines the role through "your behaviors, your impact, and the organization's recognition", and Dropbox's updated career framework names "ownership over code, processes, and operational systems" as an expectation (Dropbox, 2023). Neither mentions a tool list.
The verbs carry most of it. Building verbs say what you touched. Ownership verbs say what you answered for.
| Building verb | Ownership verb |
|---|---|
| Built, developed, created | Own, run, answer for |
| Established standards | Set the standard and enforced it in CI |
| Helped with adoption | Drove adoption across N engineers |
Here is one bullet before and after. The facts are the same. The verb and the constraint are sharper.
- Own the BCDA/FHIR claims ingestion pipelines (PySpark, Delta Lake, dbt), with idempotent, retry-safe loads under a zero data-loss SLA.
+ Own the BCDA/FHIR claims ingestion path (PySpark, Delta Lake, dbt) under a zero data-loss (RPO 0) contract, with idempotent, replay-safe loads that retry without duplicating records.
"Zero data-loss SLA" and "RPO 0" are the same promise. The second is the term a platform interviewer recognises at once, and it pairs with the failover bullet further down. And "replay-safe loads that retry without duplicating records" says what idempotent means here, so the reader does not have to take the word on trust.
A standard is the same story:
- Set the dbt governance standard (tests, docs, lineage, CI checks) for the analytics layer, so non-platform engineers can change downstream models safely.
+ Set the dbt governance standard (tests, docs, lineage) and enforced it with CI checks, so engineers outside the platform team change downstream models safely.
A standard in a wiki and a standard in CI are different jobs. Only the second one can block a merge, and that is the part that tells a reader you had the authority to set it.
A public copy and a private copy#
A personal site adds a constraint a PDF does not have. A PDF goes to one reader. A web page goes to everyone, forever, including a current employer.
So my resume has two copies. The master copy holds every number I can defend. The public copy, the one on this site, holds only the numbers I have cleared for public view, and a note at the top of its source file lists them by name. Everything else is reworded in general form ("from hours to minutes") or left out.
This is not a new idea. Google's own interns gave the same advice in 2015: "Use metrics and tangible facts (but respect confidentiality)", and "a safe bet is to use percentages rather than absolute numbers" (Google Students blog). A percentage says the work mattered without saying how big the employer's book is.
A rule in a README is not a control#
I learned in another project that prose in a README does not prevent anything and a check in CI does. So the public copy is guarded by the build.
This site is a small Rust static site generator, and build runs a content check before it writes a page. The check is a list of patterns, each with a reason. A match anywhere in published text fails the build:
/// (pattern, reason). A match anywhere in published text fails the check.
const RULES: & = &;
The real list covers internal system names, figures I have not cleared, private network addresses, local file paths and links to private repositories. It reads the resume file too, minus its internal notes. If a number I have not cleared ever lands in the public copy, by my hand or by a tool's, the site does not deploy.
The rule for AI help#
I used an AI assistant for parts of this rewrite, and it is good at it. It is also very willing to "add a metric" when a bullet has none, and that is exactly the failure this whole exercise exists to prevent.
So it works under one rule: it never adds a number, title, team size, date or outcome that I did not state. Where a bullet needs a number I have not given, it writes <N> and asks me. A bullet with no number is better than a bullet with an invented one, because the invented one will be the bullet the interviewer picks.
The same rule is why some of my bullets have no number at all:
- Run multi-cloud ingestion across Azure and AWS with automated failover.
+ Run ingestion across Azure and AWS with automated failover between the two clouds.
I could make that bullet louder with a percentage. I do not have one I can defend in public, so it stays quiet.
What I took from it#
- Read every number as a row with lineage: baseline, window, measurement, and whose it was.
- Remove a number you cannot defend in one sentence, however good it looks.
- Name the ordinary mechanism. It survives the follow-up and the exotic one does not.
- Say what you owned and what you enforced. Tools are table stakes.
- Keep a private copy and a public copy, and let a check, not your memory, keep them apart.
- If a tool helps you write, forbid it from inventing facts, and make it ask.
The resume this produced is on this site. It has fewer numbers than the old one, and I can talk about every one of them for as long as anyone wants.