I applied to Adobe in March from my phone, in a pharmacy queue, using the same résumé I had sent to eleven other companies that month. I had been a full-stack engineer for a little over five years at a mid-size SaaS company, mostly on the editor side of a collaborative document product. I was three months into a very disciplined, very wrong preparation plan: 40 minutes of algorithms before work, 90 after, a spreadsheet with a red-yellow-green column for problem patterns.
I ended up with an offer for a mid-level product engineering role. I also came within one round of not getting it, and that round had nothing to do with the spreadsheet.
How I got the interview
The pharmacy-queue application did nothing for six weeks. What moved it was boring: I found an engineer on the team through a former colleague, sent one short message naming the product surface I wanted to work on and one thing I had built adjacent to it, and asked if a referral was reasonable. She said yes. Nine days later I had a recruiter email.
I spent 90% of my energy on the interview and 10% on getting the interview. The ratio should have been closer to 70/30. My cold application sat in a queue at a company with roughly 30,000 employees; the referral skipped no evaluation step, but it got a human to open the file.
The recruiter screen, 30 minutes, early April
Standard, but not throwaway. She asked what work I wanted next, then asked two questions I did not expect from a recruiter:
- "What's a product you use every day where you have an opinion about a specific design decision?"
- "Tell me one thing you built where you'd make a different call today."
I answered the first well, because I did have an opinion about a text editor's undo stack. I answered the second badly — something about "wishing we'd written more tests," which is the interview equivalent of saying your greatest weakness is caring too much. She wrote something down. I noticed her write something down.
She also gave me the loop shape and named the rounds: a technical screen, then a coding round, a deep dive on prior work, a design round, and the hiring manager. Four to six weeks from screen to decision. Mine took five.
The technical screen, one hour, mid-April
A shared editor with an engineer from a neighboring team, and the first sign my prep was misaimed. I had done timed runs on PhantomCodeAI beforehand, all of them on algorithm problems, which was the wrong rehearsal for what I got.
The archetype: parse a small structured input format, normalize it into an in-memory representation, answer a couple of queries against it. Then extend it. Then handle malformed input I had not considered.
Nothing about it was hard in the LeetCode sense. No clever insight to find. It tested whether I could write code another person would maintain: sensible names, a data structure chosen for the queries rather than for showing off, error handling that failed loudly instead of silently returning an empty result.
I passed, but noticed two things afterward. I had spent the opening four minutes silently typing, because that was the muscle I had trained. And when he asked me to extend the code, my original design fought me, because I had optimized for the first requirement instead of the shape of the problem. He did not ding me out loud, but I heard it in the follow-up: "If you'd known this was coming, what would you have done differently at the start?"
That question, in various clothing, turned out to be the whole loop.
The onsite: four rounds, split across two days
My onsite ran in two blocks because of a scheduling conflict on their side — two rounds on a Thursday, the last two the following Tuesday. That five-day gap is the only reason I have an offer.
Round 1: coding, 55 minutes
A practical problem with product framing. The archetype: given a stream of user actions, maintain a derived view that answers a specific question cheaply, then support undoing the last N actions.
The undo part is where it got interesting. My first design recomputed the view from scratch, which is correct and slow. The interviewer let me finish, then asked what happens when N is large and the log is long. I talked through an inverse operation per action versus snapshotting every K actions, picked snapshots plus replay because one action type's inverse was ambiguous, and said out loud that this trades memory for simplicity. He seemed happier with the reasoning than the code.
That, I now think, is the point of the round. I also wrote three test cases unprompted, and he said "good" at the empty-log one.
Round 2: the deep dive on past work, 50 minutes — the round that nearly ended it
This is where I fell apart.
The prompt was simple: "Pick something you built in the last two years and walk me through it." I picked the autosave and version history system from our editor. Good project. Terrible execution.
What I delivered was a tour. Here was the client, here was the queue, here was the storage layer, here is how conflict resolution worked, and by the way it handled a few thousand concurrent documents. Chronological. Architecture-diagram-shaped. A conference talk.
He kept pulling me off the tour with questions I could not answer well:
- "Why debounce on a timer instead of on semantic boundaries?"
- "What did you give up by writing the whole document instead of a delta?"
- "Who complained first when it went out, and what did they complain about?"
- "What did you measure before you decided that was the right tradeoff?"
I had answers for two of the four, and those were retrofitted. The honest truth: some of those decisions were made by a tech lead in a meeting I attended and did not push back in, and I had never reconstructed the reasoning. So I did the worst possible thing. I smoothed over the gaps. I said "we decided" a lot. When he asked what I would do differently, I said something about testing again, and heard how thin it sounded on the way out of my mouth.
Forty minutes in he stopped following up and started explaining how his team handles a similar problem, which was pleasant, and which I read — correctly — as him being finished evaluating me.
I got out of that call and knew. Not "that could have gone better." Knew.
The five days in between
I had a weekend and three evenings. I did not open a single algorithm problem. I did two things.
First, I wrote what I now call a decision log for three projects. One page each, rigid format on purpose: the decision, the two alternatives I did not take, the specific reason, the cost I paid, the thing I measured, and what I would change now. Three to five decisions per project. When I could not fill a row honestly, I went and found out — an old design doc, a Slack thread from fourteen months earlier, two dashboard charts so I would have numbers instead of adjectives. The autosave project took four hours, half of it spent discovering I had never actually understood one of the tradeoffs.
Second, I ran four mock loops on PhantomCodeAI focused entirely on that one round type. The transcripts made the pattern embarrassingly clear: in the opening minutes of every answer I narrated chronology — "so first we built X, then we noticed Y" — instead of leading with the decision and its cost. Over two minutes, on average, before I said anything an interviewer could evaluate. By the fourth run I opened with a sentence shaped like "the interesting decision here was A versus B, we picked A, and it cost us C."
Small change. Worth the entire loop.
Round 3: design and architecture, 60 minutes
Product-shaped, not infrastructure-shaped. Not "design a URL shortener," but: design the offline behavior and sync model for an editing tool where users expect their work to survive a laptop lid closing mid-sentence. Two things differed from the FAANG-style system design I had been drilling.
The constraints were about user experience, not throughput. The follow-ups: "what does the user see while this is reconciling," "what if two devices disagree and one is the user's phone," "which failure modes are acceptable to ship with." Nobody asked for queries per second. When I brought up capacity numbers unprompted, she let me talk for ninety seconds and steered back to conflict semantics.
Scoping was tested explicitly. Around minute 40: "You have one engineer and six weeks. What's in v1?" I cut offline-first, kept crash recovery from a local buffer, and made v1 sync last-writer-wins with a visible conflict banner, because a wrong silent merge is worse than an honest ugly one. She pushed on whether the banner was a cop-out. I said it was, that the cop-out was right for six weeks, and that I would want telemetry on how often it fired before deciding whether v2 needed real merging.
That is the moment the loop turned. It stopped being an evaluation and became two people arguing about a product decision. I chose to keep arguing rather than agree with her, which I would not have had the nerve to do a month earlier.
Round 4: the hiring manager, 50 minutes
Barely technical, and it counted a lot.
He asked what I wanted to be doing in two years, what feedback I take badly, and what I would do if a designer and I disagreed about whether a feature was ready. Then he gave me a real situation from his team — a feature shipping with a known rough edge — and asked what I would cut, keep, or delay.
I used the decision-log habit without planning to. Instead of a general philosophy, I named which thing I would cut, why the cut was cheap, and what I would measure after shipping to know if it was wrong. He argued with one of my choices. I held two points, conceded the third, and said why.
Near the end: "What's something we're doing that you'd push back on?" Worth preparing for. I named a specific behavior in the product I use, said why it was the wrong default, then said what I would need to know before trusting that opinion. He laughed and said half his team agreed with me.
Then he asked what questions I had, and I had six written down. That is not a personality trait, it is preparation, and it is the cheapest signal you can buy.
The wait, and the call
Eleven days of nothing. I refreshed my email like a person with a problem. On day eight I sent the recruiter one short, non-needy note asking if she needed anything else, which is the maximum acceptable amount of chasing.
The call came on a Friday afternoon. Offer for the mid-level product engineering role, on the team I had spoken to, with the hiring manager I had argued with.
The debrief detail I think about often: the deep dive went in as the weakest signal in my loop, and the design and hiring manager rounds carried it. If those two had been on the same Thursday as the deep dive, I would not be writing this.
The negotiation
I am not going to publish numbers. They would be stale by the time you read this, and one data point from one person's loop is worse than no data. The shape of what I asked for does transfer:
- The band, and where I sat in it. Not "can you do better," but "what's the range for this level and location, where in it is this offer, and what specifically would move it?" Far more useful than a vague push.
- One other process at a late stage, mentioned once, factually. No bluffing about offers I did not have. Recruiters at this scale talk to a lot of people and they can smell it.
- The start date. Three extra weeks, granted immediately, the easiest thing I asked for.
- What my first project would be, in writing. Not contractual, just clarity. The answer was specific, which told me the team had thought about the headcount rather than opening a req out of habit.
One component moved. The others did not. Normal outcome, and it took a few days to stop feeling like I should have squeezed harder.
The two-week plan I would run again
With fourteen days, this is exactly how I would spend them. Note how little of it is code.
Days 1–3: decision logs. Three projects, one page each, the format above. If a row is empty, go find the answer in old design docs, tickets, and dashboards. Attach at least one real number per project. Highest-leverage item on the list, and almost nobody does it.
Day 4: rehearse the openings. For each of the twelve or so decisions in those logs, say the first sentence out loud until it leads with the tradeoff instead of the timeline. Record yourself. Unpleasant. Do it anyway.
Days 5–7: practical coding, in a real editor, no puzzle grinding. Pick problems with a second and third requirement bolted on after you finish. Write the tests. Name things properly. If your prep lives entirely on a platform that grades hidden test cases, you are training the wrong reflex — the senior engineering guide and the full-stack breakdown go deeper on the extend-your-own-code pattern.
Days 8–10: product-shaped design. Take three tools you use and design a hard sub-feature of each: undo across a network boundary, offline editing, versioning, permissions on shared assets. Answer "what's in v1 with one engineer and six weeks" and "what does the user see when it goes wrong." Skip the capacity math. It is not where this round lives.
Day 11: the manager round. Write out: why this team, what you want in two years, a disagreement you lost and what you did after, one thing about the product you would push back on. Then write your six questions.
Days 12–13: two full mock loops, back to back. I ran mine on PhantomCodeAI because I needed the transcript more than a friendly opinion, and what I was checking was whether I still drifted into chronology under pressure. Do at least one run tired and slightly annoyed, because that is the state you will be in by round four.
Day 14: nothing. Reread the decision logs. Sleep.
What I would tell myself in March
The three months of algorithm grinding were not wasted, exactly. They made the coding rounds feel calm, and calm is worth a lot. But they were badly proportioned. My loop rewarded depth on one system I had actually built and the ability to defend a product decision under mild disagreement, and I had spent almost no time on either.
If you have been training for the FAANG pattern and you are about to interview somewhere that lives or dies on product craft, the adjustment is not more preparation. It is different preparation, aimed at the part of your experience you have never had to explain to a stranger who is allowed to keep asking why.
Go write the decision log first. That is the whole lesson, and it took nearly losing an offer to learn it.