Amazon New Grad Four-Round VO: What Changed This Year + Three Business-Scenario Coding Questions + Bar Raiser Deep Dive
Amazon new grad four-round VO recap: this year's shift to team-based hiring, four rounds, a stronger Bar Raiser and AI questions; three business-framed coding problems — Promotion Eligibility, Vendor Contract Registry, Return Requests — with reference implementations, and key behavioral deep-dive points.
What changed between the last two years
Overall, Amazon's new-grad interviews changed noticeably this year:
| Last year | This year | |
|---|---|---|
| Hiring model | Many roles were general hiring, with team placement after the interviews | Almost all team-based hiring; most interviewers come straight from the target team |
| Rounds | Three | Increasingly four, with a much more prominent Bar Raiser |
| Coding | Lots of well-known questions; grinding the question bank paid off | More and more wrapped in real business scenarios; you rarely recognize the original problem at a glance |
| AI | Almost never came up | A frequent topic: Cursor, Claude, ChatGPT, and how you verify AI-generated code |
This year's VO format
- Usually four rounds, either in one day or split across two.
- Typically three rounds from the hiring team and one Bar Raiser.
- Technical rounds are mostly 30 minutes of behavioral + 30 minutes of coding; the BR is most likely all behavioral.
- Results come within a week.
Round 1: Behavioral + Promotion Eligibility Service
The interviewer was an SDE from the target team working on an ads platform. After introductions we went straight into behavioral questions.
Behavioral
- Tell me about a time you proactively spotted a project risk and drove the fix. I talked about an internship where the recommendation service's cache hit rate kept dropping; left alone, it could have caused a latency spike in production, so I analyzed the data early and pushed the team to improve the caching strategy.
- Tell me about a technical disagreement with a teammate. The follow-ups were detailed: not just the pros and cons of each side, but also what you'd do if it turned out you were wrong.
Coding: Promotion Eligibility Service
The platform runs promotions regularly, and a user can be in several at once. The system needs to support:
- Users joining and leaving promotions
- Querying which promotions a user is currently in
- Quickly counting how many users a promotion currently covers
Follow-ups:
- What if there are hundreds of thousands of promotions?
- What if you need a real-time view of the top 10 promotions by participants?
- How do you prevent the same user from being added to the same promotion twice?
It's a HashMap + HashSet combination problem, dressed up to look like a real business system.
import heapq
from collections import defaultdict
class PromotionService:
def __init__(self):
self.user_promos = defaultdict(set) # user -> promotions joined
self.promo_count = defaultdict(int) # promotion -> number of participants
def join(self, user, promo):
if promo in self.user_promos[user]:
return False # dedupe: a user can't join the same promotion twice
self.user_promos[user].add(promo)
self.promo_count[promo] += 1
return True
def leave(self, user, promo):
if promo not in self.user_promos[user]:
return False
self.user_promos[user].remove(promo)
self.promo_count[promo] -= 1
return True
def promos_of(self, user):
return set(self.user_promos[user])
def user_count(self, promo):
return self.promo_count[promo]
def top_promos(self, k=10):
"""The k promotions with the most participants, O(P log k)"""
return heapq.nlargest(k, (p for p, c in self.promo_count.items() if c > 0),
key=lambda p: (self.promo_count[p], p))
Follow-up ideas:
- Hundreds of thousands of promotions: store just a counter per promotion, so counting is O(1) with no iteration over users.
- Real-time top 10:
nlargestabove scans every promotion each time; for very frequent queries, maintain a structure sorted by count (e.g. a Redis ZSET), updating scores in O(log P) on each join / leave and reading the top 10 directly.- Deduplication: check the per-user HashSet before writing; in a distributed setup, back it with a unique constraint on
(user_id, promo_id).
Round 2: Behavioral + Vendor Contract Registry
Behavioral: Deliver Results
Tell me about a project with an extremely tight timeline that still launched successfully. The interviewer barely cared about the project itself and kept probing the decision-making:
- Why did you prioritize certain features?
- Why did you drop others?
- What would you do with half the time?
Coding: Vendor Contract Registry
The company maintains a large number of vendor contracts. The system needs to support:
- Adding contracts, deleting contracts, updating a contract's status
- Querying a vendor's current number of active contracts
Follow-ups:
- How do you quickly find contracts expiring in the next thirty days?
- How do you handle auto-renewing contracts?
- How do you keep data consistent when several operators edit the same contract at once?
The interviewer didn't look closely at code details; most of the time went into data structure choices and complexity analysis.
from bisect import bisect_left, insort
class ContractRegistry:
def __init__(self):
self.contracts = {} # id -> {vendor, status, end, version}
self.active_count = {} # vendor -> number of active contracts
self.by_end = [] # (end, id) sorted by end date (integer days), for expiry queries
def _adjust(self, vendor, status, delta):
if status == "ACTIVE":
self.active_count[vendor] = self.active_count.get(vendor, 0) + delta
def add(self, cid, vendor, end, status="ACTIVE"):
if cid in self.contracts:
return False
self.contracts[cid] = {"vendor": vendor, "status": status, "end": end, "version": 0}
self._adjust(vendor, status, +1)
insort(self.by_end, (end, cid))
return True
def remove(self, cid):
c = self.contracts.pop(cid, None)
if c is None:
return False
self._adjust(c["vendor"], c["status"], -1)
self.by_end.remove((c["end"], cid))
return True
def update_status(self, cid, status, expected_version):
"""Optimistic locking: a version mismatch means someone else updated first, so reject"""
c = self.contracts.get(cid)
if c is None or c["version"] != expected_version:
return False
self._adjust(c["vendor"], c["status"], -1)
self._adjust(c["vendor"], status, +1)
c["status"], c["version"] = status, c["version"] + 1
return True
def active_contracts(self, vendor):
return self.active_count.get(vendor, 0)
def expiring_within(self, today, days=30):
"""Active contracts expiring within [today, today + days]; binary search, O(log n + results).
Dates are integer day numbers (e.g. days since 1970-01-01); (d,) sorts before any (d, id)"""
lo = bisect_left(self.by_end, (today,))
hi = bisect_left(self.by_end, (today + days + 1,))
return [cid for _, cid in self.by_end[lo:hi] if self.contracts[cid]["status"] == "ACTIVE"]
Follow-up ideas:
- Expiring soon: keep an index sorted by end date (
by_endabove; in production, an index onend_datein the database) and binary-search the time range.- Auto-renewal: add an
auto_renewflag; a scheduled job scans contracts that are about to expire and need renewal, updates their end dates (and the index), and records the renewal history.- Concurrent edits: use optimistic locking — each update carries the
versionit read, and a mismatch is rejected so the user refreshes and retries (update_statusabove).
Round 3: Bar Raiser (all behavioral, about 45 minutes)
No coding at all. Three sets of questions, and each story was probed for ten minutes or more:
| Question | Where the follow-ups went |
|---|---|
| Your most impactful project | What exactly you did, and how you measured the impact |
| A failure | What caused it? Why wasn't it caught earlier? Did anyone on the team disagree? What concrete improvements followed? |
| An example of Ownership | Which parts weren't originally your responsibility? Why did you decide to take them on? |
This round felt more like validating how you've worked in the past than testing technical skill.
Round 4: Behavioral + Return Request Processing System
Behavioral
- A time you quickly learned a new technology and delivered.
- How you adjusted the project plan after a major requirements change.
Coding: Return Request Processing System
An e-commerce platform receives lots of return requests every day. The system needs to support:
- Creating and canceling return requests
- Querying a user's return history
- Counting a product's current pending returns
from collections import defaultdict
class ReturnService:
def __init__(self):
self.requests = {} # rid -> {user, item, status}
self.user_history = defaultdict(list) # user -> [rid], in creation order
self.pending = defaultdict(int) # item -> number of pending returns
def create(self, rid, user, item):
if rid in self.requests: # idempotent: ignore duplicate submissions
return False
self.requests[rid] = {"user": user, "item": item, "status": "PENDING"}
self.user_history[user].append(rid)
self.pending[item] += 1
return True
def _close(self, rid, status):
r = self.requests.get(rid)
if r is None or r["status"] != "PENDING":
return False
r["status"] = status
self.pending[r["item"]] -= 1
return True
def cancel(self, rid):
return self._close(rid, "CANCELLED")
def complete(self, rid):
return self._close(rid, "COMPLETED")
def history(self, user):
return [(rid, self.requests[rid]["status"]) for rid in self.user_history[user]]
def pending_count(self, item):
return self.pending[item]
Talking about AI (about 10 minutes)
After coding we spent ten minutes on AI:
- Do you use Cursor or Claude day to day?
- If AI hands you a complex piece of code, how do you verify it's correct?
- Have you seen an AI-generated solution that looked reasonable but had a logic flaw? How did you catch it?
Prep tip: have a real example ready that shows how you verify AI-generated code — writing test cases, comparing against a brute-force solution, understanding every line before merging, code review. The interviewer wants to hear that you own code quality, not whether you can use the tools.
Summary
- Coding: this year's questions are "HashMap / HashSet / heap + a business wrapper". The difficulty isn't the algorithm but turning the requirements into clean data structures, then discussing scaling, concurrency and complexity.
- Behavioral: every story gets probed on decisions and details, so prepare real examples that hold up under deep follow-ups, mapped to specific Leadership Principles.
- AI: now a frequent topic — prepare your answer to "how do you verify AI-generated code".
Found this helpful? Let's talk.
Happy to swap interview notes, do mock interviews, or share referral info.

Scan to add me on WeChat
More Amazon notes
View all ›Amazon China SDE 27NG Four-Round VO: GenAI Behavioral + Topological Sort + Minimum Size Subarray + Binary SearchAmazon · 2026-10-02›
Amazon New Grad Interview Question: TaskScheduler, Fully Analyzed (Topological Sort)Amazon · 2026-10-02›
Amazon SWE 26NG Four Rounds: Dijkstra Delivery Routes + Sliding Window + Top K Orders + Bar RaiserAmazon · 2026-10-02›
Amazon SWE Four-Round VO (Passed): Bracket Nesting Depth + Group Anagrams + Vending Machine OODAmazon · 2026-10-02›