How fruit flies track smell: a search algorithm in 2 numbers
Fruit flies find odor sources by remembering one angle, not by reflex. It's a lesson in cheap state for anyone writing search or retry loops on a small budget.

How fruit flies track smell turns out to be a storage problem, not a reflex problem. A team at Rockefeller University put flies on a tiny treadmill, fed them a fake odor world, and found the insects were steering toward a remembered position after the smell had already vanished.
I'm writing about this because the result is a clean piece of algorithm design done by evolution, and the shape of it is directly useful if you write search, crawl, or retry loops. Full credit to the reporting: Ars Technica's write-up by Jacek Krywko covers the study, published in Nature (DOI 10.1038/s41586-026-10827-7).
🪰 The old model was a reflex. This one has a goal.
For decades the standard explanation was surge and cast: smell something, fly straight upwind; lose it, sweep side to side until you catch it again. No memory, no state, just wiring.
The Rockefeller team, led by neuroscientist Vanessa Ruta, tested that directly. They tethered a Drosophila over a ball floating on air, in complete darkness. Ruta calls it a fly-sized treadmill. As the fly walked, its turns rotated a nozzle so the wind always seemed to come from a fixed direction, and apple cider vinegar was switched into the airstream based on where the fly "was" in a virtual field.
In a straight vinegar corridor about 50 millimetres wide, the flies did not march up the middle. They hugged one edge: cross in, immediately whip back out, loop through clean air, then beeline back to the boundary. The team named it edge tracking.
| Surge and cast (old model) | Edge tracking (observed) | |
|---|---|---|
| Trigger | odor present or absent | crossing the odor boundary |
| Inside the plume | fly straight upwind | turn around and leave |
| Outside the plume | cast side to side | beeline back to a remembered point |
| State stored | none | wind heading + last entry angle |
| Gradient needed | assumed | no; worked with the gradient reversed |
Two controls make this hard to argue with. Reversing the gradient, so the vinegar got fainter as the fly advanced, did not stop edge tracking. And when flies engineered so light could fire their olfactory neurons were given a beam of 660-nanometre red light instead of vinegar, they tracked the edge of the light plume just as well. Whatever the fly is following, it isn't concentration.
Flies spend more time outside the plume than inside it, yet nearly all their forward progress happens during those brief dips into the scent. Ruta says they will track meters along an edge and never cross over.
🧠 Two numbers and a two-state loop
Imaging the brain while flies tracked, the team found the machinery split into two parts:
- A compass in the central complex, locked to the wind direction and indifferent to whether the fly was in odor or out. Silence those neurons and the flies got lost, drifting upwind with no way back.
- A goal pointer in the fan-shaped body, a structure already known to encode where a fly wants to go. Out in clean air, this pointer swung away from the compass to aim at the plume's edge, several seconds before the fly physically turned around.
That gap between the pointer moving and the body turning is the part I find convincing. The decision is made in stored coordinates, then executed.
Their simulation compressed the whole behaviour into a two-mode loop that updates a stored edge position on every crossing. Here is my own compression of that idea, not code from the paper:
state = "returning"
edge_angle = None # the goal: heading on the last plume entry
while not at_source:
if smells_odor():
if state == "returning":
edge_angle = current_heading # overwrite the goal
state = "leaving"
steer(away_from_plume)
else:
state = "returning"
steer(toward=edge_angle) # no signal; run on memory
The single most important variable was the entry angle, the direction from which the fly last hit the plume. Strip it out of the model and simulated flies could no longer edge track at all.
Key takeaway: the fly's entire working memory for this task is roughly one heading plus one angle. Good search doesn't need a big model. It needs the right state variable, updated at the right moment.
⚡ One training example rewrote the goal
The team then checked whether the memory was writable. They had flies track a plume tilted 45 degrees, then flipped it abruptly to the opposite 45-degree angle. The flies were initially lost, searching in the old direction. A single training session — a puff of vinegar delivered whenever a fly happened to walk the correct new angle — was enough. They rewrote the internal goal and started tracking the new segment.
That is a one-shot update to a spatial goal, in a brain the size of a pinhead. For Ruta, it is among the strongest evidence that memory, not reflex, drives this.
It is also a design note worth stealing. The fly does not average its last twenty crossings into a smoothed estimate. It overwrites. When the world genuinely changes, a slow-moving average is the wrong data structure, and most of us reach for one by default.
🛠️ When memory stops paying and reflex takes over
The nice part is that the paper does not oversell the memory. Run the model through a simulated natural plume and the entry-angle memory works best near the source, where the plume still holds together as a coherent ribbon. Farther downwind, where it shatters into filaments arriving from every direction, the memory becomes unreliable and gets overridden. The team's read: the flies likely fall back on the simpler reflexes there.
| Near the source | Far downwind | |
|---|---|---|
| Signal shape | coherent ribbon | chaotic filaments, every direction |
| Best strategy in the model | entry-angle memory | simpler reflexes take over |
| Engineering analogue | stable API, predictable latency | flaky link, rate limits, cold starts |
| What to do | trust and reuse cached state | drop to a dumb, cheap sweep |
Surge and cast isn't dead. It's the fallback. That two-tier arrangement — a memory-driven policy plus a reflex that survives when the memory stops predicting — is exactly the structure I'd want in a scraper, a retry policy, or an agent loop that has to keep working when the environment gets noisy.
💡 The part that matters on a small budget
Two things stand out for anyone building here without a lab, a GPU cluster, or a research budget.
- The rig was deliberately cheap. A ball on an air cushion, a steerable nozzle, and vinegar. Ruta describes it as not a very complicated virtual reality system, but extremely powerful. The power came from controlling the input, so the researchers knew every molecule the fly received. Most debugging failures I see are the same problem: we're guessing at the input rather than pinning it down.
- The first thing they tested was the accepted model. It failed, and that failure produced the paper. Testing the boring hypothesis first is cheap and it is where the surprises live.
If you want to feel the algorithm rather than read about it, the loop above is about thirty lines to simulate on a grid, and you can do it in the browser with our online Python compiler, no install and nothing to configure. Give the plume a wobble, delete edge_angle, and watch the search collapse.
What this means for you
- Store a goal, not just a reading. The fly's advantage is that it knows where it wants to be when the signal drops out. Your retry loop probably only knows what it last saw.
- The right state variable beats more state. One angle carried this behaviour for meters of tracking.
- Overwrite on real change; average on noise. Knowing which regime you're in is the actual design decision.
- Keep a reflex underneath. When the environment stops being predictable, the memory should yield to something dumb and cheap rather than confidently steering you wrong.
- Control your inputs before you theorise. A cheap rig where you know the ground truth beats an expensive one where you don't.
Ruta's broader claim is that this translating of fleeting sensory signals into stored spatial goals is a core computation shared across the animal kingdom, brains like ours included. I'd extend it one step further: it's a decent architecture for software too, and the fly is running it on a fraction of a milliwatt.