TL;DR: “Greedy probing works — until it doesn’t. This post shows how a small shift in fallback strategy, Elastic Rotation, turns sudden failure into gradual degradation. We break the cliff, bend the curve, and rethink what fairness really means under pressure.”

Greedy: Elegant Until Everyone’s Circling

Think of a hash table like a car park.

Each slot is a parking bay. Each key is a driver. And the hash function? That’s the parking attendant pointing them to their first choice.

And if that bay’s taken? The attendant hands over a list of backup instructions — “Try the next one along, then the next…”

Greedy probing feels like the perfect plan: hash the key, find the next empty bay, park the car. Simple. Fast. Done.

It’s elegant in its simplicity — and for a while, it works flawlessly.
At 50% full, it’s easy to find a spot.
Even at 75%, you’re still gliding in without much fuss.

But as the car park fills into the high 90s, that easy parking turns into chaos.
Every insert becomes a slow lap. Every fallback instruction takes you further from the entrance.
You’re not inserting — you’re circling the block.

01Ful2lbays3linear[fa4ll]back,[n5o]varia[Ptri6oobn]es[7][8]9Success
Greedy Insert Under Load

Here’s what that collapse looks like:

Greedy insertion probe cost curve

Greedy performs well early on — but probe cost spikes hard around 97% full.

For most of the journey, performance holds steady.
But just before the lot fills up, the probe cost spikes — sharp, unforgiving, and fast.

That’s the wall.

There’s no warning. No time to swerve.
One moment there’s room, the next you’re stuck doing loops. All it takes is a handful of new arrivals.

And that’s the real problem. Greedy doesn’t just fail — it fails suddenly.

Fallback can’t be a last resort. It has to shape how things fill up — and how they hold together under pressure.


From Cliffs to Curves

We aren’t just chasing performance. We’re chasing a different shape.

Greedy probing is like a single-level car park with one entrance and one row.
It works fine when there’s space. But as it fills up, everyone queues for the same few bays — and there’s nowhere else to go.

Elastic hashing changes that.

Instead of one long row, we split the table into subarrays.

Think of them as separate car parks — each with its own layout. Each one gives the driver a new set of bays to try.

GEEGErlLLLarleKaoooceaesttthesdtdtyiABClyic:::oc(tfS(afiMglanuillglvbllteabeiscaXpkcRltkoehiwesg)XLi:oXdavtresipsX)va:XecyrkoeuXadXnaorltotXhweerrantaXsthBeoutnlnoaittnsgDttpsbrhhaeieerofvnnknoceirarhhnaereegstrrSfreeardituresusistrtvrdrehuaaecytfrt.ioeuorrnwfeaidhrridsfttasl.l.o.lo.bkaicnkg,fnoortfriarnsdtomfrdeeetobuarys.
From One Lot to Many — Greedy vs Elastic Fallback

One lot full? No problem. Try the next. And the next.
Fallback isn’t a last-minute workaround — it’s in the layout.

It’s no longer linear. It’s layered. Predictable. Spread out.

But just having more lots doesn’t solve the problem.

If every driver still wants bay #17, you’ve just got the same pile-up in four different places.

Structure helps.
But without variation — it’s still chaos, just in parallel.


Our First Try: Unbalanced + Unrotated

We tried an elastic fallback strategy where each driver got access to several car parks — but was told to try the same numbered bay in each one. Always starting at car park A.

C[aBraD(yrFPiua3vlr]elkr)AC[aBfraa(ylFPlua3blr]alkc)kBC[aBfraa(ylFPlua3blr]alkc)kCCa(rBiEanmPyspaetr3rykt)DSuccess
Elastic Hashing: Car Parks with Shared Bay Targets (Unbalanced Fallback)

It sounded fair. It failed spectacularly.

Unbalanced unrotated fallback probe cost curve

Unbalanced + Unrotated fallback performs worse than greedy — symmetry without variation leads to collisions.

It was worse than greedy.

Imagine four car parks — but every driver tries to park in bay #17.

That’s what unbalanced fallback does.
Each key gets four chances — but still aims for the same bay number every time.
If #17 is full in one lot, odds are it’s full in the others too.

BBBBBaaaaayyyyy01234AlDlridvreirvCeaArr[s01234P]tarryktAhDerisvaemreCaBbr[a01234yP]aarckroBDsrsivaelrlCaClro[tP01234sa]rknCovariatCiaor[n01234,P]ahrikghDcollisionrisk.
Unbalanced Stampede — Symmetry Without Variation

It’s not fallback. It’s just four versions of the same bottleneck.

More car parks without variation just means more places to queue for the same spot.


We Rotated the Starting Car Park

So we tried giving each driver a different car park to start in.

It helped — a bit. Fewer pileups. A bit less circling.
But it still didn’t beat greedy.

let base = (hash as usize) % self.subarray_count;
for i in 0..self.subarray_count {
    let subarray_idx = (base + i) % self.subarray_count;
}
Unbalanced rotated fallback probe cost curve

Rotating the fallback starting point reduces collisions slightly — but without slot variation, greedy still wins.

Why didn’t it work?

Because every driver still aimed for the same bay — they just entered from a different car park.

We changed the entrance, but not the destination.
Bay 17 in every lot still copped the full brunt of traffic.

BBBBBaaaaayyyyy01234DriCvaerrP[Aa01234r]sktaArtshereDriCvaerr[P01234Ba]rsktaBrtshereDCrairv[eP01234ra]rCkhCereDrCiavre[rP01234a]DrkheDre
Rotated Start — Fallback Without Spread

