What Amazon’s Bar Raiser Actually Tests in Coding Interviews

What Amazon’s Bar Raiser Actually Tests in Coding Interviews

1 14
calendar_todayschedule7 min read
— Originally published at www.codeintuition.io

I thought solving the problem was the round. The last ten minutes turned out to be the part that counted.

I'd put close to four months into Amazon prep by the time my onsite landed. Two coding rounds went fine. The third started fine too.

I solved the initial problem in about twenty minutes, walked through the test cases, and felt the round was already mostly won.

Then the interviewer asked one follow up.

The constraint they changed was small, the kind of thing I'd have called "minor" if I'd been describing it on paper.

It exposed that I'd been preparing for the wrong half of the round, and I spent the next ten minutes recovering ground I should never have lost.

That round was a Bar Raiser round.

I didn't know it at the time (Amazon doesn't tell you), but the debrief came back with the kind of feedback only the Bar Raiser writes:

"Strong initial solution, struggled to adapt under constraint change, did not demonstrate the structural reasoning we look for."

The phrasing is almost word for word from how Bar Raisers grade.

The follow up after the working solution is the round.

What I figured out

  • The Bar Raiser is one of the four or five interviewers on the loop, but you won't know which one. Treat every round as if it's them.
  • Amazon's pattern coverage is wider than Google's or Meta's, so going deep on three families isn't enough.
  • The grade often lives in the last ten minutes after your first working solution, not in the first solution itself.
  • Adapting after a constraint flip is a specific skill that grinding more problems doesn't build.
  • The fix is interleaved practice plus an explicit constraint flip rep on every problem.

Where my approach was breaking

My prep model was the standard FAANG one.

Pick the two or three pattern families that show up most for the company. Go deep on those. Time myself on company tagged problems. Repeat until recall got fast.

For Google that worked well enough.

Google leans heavily on predicate search, counting, and graph traversal. If you're solid on those three, the round usually lands in your zone. I'd interviewed at Google with that exact prep and it had been fine.

Amazon's pattern set is wider.

Across the problems Amazon actually tests, you'll see:

  • counting
  • fixed and variable sliding window
  • prefix sum
  • LRU-style design
  • randomized set design
  • plain binary search
  • 2D and staircase binary search variants
  • queue design
  • backtracking

That's roughly eleven distinct families against Google's seven or eight.

The depth strategy that worked for Google had a worse hit rate at Amazon, and on the round that turned into the Bar Raiser slot, the problem landed in a family I'd given less time to.

The deeper issue was something the wider pattern coverage just made more visible.

Even on patterns I had practised, my fluency was template recall, not invariant construction.

As long as the problem looked enough like a textbook example, I produced the standard solution quickly.

The moment the constraint shifted, I tried to retrieve a different template instead of modifying the one I had.

The Bar Raiser format is built to expose that gap.

The follow up after the working solution is the round.


What I started doing differently

After the rejection landed, I went back through every coding round I'd done in mock interviews, including the ones I'd thought went well.

Two patterns showed up across roughly half of them:

  • I'd produced a correct solution within the time budget, but I couldn't have explained which invariant the data structure I picked was maintaining. The hash map worked. I couldn't have said cleanly what would break if I'd used an array instead.
  • When the mock interviewer changed a constraint at the end (which the better mocks always did), I either started from scratch or stalled. I almost never reached for the original solution and asked which part of it depended on the constraint that had moved.

Both were habits I'd built by drilling for speed against template problems.

Neither was a coding skill I lacked.

They were prep habits.

I shifted two things.

First, every problem I solved got a constraint flip rep.

Whatever the original constraint was, I changed one piece of it and reimplemented.

Second, I started reading my old solutions out loud as if explaining them to an interviewer, naming the invariant the structure maintained on every line.

The first felt like more work for the same problem count.

The second felt like wasted time.

Both turned out to be the gap.

Here's what changed in practice:

What I used to do What I started doing
Solve the problem, check the answer, move on Solve the problem, then write down the constraint change that would invalidate the solution most
Drill problems within one pattern family per week Rotate between three or four pattern families inside a single session
Recall the optimal solution before writing any code Get a correct O(n²) working first, confirm edge cases, then improve
Treat the follow up question in mocks as a bonus Treat the follow up as the main rep
Explain the solution by walking through the code Explain the solution by naming the invariant first

What that looked like on the next Word Search follow up

A few weeks later I ran a mock that landed on Word Search.

Standard backtracking on a grid:

Given a board of characters and a target word, return whether the word can be formed by a path of adjacent cells, with no cell reused.

The solution is a depth first search from each starting cell with a visited mark.

