Amazon Interview Experience — Full Stack JavaScript Developer (All Rounds)
Amazon Interview Experience — Full Stack JavaScript Developer (All Rounds)
Hey everyone! This blog is a complete round-by-round breakdown of the Amazon SDE interview for a Full Stack JavaScript Developer — with real questions asked and detailed answers!
Amazon's interview is not just about coding. It tests your JavaScript depth, system design thinking, DSA skills, and Leadership Principles — all together. This is your one-stop guide.
What we will cover:
- Round 0 — Online Assessment (OA)
- Round 1 — Technical Phone Screen
- Round 2 — DSA Coding Round
- Round 3 — JavaScript and Node.js Deep Dive
- Round 4 — React and Frontend System Design
- Round 5 — Bar Raiser Round (Leadership Principles)
- Quick Recap + Key Tips
Amazon Interview Process — Overview
Application → OA → Phone Screen → Loop (4–5 Onsite Rounds) → Offer ┌──────────────────────────────────────────────────────────────┐ │ AMAZON LOOP STRUCTURE │ │ │ │ Round 0: Online Assessment (OA) → Filter round │ │ Round 1: Technical Phone Screen → JS basics + 1 LP │ │ Round 2: DSA Coding Round → Medium–Hard LeetCode │ │ Round 3: JS / Node.js Deep Dive → Core concepts + code │ │ Round 4: React + System Design → Frontend architecture │ │ Round 5: Bar Raiser → Leadership Principles │ │ │ │ Each onsite round = 55–60 minutes │ │ Every round has BEHAVIORAL questions (Leadership Principles) │ │ Strong code + Weak LP = NO OFFER at Amazon! │ └──────────────────────────────────────────────────────────────┘
Amazon's 16 Leadership Principles (LP) are tested in EVERY round. The most common ones for SDE roles:
- Customer Obsession
- Ownership
- Invent and Simplify
- Are Right, A Lot
- Learn and Be Curious
- Dive Deep
- Deliver Results
- Bias for Action
Round 0 — Online Assessment (OA)
Duration: 2 hours | Platform: HackerRank / Amazon's internal portal
The OA is the first filter. It has 3 parts:
Part 1: 10 MCQs on HTML, JavaScript, and CSS (20 min) Part 2: 1 Machine Coding Question — Build a UI component in Vanilla JS (90 min) Part 3: Work Style Survey (Amazon Leadership Principles) (15 min)
MCQ Questions Asked (Part 1)
Q1: What is the output of the following code?
setTimeout(() => console.log("A"), 0);
Promise.resolve().then(() => console.log("B"));
console.log("C");
A) A B C
B) C A B
C) C B A ✅
D) B C A
ANSWER: C B A
WHY: console.log("C") → synchronous, runs first.
Promise.then → microtask, runs before macrotask.
setTimeout → macrotask, runs last.
Q2: What does the following output?
let x = 1;
function test() {
console.log(x);
let x = 2;
}
test();
A) 1
B) 2
C) undefined
D) ReferenceError ✅
ANSWER: ReferenceError
WHY: 'let' is in the Temporal Dead Zone (TDZ) until its declaration.
'x' is hoisted but not initialized — accessing it before
the 'let x = 2' line throws ReferenceError.
Q3: What is event delegation?
A) Assigning events to each element separately
B) Using capture phase for events
C) Attaching one event listener to a parent to handle events
from its children ✅
D) Preventing event bubbling
ANSWER: C
WHY: Instead of 100 event listeners for 100 list items,
you put ONE listener on the parent. Events bubble up
from child to parent, so the parent handles all of them.
Q4: Which array method does NOT mutate the original array? A) splice B) push C) map ✅ D) pop ANSWER: C — map returns a NEW array, original is unchanged. splice, push, pop ALL mutate the original array.
Q5: What is the difference between == and ===? == does TYPE COERCION (converts types before comparing) === is STRICT EQUALITY (no type conversion) "5" == 5 → true (string "5" coerced to number) "5" === 5 → false (different types, no coercion) null == undefined → true null === undefined → false
Machine Coding Question (Part 2)
Question: Build an Image Carousel in Vanilla JavaScript
Requirements: - Display images one at a time - Previous and Next buttons - Auto-play with 3 second interval - Dot indicators showing current slide - Pause auto-play on hover - No libraries — plain HTML, CSS, JS only // HTML Structure <div class="carousel"> <button id="prev">‹</button> <img id="slide" src="" alt="slide" /> <button id="next">›</button> <div id="dots"></div> </div>
// JavaScript Solution
const images = [
"img1.jpg", "img2.jpg", "img3.jpg", "img4.jpg"
];
let current = 0;
let timer;
const slide = document.getElementById("slide");
const dotsContainer = document.getElementById("dots");
// Build dots
images.forEach((_, i) => {
const dot = document.createElement("span");
dot.className = "dot";
dot.onclick = () => goTo(i);
dotsContainer.appendChild(dot);
});
function goTo(index) {
current = (index + images.length) % images.length;
slide.src = images[current];
document.querySelectorAll(".dot").forEach((d, i) => {
d.classList.toggle("active", i === current);
});
}
function startAutoPlay() {
timer = setInterval(() => goTo(current + 1), 3000);
}
function stopAutoPlay() {
clearInterval(timer);
}
document.getElementById("next").onclick = () => goTo(current + 1);
document.getElementById("prev").onclick = () => goTo(current - 1);
document.querySelector(".carousel").addEventListener("mouseenter", stopAutoPlay);
document.querySelector(".carousel").addEventListener("mouseleave", startAutoPlay);
goTo(0); // Initialize
startAutoPlay();
KEY POINTS the interviewer checks:
- Modulo wrap-around logic: (index + length) % length
- Proper dot highlighting
- clearInterval on hover → prevents multiple intervals stacking
- Separation of concerns (goTo handles all state)
Round 1 — Technical Phone Screen
Duration: 45–60 minutes | First 20 min: Behavioral | Next 35 min: Technical
Behavioral Questions Asked
Q: Tell me about a time you had a disagreement with a teammate.
How did you handle it?
STAR ANSWER:
──────────────
S — Situation:
On a React + Node.js project, a teammate wanted to store
user session data in localStorage for simplicity. I was
concerned about XSS vulnerability.
T — Task:
I needed to convince the team to use httpOnly cookies instead
without creating conflict or slowing down the sprint.
A — Action:
I wrote a quick 1-page document comparing localStorage vs
httpOnly cookies on security. I showed a simple XSS demo
where malicious script could steal localStorage tokens.
I suggested we switch without delaying the deadline.
R — Result:
Team agreed. We shipped with httpOnly cookies + CSRF tokens.
2 weeks later, a security audit praised this decision.
The feature launched on time with zero security issues.
LEADERSHIP PRINCIPLE: Are Right, A Lot + Ownership
Technical Questions Asked
Q1: What is the difference between null and undefined? ANSWER: undefined → variable declared but NOT assigned any value null → variable explicitly assigned "no value" intentionally let a; // undefined — JS assigned it automatically let b = null; // null — developer intentionally set "empty" typeof undefined → "undefined" typeof null → "object" (historical bug in JS!) null == undefined → true (loose equality) null === undefined → false (strict equality)
Q2: What is the difference between var, let, and const?
Feature var let const
────────────────────────────────────────────────────
Scope Function Block Block
Hoisting Yes (undef) Yes (TDZ) Yes (TDZ)
Re-declare Yes No No
Re-assign Yes Yes No
Global object Yes (window) No No
var x = 1;
if (true) {
var x = 2; // Same variable! Overwrites!
let y = 3; // Block-scoped, only exists here
}
console.log(x); // 2 (var leaked out!)
console.log(y); // ReferenceError (let stays in block)
CONST gotcha:
const obj = { name: "Shreyesh" };
obj.name = "Amazon"; // ✅ WORKS — object is mutable
obj = {}; // ❌ TypeError — can't reassign binding
Q3: Implement a function that flattens a nested array.
Input: [1, [2, [3, [4]], 5]]
Output: [1, 2, 3, 4, 5]
// Solution 1: Recursion
function flatten(arr) {
const result = [];
for (const item of arr) {
if (Array.isArray(item)) {
result.push(...flatten(item)); // recurse!
} else {
result.push(item);
}
}
return result;
}
// Solution 2: Array.flat() (ES2019 — mention this too!)
[1, [2, [3, [4]], 5]].flat(Infinity);
// Solution 3: reduce + recursion (shows mastery)
function flatten(arr) {
return arr.reduce((acc, item) =>
acc.concat(Array.isArray(item) ? flatten(item) : item), []);
}
console.log(flatten([1, [2, [3, [4]], 5]]));
OUTPUT: [1, 2, 3, 4, 5]
Interviewer expects you to handle infinite nesting
and mention .flat(Infinity) as a built-in alternative!
Round 2 — DSA Coding Round
Duration: 55–60 minutes | 1–2 DSA problems | Medium to Hard difficulty
Amazon focuses heavily on Arrays, Strings, Trees, Graphs, and DP. Expect LeetCode Medium as baseline.
Question 1 Asked: Rotting Oranges (BFS)
PROBLEM: You have a grid. Each cell is: 0 = empty, 1 = fresh orange, 2 = rotten orange Every minute, a rotten orange makes all adjacent (up, down, left, right) fresh oranges rot. Return the minimum number of minutes until no fresh orange remains. If impossible, return -1. Input: [[2,1,1], [1,1,0], [0,1,1]] Output: 4
// Solution: Multi-Source BFS
function orangesRotting(grid) {
const rows = grid.length;
const cols = grid[0].length;
const queue = [];
let fresh = 0;
// Step 1: Find all rotten oranges + count fresh
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (grid[r][c] === 2) queue.push([r, c, 0]); // [row, col, time]
if (grid[r][c] === 1) fresh++;
}
}
if (fresh === 0) return 0; // Edge case: no fresh oranges
// Step 2: BFS from all rotten oranges simultaneously
const directions = [[1,0],[-1,0],[0,1],[0,-1]];
let maxTime = 0;
let i = 0;
while (i < queue.length) {
const [r, c, time] = queue[i++];
for (const [dr, dc] of directions) {
const nr = r + dr;
const nc = c + dc;
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols
&& grid[nr][nc] === 1) {
grid[nr][nc] = 2; // Mark as rotten
fresh--;
maxTime = Math.max(maxTime, time + 1);
queue.push([nr, nc, time + 1]);
}
}
}
return fresh === 0 ? maxTime : -1;
}
console.log(orangesRotting([[2,1,1],[1,1,0],[0,1,1]]));
OUTPUT: 4
WHY BFS?
BFS processes level by level — each level = 1 minute.
Multi-source BFS starts from ALL rotten oranges at minute 0.
Greedy expansion ensures minimum time.
Time: O(rows × cols)
Space: O(rows × cols) for the queue
Question 2 Asked: Two Sum (variant with indices)
PROBLEM:
Given an array of integers and a target, return INDICES
of two numbers that add up to target.
You may not use the same element twice.
Input: nums = [2, 7, 11, 15], target = 9
Output: [0, 1] (nums[0] + nums[1] = 2 + 7 = 9)
// NAIVE solution — O(n²) → DO NOT write this!
function twoSum(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) return [i, j];
}
}
}
// OPTIMAL solution — O(n) using HashMap!
function twoSum(nums, target) {
const map = new Map(); // value → index
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (map.has(complement)) {
return [map.get(complement), i];
}
map.set(nums[i], i);
}
}
console.log(twoSum([2, 7, 11, 15], 9));
OUTPUT: [0, 1]
WHY HASHMAP?
For each number, we need its complement (target - num).
Map gives O(1) lookup — one pass through the array!
Time: O(n) | Space: O(n)
Interviewer follow-ups:
- What if no solution exists? → return [] or throw Error
- What if duplicate numbers? → Map stores last index, handle carefully
- What if sorted array? → Two pointer approach → O(1) space
Round 3 — JavaScript and Node.js Deep Dive
Duration: 55–60 minutes | Core JS concepts + Node.js + live coding
This round is where they test HOW WELL you know JavaScript — not just that you use it!
Question 1: Explain the JavaScript Event Loop
Q: What is the Event Loop? What is the difference between
the microtask queue and macrotask queue?
ANSWER:
=========
JavaScript is single-threaded — it can do ONE thing at a time.
The Event Loop is what lets it handle async operations
without blocking.
Components:
───────────
1. Call Stack → where code executes (LIFO)
2. Web APIs → setTimeout, fetch, DOM events (browser handles these)
3. Microtask Queue → Promise.then, queueMicrotask, MutationObserver
4. Macrotask Queue → setTimeout, setInterval, setImmediate (Node.js)
ORDER OF EXECUTION:
1. Run all synchronous code (Call Stack empties)
2. Run ALL microtasks (Promise.then chain completely)
3. Render the UI (browser only)
4. Run ONE macrotask (one setTimeout/setInterval)
5. Repeat from step 2
EXAMPLE — Predict the output:
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve()
.then(() => console.log("3"))
.then(() => console.log("4"));
console.log("5");
OUTPUT:
1
5
3
4
2
WHY:
1, 5 → synchronous, runs immediately
3, 4 → microtasks (Promise.then), run before macrotask
2 → macrotask (setTimeout), runs last
Even though setTimeout has 0ms delay, it waits for
ALL microtasks to finish first!
Question 2: Implement Debounce from scratch
Q: Implement a debounce function. Where would you use it?
WHAT IS DEBOUNCE?
==================
Debounce ensures a function runs ONLY AFTER a specified
delay of inactivity. If called again before the delay
expires, the timer RESETS.
Real-World Use: Search bar — don't fire API call on every
keystroke. Wait until user stops typing for 300ms.
// Implementation
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer); // Reset timer on each call
timer = setTimeout(() => {
fn.apply(this, args); // Execute after delay
}, delay);
};
}
// Usage
const searchAPI = debounce((query) => {
console.log("Fetching:", query);
// fetch(`/api/search?q=${query}`)
}, 300);
// Simulate user typing
searchAPI("r"); // Timer starts
searchAPI("re"); // Timer RESET
searchAPI("rea"); // Timer RESET
searchAPI("reac"); // Timer RESET
searchAPI("react"); // Timer starts, no more calls...
// After 300ms of silence:
OUTPUT: Fetching: react
Only ONE API call instead of 5!
VS THROTTLE (common follow-up):
─────────────────────────────────
Debounce → "call only after silence of Xms"
Throttle → "call at most once every Xms, no matter what"
function throttle(fn, limit) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= limit) {
lastCall = now;
fn.apply(this, args);
}
};
}
USE CASES:
Debounce → Search bar, form validation, resize handler
Throttle → Scroll events, mousemove, button spam prevention
Question 3: Explain Promises and async/await
Q: What is the difference between Promise.all,
Promise.allSettled, Promise.race, and Promise.any?
ANSWER:
=========
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.reject("Error!");
// Promise.all → ALL must succeed. If ONE fails → reject!
Promise.all([p1, p2, p3])
.then(values => console.log(values))
.catch(err => console.log("Failed:", err));
OUTPUT: Failed: Error!
// Promise.allSettled → waits for ALL, doesn't reject on failure
Promise.allSettled([p1, p2, p3])
.then(results => console.log(results));
OUTPUT:
[
{ status: "fulfilled", value: 1 },
{ status: "fulfilled", value: 2 },
{ status: "rejected", reason: "Error!" }
]
// Promise.race → first one to settle (resolve OR reject) wins
Promise.race([p1, p2, p3]).then(v => console.log(v));
OUTPUT: 1 (p1 resolved first)
// Promise.any → first SUCCESS wins. Rejects if ALL fail
Promise.any([p3, p1, p2]).then(v => console.log(v));
OUTPUT: 1 (p1 is first success; p3 rejected but ignored)
WHEN TO USE:
Promise.all → Parallel API calls that ALL must succeed
(load user + posts + comments together)
Promise.allSettled → Show whatever loaded, show errors for rest
Promise.race → Timeout pattern (race fetch vs timeout)
Promise.any → Try multiple sources, use whichever responds first
Question 4: Node.js — What is the difference between process.nextTick and setImmediate?
Q: In Node.js, explain process.nextTick vs setImmediate
vs setTimeout with 0ms delay.
ANSWER:
=========
Node.js Event Loop phases:
timers → I/O → poll → check → close
process.nextTick() → runs BEFORE the next event loop phase
even before microtasks? No — it runs IN
a special "nextTick queue" that drains
after each operation, before microtasks!
setImmediate() → runs in the "check" phase of the event loop
(after I/O callbacks)
setTimeout(fn, 0) → runs in the "timers" phase
// Example
console.log("Start");
setTimeout(() => console.log("setTimeout"), 0);
setImmediate(() => console.log("setImmediate"));
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("Promise"));
console.log("End");
OUTPUT:
Start
End
nextTick
Promise
setImmediate
setTimeout (may swap with setImmediate — order not guaranteed in timers phase)
WHY nextTick before Promise?
process.nextTick queue drains BEFORE Promise microtasks in Node.js!
REAL WORLD:
process.nextTick → defer execution but before I/O
(e.g., emit events after constructor setup)
setImmediate → defer to next iteration of event loop
(e.g., break up CPU-intensive work)
Round 4 — React and Frontend System Design
Duration: 55–60 minutes | React deep dive + Design a scalable frontend system
React Question 1: What happens during React reconciliation?
Q: Explain React's reconciliation algorithm and the Virtual DOM.
ANSWER:
=========
Virtual DOM: React keeps a lightweight JS copy of the real DOM.
When state changes:
1. React creates a NEW Virtual DOM tree
2. DIFFS the new tree vs the old tree (reconciliation)
3. Calculates MINIMUM changes needed
4. Applies ONLY those changes to the real DOM
WHY? Real DOM operations are slow.
JS object comparison is fast.
React batches real DOM updates for performance.
Reconciliation Rules:
─────────────────────
1. Same element type → update props (no unmount/mount)
2. Different type → destroy old, create new subtree
3. Keys in lists → help React identify which item changed
// BAD — no keys, React can't track items
<ul>
{items.map(item => <li>{item.name}</li>)}
</ul>
// GOOD — keys help React diff correctly
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
// Using index as key — bad for dynamic lists!
// If you add/remove items, index shifts → wrong diffs
items.map((item, i) => <li key={i}>...</li>) // ❌ avoid for dynamic lists
React Question 2: useMemo vs useCallback
Q: What is the difference between useMemo and useCallback?
When would you use each?
ANSWER:
=========
useMemo → memoizes a COMPUTED VALUE
useCallback → memoizes a FUNCTION REFERENCE
// useMemo Example
function ProductList({ products, filterText }) {
// Without useMemo: recalculates on EVERY render
// With useMemo: recalculates ONLY when products or filterText changes
const filtered = useMemo(() => {
return products.filter(p =>
p.name.toLowerCase().includes(filterText.toLowerCase())
);
}, [products, filterText]);
return <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}
// useCallback Example
function Parent() {
const [count, setCount] = useState(0);
// Without useCallback: new function reference every render
// → Child always re-renders even if nothing changed!
const handleClick = useCallback(() => {
console.log("clicked");
}, []); // Stable reference — never recreated
return (
<div>
<button onClick={() => setCount(c => c + 1)}>{count}</button>
<ExpensiveChild onClick={handleClick} />
</div>
);
}
const ExpensiveChild = React.memo(({ onClick }) => {
console.log("Child rendered!");
return <button onClick={onClick}>Click me</button>;
});
// Without useCallback → Child renders on EVERY count change
// With useCallback → Child renders ONLY ONCE (function ref is stable)
SUMMARY:
useMemo → expensive calculations (filtering, sorting big arrays)
useCallback → stable function refs passed to memoized children
System Design Question: Design a Type-Ahead Search Component
Q: Design a production-ready type-ahead / autocomplete search
for an e-commerce site with millions of products.
Discuss component design, API calls, caching, and performance.
ANSWER WALKTHROUGH:
====================
1. COMPONENT ARCHITECTURE
───────────────────────────
<SearchBar>
├── <Input> ← controlled input
├── <SuggestionList> ← dropdown
│ └── <SuggestionItem> (× N)
└── <Spinner> ← loading state
State:
query → current input value
suggestions → array of results
isLoading → boolean
cache → Map() for memoizing results
2. DEBOUNCE API CALLS
───────────────────────────
const [query, setQuery] = useState("");
const [suggestions, setSuggestions] = useState([]);
const cache = useRef(new Map());
const fetchSuggestions = useCallback(
debounce(async (q) => {
if (q.length < 2) return setSuggestions([]);
// Check cache first!
if (cache.current.has(q)) {
return setSuggestions(cache.current.get(q));
}
const res = await fetch(`/api/search?q=${q}`);
const data = await res.json();
cache.current.set(q, data);
setSuggestions(data);
}, 300),
[]
);
useEffect(() => { fetchSuggestions(query); }, [query]);
3. HANDLE RACE CONDITIONS
───────────────────────────
// User types fast: "r" → "re" → "rea" → "react"
// Responses may come back OUT OF ORDER!
// "react" result arrives, then "re" result overwrites it → BUG!
// FIX: Use AbortController
const controllerRef = useRef(null);
const fetchSuggestions = async (q) => {
if (controllerRef.current) {
controllerRef.current.abort(); // Cancel previous request!
}
controllerRef.current = new AbortController();
const res = await fetch(`/api/search?q=${q}`, {
signal: controllerRef.current.signal
});
const data = await res.json();
setSuggestions(data);
};
4. KEYBOARD NAVIGATION + ACCESSIBILITY
───────────────────────────────────────
- Arrow Up/Down → navigate suggestions
- Enter → select highlighted suggestion
- Escape → close dropdown
- aria-role="combobox", aria-expanded, aria-activedescendant
- Screen reader announcements for result count
5. PERFORMANCE OPTIMIZATIONS
───────────────────────────────
- Debounce (300ms) → reduce API calls
- Client cache (Map) → instant results for repeated queries
- React.memo on SuggestionItem → avoid re-rendering all items
- Virtualize list if > 50 suggestions (react-window)
6. BACKEND / API
───────────────────────────
GET /api/search?q=react&limit=10
Response: { suggestions: ["React", "React Native", "ReactDOM"] }
Server-side: Elasticsearch / Redis prefix trie for fast lookups
CDN caching for popular queries
Rate limiting per user to prevent abuse
Round 5 — Bar Raiser Round (Leadership Principles)
The Bar Raiser is a senior Amazonian from a DIFFERENT team with veto power over your offer. This round is pure behavioral — and it's as important as all technical rounds combined.
Bar Raiser Goal:
=================
NOT just checking if you're good enough for this role.
They check: "Is this person better than 50% of current
Amazonians at this level?"
They will:
- Dig deeper with follow-up questions
- Challenge your answers ("What would you have done differently?")
- Look for ownership, metrics, and real impact
- Probe until they find a contradiction or confirm it's real
Formula: Strong LP = Offer even with mediocre code
Weak LP = No offer even with perfect code
Question 1: Customer Obsession
Q: Tell me about a time you went beyond what was required
to improve the customer experience.
STAR ANSWER:
──────────────
S — While working on an e-commerce checkout page, analytics
showed 34% cart abandonment rate on the payment step.
T — My task was to fix a bug in the coupon field, but I
noticed the real problem — the page had 12 form fields
and no progress indicator.
A — I didn't just fix the bug. I proposed a 3-step checkout
wizard with a progress bar. I built a prototype in 2 days
using React and showed it to the product team with data.
Got approval. Delivered in one sprint.
R — Cart abandonment dropped from 34% to 19% in 3 weeks.
Monthly revenue increased by ₹12 lakhs. This was later
rolled out across all product categories.
LP: Customer Obsession → I looked BEYOND my ticket to fix
the actual customer problem.
Question 2: Ownership
Q: Describe a situation where you took ownership of something
that wasn't your responsibility.
STAR ANSWER:
──────────────
S — Our backend team had a Node.js API that was returning
responses in 4–6 seconds for a search endpoint. Users
were complaining. The backend team was overloaded.
T — This was not my area — I'm a frontend developer. But
the user experience was suffering and the deadline was
in 3 days.
A — I profiled the API myself. Found that 3 database queries
were running sequentially instead of in parallel. Changed
them to Promise.all(). Also added Redis caching for
frequently searched terms. Raised a PR to the backend repo
with full documentation and benchmarks.
R — Response time dropped from 5.2 seconds to 380ms.
Senior engineers reviewed and merged it. The fix went live
in 2 days — before the deadline.
LP: Ownership → "Leaders don't say 'that's not my job.'"
Question 3: Dive Deep (Technical Leadership)
Q: Tell me about a time you had to deep-dive into a complex
technical problem to find the root cause.
STAR ANSWER:
──────────────
S — Production showed a memory leak in our React app. Memory
usage grew from 80MB to 800MB over 4 hours and then the
tab crashed. No obvious errors in the logs.
T — I was the only senior frontend dev available. Needed to
find and fix the root cause within the day.
A — Used Chrome DevTools → Memory tab → took heap snapshots
every 30 minutes. Compared snapshots and found thousands
of event listener objects were accumulating.
Root cause: a useEffect was adding a window scroll event
listener on EVERY render — but the cleanup function was
returning early due to a bug, so listeners were never removed.
useEffect(() => {
window.addEventListener("scroll", handleScroll);
// BUG: cleanup was inside an if-block that never ran!
return () => {
window.removeEventListener("scroll", handleScroll);
};
}); // ← missing dependency array → runs on every render!
Fix: Added dependency array [] so it runs once.
Verified: Memory stabilized at 85MB for 24 hours.
R — Zero crashes in production. Wrote internal doc on
React memory leak patterns. Shared with team in next sprint.
LP: Dive Deep + Learn and Be Curious
Question 4: Deliver Results
Q: Tell me about a time you delivered a project despite
facing major obstacles.
STAR ANSWER:
──────────────
S — We had a 6-week deadline to migrate a legacy jQuery app
to React. 3 weeks in, 2 of our 4 developers resigned.
T — I needed to deliver the migration with half the team
and without extending the deadline (client contract).
A — I immediately re-estimated and re-prioritized. Cut scope
to the 3 most critical modules (checkout, search, user profile).
Set up component library so any new developer could onboard
in 1 day. Worked with QA to automate regression tests so
we didn't spend time on manual testing.
R — Delivered all 3 critical modules on time. Deferred 2 less-
critical modules to next sprint with client agreement.
Post-launch: page load reduced from 6.8s to 1.9s.
Client extended the contract for 6 more months.
LP: Deliver Results + Bias for Action
Quick Recap — All Rounds
| Round | What's Tested | Key Topics | Duration |
|---|---|---|---|
| Round 0 Online Assessment |
Filter Round | HTML/CSS/JS MCQs, Machine Coding (Carousel) | 2 hours |
| Round 1 Phone Screen |
JS Basics + 1 LP | null/undefined, var/let/const, array flatten, STAR story | 45–60 min |
| Round 2 DSA Coding |
Algorithms | BFS, HashMap, Arrays, Trees, Graph traversal | 55–60 min |
| Round 3 JS / Node.js Deep Dive |
Core JavaScript + Node | Event Loop, Debounce/Throttle, Promises, nextTick | 55–60 min |
| Round 4 React + System Design |
React + Architecture | Reconciliation, useMemo/useCallback, Type-ahead design | 55–60 min |
| Round 5 Bar Raiser |
Leadership Principles | Ownership, Customer Obsession, Dive Deep, Deliver Results | 55–60 min |
Key Tips to Remember
- Every single round has LP questions — prepare 8–10 STAR stories before the interview
- Always include metrics in your answers — "dropped by 34%", "saved ₹12 lakhs", "from 5s to 380ms"
- Amazon loves Vanilla JS — don't depend on React for OA and machine coding rounds
- Think out loud — interviewers want to see how you reason, not just the final answer
- Microtasks before macrotasks — Promise.then runs before setTimeout in the event loop
- Debounce resets timer, Throttle limits frequency — know both implementations
- Always handle edge cases in DSA — empty input, single element, negative numbers
- STAR answers should be YOUR actions — use "I" not "we" in the Action step
- Bar Raiser has VETO POWER — treat this round as the most important one
- Promise.all vs allSettled — one fails on first rejection, other waits for all
- useCallback for function refs, useMemo for computed values — don't mix them up
- AbortController for cancelling stale fetch requests — shows production awareness
- Accessibility matters at Amazon — mention aria attributes in UI design answers
- Weak LP answers = no offer — even if your code was perfect
Keep coding, keep learning! This is the real Amazon experience — go crack it! See you in the next one!
Sources: Frontend Interview Handbook | GeeksforGeeks Amazon SDE-II Frontend | IGotAnOffer — Bar Raiser Guide | GreatFrontend Amazon Guide | Dev.to — Amazon SDE May 2024 Experience
Post a Comment