Leadership

Recognition Is Not Recall: Why You Understand Code You Cannot Write

You can read a debounce, review a rate limiter and explain an LRU cache, then freeze when someone asks you to write one. That gap has a name and a fix, and the fix is not more reading. What retrieval practice is, why rereading feels better than it works, and how to build a drill that is not easier than the job.

20 Aug 2026

Recognition Is Not Recall: Why You Understand Code You Cannot Write

Somebody shares their screen and asks you to write a debounce. You have reviewed
this exact function perhaps a hundred times. You know what it does, you know the
trap with the trailing call, and you could spot a broken one in a pull request in
about four seconds.

Your hands do nothing.

The interview is not the point here. The point is that something you genuinely
know did not arrive when you reached for it, and the same gap shows up on a
Tuesday afternoon when the thing you cannot produce is a retry policy for a
service that is already down.

The gap has a name

Recognition is knowing the answer is right when you see it. Recall is
producing the answer when nothing is in front of you.

They feel like one skill. They are two, and they do not decay at the same rate.
Recognition is cheap and it lasts. Recall is expensive and it fades quietly,
because nothing in your normal week ever tests it.

Think about how you spend a working day. You read code, review pull requests,
scan documentation, accept a completion, skim a diff. Every one of those is
recognition. You are judging something already on the screen. A senior engineer
can go years doing excellent work and almost never produce a non-trivial function
from an empty file.

So the skill that decays is not the one you notice decaying.

Why reading it again does not fix it

The obvious repair is to go back over the material. Reread the article, watch the
video again. This is the most popular study method there is and it barely works.

It does something worse than not working. It feels like it is working.

Robert Bjork's work on desirable difficulties, conditions that make learning
harder now and stronger later, explains why. Rereading produces fluency. The
words go down easily, nothing snags, and you finish the page sure you have got
this. Your brain reads that smoothness as learning. It is familiarity, and
familiarity is recognition again.

Henry Roediger and Jeffrey Karpicke measured the gap in 2006. Students learned
short science passages. One group read a passage four times. The other read it
once, then spent the remaining sessions writing down everything they could
remember, with no peeking.

Five minutes later the rereaders looked like the winners, producing about 83
percent of the passage against about 71 percent.

A week later it had reversed. The rereaders were down to about 40 percent. The
group that had spent its time struggling to retrieve produced about 61 percent.

That reversal is the whole thing. The method that looked better in the room was
worse by the following week, and the students had no way of telling, because the
signal they were reading was fluency.

Retrieval, and why the schedule is the product

Retrieval practice means producing the thing from memory, with no answer
available, and finding out afterwards whether you were right. The productive part
is the struggle before the answer arrives, not the answer. Looking at a solution
and thinking "yes, that is what I would have written" teaches you almost nothing.
You did not retrieve it. You recognised it.

Timing matters as much as the act. Repeating something four times in one evening
is nearly wasted, because by the second attempt you are copying from short-term
memory, which is recognition wearing a disguise. Spaced repetition widens the
gap between attempts so each one lands where you have nearly forgotten. Nearly is
the operative word. Too soon and there is no struggle. Too late and you are
learning it again from scratch.

So a schedule is not an organiser, it is the mechanism. No human is good at
picking the gap, because the feeling of "I know this" is the exact signal that
has already been shown to be untrustworthy.

flowchart diagram: You produce it from an empty file

Neither branch is chosen by you on the day, and that is the point of it.

A drill that is not easier than the job

A drill easier than the real thing is worse than no drill, because it returns
a pass and you bank the confidence. You now believe you can produce a rate
limiter. You cannot, and you will find out in the worst available room.

Three properties keep it honest. The tests are hidden, because if you can read
the assertions you write code that satisfies the assertions, which is a much
smaller task than solving the problem. There is a clock you can exceed at a cost
rather than a lockout, because being cut off mid-thought teaches nothing. And
pasting is off, which you can defeat with developer tools if you want to; it is
there to stop a reflex, not to police you.

Then the part that takes real care. The checker judges behaviour, not one blessed
output:

Ts
// Don't
expect(order).toEqual(["clean", "lint", "compile", "test", "bundle"]);

// Do
for (const task of order) {
  for (const dep of dependsOn(task)) {
    expect(order.indexOf(dep)).toBeLessThan(order.indexOf(task));
  }
}

The first version fails a correct answer whenever two siblings could legitimately
come out in either order. That is the expensive failure. A drill that rejects
good work teaches you to write for the grader, which is a worse version of the
thing you were trying to escape.

What not to measure

Streaks and points are the easiest thing to build and the easiest thing to start
optimising by accident. A streak measures attendance. You can hold a hundred day
streak doing the same three easy problems and never once sit with something you
cannot do.

The only measurement that means anything is whether a pattern you have not seen
for three weeks comes back out of your hands when it is asked for. If you catch
yourself picking the problem you already know, you have switched from practice to
performance.

Where this stops working

Drills make your hands fast. They do not make you senior.

Nothing here helps you decide whether a queue belongs between two services, or
whether the right move is to delete the feature rather than optimise it. That
judgement comes from living with decisions long enough to see them age, and it
cannot be drilled, because the feedback loop is measured in quarters. If that is
the gap, a system design interview playbook
is closer to what you need, and
picking problems worth solving
is closer still.

What drills fix is narrow and real. They stop production from being the
bottleneck, so that when you have a design in your head and eight minutes to show
it, the mechanical part does not eat the eight minutes. The same is true of
the anti-patterns that cost you twice.

I built coding.gazar.dev for this and for nothing
else. Timed TypeScript problems, hidden tests, pasting blocked, and a schedule
that decides which one you get today. Fifteen problems, small on purpose, because
the bank is not the product. A thousand problems you attempt once are a library
rather than practice. You can open any of it without an account.

The rule I would defend in a post-mortem: if you have not produced it from an
empty file this quarter, you do not know it, you recognise it. Those are
different, and only one of them turns up when you need it.

Go further
Live cohort on Maven

Production-Ready Systems with LLMs and Agents

A live Maven cohort, 5 October to 2 November: eight 90-minute sessions where you build LLM and agent systems that survive real traffic, real cost and real failure. Tuesdays and Thursdays, 7:30 to 9:00pm London.

Cohort 2 starts 5 October. Eight live sessions, $1,500.

View the live cohort

Keep reading