Each driver pulls into a different car park — but still heads straight to the same bay number.

We spread out the arrivals. But not the demand.
And without that, rotation just delays the jam — it doesn’t prevent it.


Finally: Elastic Rotation

This is where everything clicked.

Balanced fallback doesn’t just rotate which car park a driver enters — it rotates the map inside each one.

Same driver. Same parking attendant. But in each car park, they’re handed a different set of instructions.

That means less crowding. Fewer pileups. No more stampede to bay #17.

Each fallback lot now gives a different layout — and that breaks up hotspots.
Traffic spreads. Pressure drops. The curve softens.

Now fallback actually works.

And it all comes down to one small shift:

fn slot_index(&self, hash: u64, subarray_idx: usize) -> usize {
    if self.balanced {
        ((hash.rotate_right(subarray_idx as u32)) as usize) % self.slots_per_subarray
    } else {
        (hash as usize) % self.slots_per_subarray
    }
}
Balanced rotated fallback probe cost curve

Elastic Rotation fallback spreads pressure evenly — and finally beats greedy under high load.

BBBBBaaaaayyyyy01234DriverACar[01234P]arkDAriverCBar[P01234a]rkBDriverCaCr[P01234a]rkCDriverCDar[P01234a]rkD
Balanced Fallback — Different Views of the Same Hash

Now, every driver still wants a spot.
But instead of aiming for bay #17 in every car park, each attendant gives them a different route.

Rotation spreads where fallback starts.
Balance spreads what fallback targets.

And the result?

Not just fewer collisions — but a system that degrades predictably.
No more cliffs. Just a gentle hill


The Full Picture

Here’s how they all compare — now that you’ve seen the journey:

Comparison of greedy and elastic fallback strategies

Greedy climbs quickly. But with rotation and balance, fallback stays smooth — even under pressure.

Elastic Rotation holds its shape. Every other variant — including greedy — buckles.


The Maths

The Maths Behind the Cliff

Greedy looks efficient — but its cost curve hides a trap:

$ \mathbb{E}[\text{probes}] = \frac{1}{1 - \alpha} $

Where \( \alpha \) is the load factor — the portion of the table that’s already full.

  • At 80% full: ~5 probes
  • At 90%: 10
  • At 99%: over 100

You don’t get a gentle slowdown. You get a cliff.

Why? Because greedy fallback always checks the next bay. The fewer empty spots left, the longer that list of instructions gets.

It’s like trying to park at the beach on a public holiday — every turn is taken, and the attendant just keeps pointing you further down the row.

Theoretical probe cost curve for greedy fallback

Greedy fallback performs well at low load — but climbs rapidly as the table fills.

This is why elastic hashing exists: to bend the curve. To leak pressure early, rather than explode late.


The Maths of Bounded Pain

Greedy’s cost curve spikes. But balanced fallback stays contained:

$ \text{max probes} \leq \mathcal{O}\left(\log \frac{1}{\delta}\right) $

Where \( \delta = 1 - \alpha \) — the remaining capacity in the table.

It doesn’t stop probe growth entirely. But it slows it down, flattens it out.

Instead of hitting a wall, you get a slow crawl.
Instead of being waved from bay to bay in panic, you ease through with time to think.

That’s what balanced fallback gives you:
A system that gives you warning, breathing room, and a fair chance at parking without stress.

Comparison of greedy and elastic theoretical probe cost curves

Elastic fallback bends early and stays flat — greedy climbs sharply as load increases.


Try It Yourself

Fire up the dev shell:

nix develop

Generate the plots:

just probes-at-load-post1  
just probes-at-load-post2-unbalanced-unrotated  
just probes-at-load-post2-unbalanced  
just probes-at-load-post2-balanced  
just plot-probes

All output lands in probe-data/, including the blog-ready charts.

Watch the wall.
Then watch it bend.


The Shape of Failure

You don’t build tables to sit half empty.
You build them to take load — to grow, stretch, and survive pressure.

And when that pressure hits, what matters isn’t peak performance — it’s behaviour.
How the system bends. How it breaks. How much warning it gives you.

Greedy gives you none.

It works — until it doesn’t. And when it breaks, it breaks fast.

That’s not just a system failure. It’s a human one.

We miss the warning signs. We normalise risk.
And when the spike hits — latency, cost, pressure — it feels sudden. But it isn’t.

The curve had flattened long before it broke.

Comparison between cliff-like and curve-like system failures

Systems that fail like cliffs give no warning. Systems that fail like curves give you time.

That’s why fallback can’t be a patch. It has to shape how failure unfolds.

Elastic Rotation does exactly that.

By rotating the hash per fallback lane, it spreads load, breaks up collisions, and bends the curve early — before the system gets tight.

It’s not a trick. It’s a design shift. From fallback as emergency… to fallback as architecture.

Sometimes, resilience comes from the shape of the fallback — not its complexity.

Systems that fail gradually, not suddenly.
That hold their shape when pressure builds.

That’s the bound we came to break.


Next Up

We’ve bent the curve. Next, we build the full system.

Following the path laid out by Anshu, Dey, and Jayaram in Optimal Bounds for Open Addressing Without Reordering, we’ll go deeper — into fallback strategies that balance better and break a 40-year assumption.

Full probe logic. Batch-aware inserts. Search that stays fast, even when every bay’s nearly full.