def exist(board, word):
    rows, cols = len(board), len(board[0])

    def dfs(r, c, idx):
        if idx == len(word):
            return True
        if r < 0 or r >= rows or c < 0 or c >= cols:
            return False
        if board[r][c] != word[idx]:
            return False

        tmp = board[r][c]
        board[r][c] = '#'

        found = (
            dfs(r+1, c, idx+1)
            or dfs(r-1, c, idx+1)
            or dfs(r, c+1, idx+1)
            or dfs(r, c-1, idx+1)
        )

        board[r][c] = tmp
        return found

    for r in range(rows):
        for c in range(cols):
            if dfs(r, c, 0):
                return True

    return False

The invariant the in-place marking maintains:

At any point in the recursion, the cells along the current path are marked #, every other cell is restored.

Backtracking by restoring on the way out keeps the invariant true at depth zero, which is what makes:

“No cell reused along this path”

hold.

Then came the follow up.

Instead of a single word, you now have a list of k words to find on the same board.

Same constraint.

No cell reused along a single word's path.

The old me would've started writing:

for w in words:
    exist(board, w)

taken the cost of:

O(k * rows * cols * 4^L)

and gone home.

The interviewer would've asked the obvious question:

“Can you do better than the naive loop?”

Which is exactly what had happened in the real round.

This time I asked a different question first:

Which part of the original solution depended on the constraint that just changed?

The DFS was doing the same prefix walk repeatedly for every word sharing a prefix.

So instead of changing the traversal:

Change what the traversal checks against.

Compose the DFS with a trie of all k words.

Every board walk now checks against all words simultaneously.

The invariant doesn't change.

The base case changes.

The grid traversal stays.

The constraint changed.

Not the structure.

def find_words(board, words):
    root = build_trie(words)
    rows, cols = len(board), len(board[0])
    found = set()

    def dfs(r, c, node):
        ch = board[r][c]

        if ch == '#' or ch not in node.children:
            return

        nxt = node.children[ch]

        if nxt.word:
            found.add(nxt.word)
            nxt.word = None

        board[r][c] = '#'

        for dr, dc in ((1,0), (-1,0), (0,1), (0,-1)):
            nr, nc = r + dr, c + dc

            if 0 <= nr < rows and 0 <= nc < cols:
                dfs(nr, nc, nxt)

        board[r][c] = ch

    for r in range(rows):
        for c in range(cols):
            dfs(r, c, root)

    return list(found)

I got there in roughly four minutes.

Not because I'd drilled Word Search II as a separate template.

Because I'd been practising one question repeatedly:

Which part of the original depended on the constraint that changed?

The change was in what the DFS checked.

Not in the DFS itself.


Why interleaving works for breadth

The other half of the gap was simply pattern coverage.

Three families deep wasn't enough for Amazon's surface area.

But I also couldn't realistically go equally deep on eleven families in the time I had left.

What I could do was rotate between them.

Research on interleaved practice consistently shows that mixing problem types improves your ability to identify which pattern applies to a new problem.

Mixed practice feels harder.

Blocked practice feels easier.

That's exactly why it works.

Blocked practice gives you:

“This week is sliding window.”

The Bar Raiser gives you:

“Figure out what this is.”

The added friction during practice was the same identification work the round required.

Practically, that meant:

A session of four problems became:

four different families

not:

four sliding window problems.


What I'd tell someone in the same spot

A few rules I wish I'd had four months earlier.

1. Get a working solution before chasing the optimal one

Twenty-five minutes thinking before writing leaves no room for the follow up.

A correct O(n²) solution that gets improved beats a half-written O(n) attempt every time.

2. Treat the follow up as the round

When the interviewer changes a constraint:

Ask which part of your solution depended on that constraint.

Modify only that part.

The instinct to redesign from zero is expensive.

3. Practise the constraint flip explicitly

Every problem gets a second pass with one constraint changed.

Implement the modified version.

That rep builds adaptation.

And adaptation is what the round grades.

If someone had explicitly taught me how to identify which part of a solution depends on a changing constraint, it would've shortened the loop considerably. The closest thing to the work I had to build for myself later was a pattern-identification lesson I eventually added inside Codeintuition.

I originally posted a longer version on my own blog with the per-pattern breakdown across all eleven families and how the rest of Amazon's interview loop factors into the Bar Raiser grade.

What’s a constraint flip from an interview that exposed a solution you thought you understood?

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Your Tech Stack Isn’t Your Ceiling. Your Story Is

Karol Modelskiverified - Apr 9

The Senior Angular Take‑Home That Made Me Rethink Tech Interviews

Karol Modelskiverified - Apr 2

FAANG Coding Interviews Aren’t the Same: The DSA Patterns Each Company Actually Tests

prakhar_srv - May 12

Your AI Doesn't Just Write Tests. It Runs Them Too.

Kevin Martinez - May 12

How to Explain Algorithm Correctness in Coding Interviews

prakhar_srv - May 6
chevron_left
626 Points15 Badges
London, UKcodeintuition.io
17Posts
6Comments
4Connections
I write about the hidden parts of coding interview prep most people discover too late: algorithmic i... Show more

Related Jobs

View all jobs →

Commenters (This Week)

2 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!