Amazon

Real Amazon Interview Experience

4 Rounds: Vanilla JS Machine Coding, DSA + JS Output, Frontend System Design & Bar Raiser

4
Rounds
3
Weeks Process
35-45 LPA
Package
FEE II
Bangalore
Vasanth

By Vasanth Bhat

Staff Software Engineer @ Walmart Global Tech

Mentored 100+ frontend developers through successful interviews

Round 1: Vanilla JS Machine Coding (60 mins)

On livecode.com. No IDE, no autocomplete, no React. Pure HTML, CSS, and vanilla JavaScript. They start with a base problem and keep extending it with follow-ups. You need to write clean, accessible, production-quality code without any framework.

šŸ“Œ Build a 5-Star Rating with Hover Preview and Committed Value

Difficulty: Medium | Time: 20 minutes (base) + extensions

Initial Requirements:
• 5 clickable stars
• Hover shows preview (highlight stars up to cursor)
• Click commits the rating
• Mouse leave reverts to committed value
šŸŽÆ Base Solution:
<!-- HTML -->
<div class="star-rating" role="radiogroup" aria-label="Rating">
  <span class="star" data-value="1">ā˜…</span>
  <span class="star" data-value="2">ā˜…</span>
  <span class="star" data-value="3">ā˜…</span>
  <span class="star" data-value="4">ā˜…</span>
  <span class="star" data-value="5">ā˜…</span>
</div>

<style>
  .star-rating { display: flex; gap: 4px; cursor: pointer; }
  .star { font-size: 2rem; color: #ddd; transition: color 0.1s; }
  .star.active, .star.hover { color: #FFD700; }
</style>

<script>
const container = document.querySelector('.star-rating');
const stars = container.querySelectorAll('.star');
let committedRating = 0;

function highlightStars(count, className) {
  stars.forEach((star, i) => {
    star.classList.toggle(className, i < count);
  });
}

container.addEventListener('mouseover', (e) => {
  const star = e.target.closest('.star');
  if (!star) return;
  const value = parseInt(star.dataset.value);
  highlightStars(value, 'hover');
});

container.addEventListener('mouseleave', () => {
  stars.forEach(star => star.classList.remove('hover'));
});

container.addEventListener('click', (e) => {
  const star = e.target.closest('.star');
  if (!star) return;
  committedRating = parseInt(star.dataset.value);
  highlightStars(committedRating, 'active');
});

// Initialize
highlightStars(committedRating, 'active');
</script>
Extension 1: Half-Star Support Using clip-path
<!-- Each star becomes two halves -->
<style>
  .star-container { position: relative; display: inline-block; font-size: 2rem; }
  .star-half {
    position: absolute; top: 0; left: 0;
    overflow: hidden; width: 50%;
    clip-path: inset(0 50% 0 0); /* Show only left half */
  }
  .star-full { color: #ddd; }
  .star-half.active, .star-full.active { color: #FFD700; }
</style>

<script>
// Track half values: 0.5, 1, 1.5, 2, ...
container.addEventListener('mousemove', (e) => {
  const star = e.target.closest('[data-value]');
  if (!star) return;

  const rect = star.getBoundingClientRect();
  const isLeftHalf = (e.clientX - rect.left) < rect.width / 2;
  const value = parseInt(star.dataset.value);
  const rating = isLeftHalf ? value - 0.5 : value;

  highlightStarsWithHalf(rating);
});

function highlightStarsWithHalf(rating) {
  stars.forEach((star, i) => {
    const fullValue = i + 1;
    const halfEl = star.querySelector('.star-half');
    const fullEl = star.querySelector('.star-full');

    if (fullValue <= rating) {
      // Full star
      fullEl.classList.add('active');
      halfEl.classList.add('active');
    } else if (fullValue - 0.5 === rating) {
      // Half star
      halfEl.classList.add('active');
      fullEl.classList.remove('active');
    } else {
      fullEl.classList.remove('active');
      halfEl.classList.remove('active');
    }
  });
}
</script>
Extension 2: Keyboard Support with ARIA
<div class="star-rating" role="radiogroup" aria-label="Rating"
     tabindex="0" aria-valuenow="0" aria-valuemin="0" aria-valuemax="5">
  <!-- stars -->
</div>

<script>
container.setAttribute('tabindex', '0');

container.addEventListener('keydown', (e) => {
  switch (e.key) {
    case 'ArrowRight':
    case 'ArrowUp':
      e.preventDefault();
      committedRating = Math.min(5, committedRating + 0.5);
      break;
    case 'ArrowLeft':
    case 'ArrowDown':
      e.preventDefault();
      committedRating = Math.max(0, committedRating - 0.5);
      break;
    case 'Home':
      e.preventDefault();
      committedRating = 0;
      break;
    case 'End':
      e.preventDefault();
      committedRating = 5;
      break;
  }

  container.setAttribute('aria-valuenow', committedRating);
  highlightStarsWithHalf(committedRating);
});

// Screen reader announcement
container.setAttribute('role', 'slider');
container.setAttribute('aria-valuemin', '0');
container.setAttribute('aria-valuemax', '5');
container.setAttribute('aria-valuenow', committedRating);
container.setAttribute('aria-label', 'Star rating');
</script>
What Amazon Evaluates:
• Can you build without frameworks? (Core JS/DOM knowledge)
• Event delegation vs individual listeners
• Accessibility (ARIA, keyboard) — this is non-negotiable at Amazon
• Progressive enhancement — base works, extensions layer on top

šŸ“Œ Variant: Accordion with Single-Open & Multi-Open Mode

Difficulty: Medium | Time: 25 minutes

Requirements:
• Click header to expand/collapse content
• Single-open mode: only one panel open at a time
• Multi-open mode: any number of panels can be open
• Smooth height animation
• Keyboard accessible (Enter/Space to toggle)
šŸŽÆ Solution:
class Accordion {
  constructor(container, { mode = 'single' } = {}) {
    this.container = container;
    this.mode = mode; // 'single' or 'multi'
    this.panels = container.querySelectorAll('.accordion-panel');
    this.init();
  }

  init() {
    this.panels.forEach((panel) => {
      const header = panel.querySelector('.accordion-header');
      const content = panel.querySelector('.accordion-content');

      // Set initial state
      content.style.maxHeight = '0';
      content.style.overflow = 'hidden';
      content.style.transition = 'max-height 0.3s ease';

      header.setAttribute('role', 'button');
      header.setAttribute('tabindex', '0');
      header.setAttribute('aria-expanded', 'false');

      header.addEventListener('click', () => this.toggle(panel));
      header.addEventListener('keydown', (e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          e.preventDefault();
          this.toggle(panel);
        }
      });
    });
  }

  toggle(panel) {
    const content = panel.querySelector('.accordion-content');
    const header = panel.querySelector('.accordion-header');
    const isOpen = panel.classList.contains('open');

    if (this.mode === 'single' && !isOpen) {
      // Close all others first
      this.panels.forEach((p) => {
        if (p !== panel) this.close(p);
      });
    }

    if (isOpen) {
      this.close(panel);
    } else {
      panel.classList.add('open');
      content.style.maxHeight = content.scrollHeight + 'px';
      header.setAttribute('aria-expanded', 'true');
    }
  }

  close(panel) {
    const content = panel.querySelector('.accordion-content');
    const header = panel.querySelector('.accordion-header');
    panel.classList.remove('open');
    content.style.maxHeight = '0';
    header.setAttribute('aria-expanded', 'false');
  }
}

// Usage
const el = document.querySelector('.accordion');
const accordion = new Accordion(el, { mode: 'single' });

// Switch mode dynamically
// accordion.mode = 'multi';

šŸ“Œ Variant: Relative Time Widget

Difficulty: Medium | Time: 15 minutes

Requirements:Display "just now", "n minutes ago", "n days ago", "n years ago" from a timestamp.
function getRelativeTime(timestamp) {
  const now = Date.now();
  const diff = now - new Date(timestamp).getTime();

  const seconds = Math.floor(diff / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);
  const months = Math.floor(days / 30);
  const years = Math.floor(days / 365);

  if (seconds < 60) return 'just now';
  if (minutes < 60) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
  if (hours < 24) return `${hours} hour${hours > 1 ? 's' : ''} ago`;
  if (days < 30) return `${days} day${days > 1 ? 's' : ''} ago`;
  if (months < 12) return `${months} month${months > 1 ? 's' : ''} ago`;
  return `${years} year${years > 1 ? 's' : ''} ago`;
}

// Auto-updating widget
class RelativeTimeWidget {
  constructor(element) {
    this.element = element;
    this.timestamp = element.getAttribute('data-timestamp');
    this.update();
    this.startAutoUpdate();
  }

  update() {
    this.element.textContent = getRelativeTime(this.timestamp);
    this.element.setAttribute('title', new Date(this.timestamp).toLocaleString());
  }

  startAutoUpdate() {
    // Update every minute for recent, less for older
    const diff = Date.now() - new Date(this.timestamp).getTime();
    const interval = diff < 3600000 ? 60000 : 3600000; // 1min or 1hr

    this.timer = setInterval(() => this.update(), interval);
  }

  destroy() {
    clearInterval(this.timer);
  }
}

// Usage
// <time data-timestamp="2026-06-22T10:30:00Z" class="relative-time"></time>
document.querySelectorAll('.relative-time').forEach(el => {
  new RelativeTimeWidget(el);
});

šŸ’” Interview Tips for Round 1:

  • No React allowed: Practice building components with vanilla JS, addEventListener, and DOM manipulation
  • Accessibility is mandatory: Amazon cares deeply about a11y — always add ARIA attributes and keyboard support
  • Event delegation:Use it. Don't attach listeners to every element individually.
  • CSS matters: clip-path, transitions, flexbox — know them without looking up docs
  • 60 minutes goes fast: Get the base working in 15-20 min, then handle extensions

Amazon's machine coding is pure vanilla JS. If you can't build it without React, you're not ready. Master DOM manipulation and vanilla JS patterns →

Round 2: DSA + JS Output (60 mins)

Starts with 15 minutes of behavioral questions, then moves to DSA on a shared document. They also ask JS output questions to test your understanding of the language fundamentals.

1ļøāƒ£ Row with Maximum Ones in a Row-Sorted Binary Matrix

Platform: LeetCode | Difficulty: Medium | Time: 15 min

Problem Statement:
Given an mƗn binary matrix where each row is sorted (all 0s before all 1s), find the row with the maximum number of 1s.
Input: [[0,0,1,1], [0,1,1,1], [0,0,0,1], [0,0,1,1]]
Output: 1 (row index 1 has 3 ones — maximum)
šŸŽÆ Optimal Solution — Staircase Walk: O(m + n)
function rowWithMaxOnes(matrix) {
  const rows = matrix.length;
  const cols = matrix[0].length;

  let maxRow = -1;
  let col = cols - 1; // Start top-right corner

  for (let row = 0; row < rows; row++) {
    // Move left while we see 1s
    while (col >= 0 && matrix[row][col] === 1) {
      col--;
      maxRow = row;
    }
  }

  return maxRow;
}

// How it works:
// Start at top-right. If current cell is 1, move left (this row has more 1s).
// If current cell is 0, move down (this row can't beat current best).
// The "staircase" path guarantees we visit at most m + n cells.

// Time: O(m + n) — much better than O(m * log n) binary search approach
// Space: O(1)

// Test
console.log(rowWithMaxOnes([
  [0, 0, 1, 1],
  [0, 1, 1, 1],  // ← This row (index 1) has max ones
  [0, 0, 0, 1],
  [0, 0, 1, 1]
])); // Output: 1
Alternative approaches:
• Brute force: O(m Ɨ n) — count ones in each row
• Binary search for first 1: O(m Ɨ log n) — good but not optimal
• Staircase walk: O(m + n) — best, leverages sorted property

2ļøāƒ£ Clone a Directed Graph (LeetCode 133)

Platform: LeetCode | Difficulty: Medium | Time: 15 min

Problem Statement:
Given a reference to a node in a connected directed graph, return a deep copy (clone) of the graph. Each node contains a value and a list of its neighbors.šŸŽÆ Solution — BFS with HashMap:
class GraphNode {
  constructor(val, neighbors = []) {
    this.val = val;
    this.neighbors = neighbors;
  }
}

function cloneGraph(node) {
  if (!node) return null;

  const visited = new Map(); // original → clone mapping
  const queue = [node];

  // Create clone of starting node
  visited.set(node, new GraphNode(node.val));

  while (queue.length > 0) {
    const current = queue.shift();

    for (const neighbor of current.neighbors) {
      if (!visited.has(neighbor)) {
        // Clone unvisited neighbor
        visited.set(neighbor, new GraphNode(neighbor.val));
        queue.push(neighbor);
      }
      // Connect clone's neighbor
      visited.get(current).neighbors.push(visited.get(neighbor));
    }
  }

  return visited.get(node);
}

// DFS alternative (recursive):
function cloneGraphDFS(node, visited = new Map()) {
  if (!node) return null;
  if (visited.has(node)) return visited.get(node);

  const clone = new GraphNode(node.val);
  visited.set(node, clone);

  for (const neighbor of node.neighbors) {
    clone.neighbors.push(cloneGraphDFS(neighbor, visited));
  }

  return clone;
}

// Time: O(V + E) — visit every vertex and edge once
// Space: O(V) — HashMap stores all nodes
Key Insight: The HashMap prevents infinite loops (handles cycles) and ensures each node is cloned exactly once.

3ļøāƒ£ JS Output: Closures Inside a for Loop — var vs let

Question:What's the output?
// With var
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log('var:', i), 100);
}

// With let
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log('let:', j), 100);
}

// Output:
// var: 3
// var: 3
// var: 3
// let: 0
// let: 1
// let: 2
Why:
• var — function-scoped. All 3 closures share the SAME variable. By the time setTimeout fires, i is already 3.
• let — block-scoped. Each iteration gets its OWN copy of j. The closure captures the value at that iteration.
Fix for var (classic interview follow-up):
// Fix 1: IIFE
for (var i = 0; i < 3; i++) {
  ((index) => {
    setTimeout(() => console.log(index), 100);
  })(i);
}

// Fix 2: setTimeout's third argument
for (var i = 0; i < 3; i++) {
  setTimeout((index) => console.log(index), 100, i);
}

4ļøāƒ£ JS Output: setTimeout, Promise.then, async/await Order

Question:What's the output order?
console.log('start');

setTimeout(() => console.log('timeout'), 0);

Promise.resolve()
  .then(() => {
    console.log('promise 1');
    return Promise.resolve();
  })
  .then(() => console.log('promise 2'));

async function run() {
  console.log('async start');
  await Promise.resolve();
  console.log('async end');
}

run();

console.log('end');
Output:
start → async start → end → promise 1 → async end → promise 2 → timeout
Rule: Synchronous → Microtasks (Promises, await) → Macrotasks (setTimeout)

Each await and .then() schedules the continuation as a microtask. All microtasks drain before the next macrotask.

5ļøāƒ£ __proto__ vs prototype vs Object.create

// prototype — property on constructor FUNCTIONS
function Dog(name) { this.name = name; }
Dog.prototype.bark = function() { return this.name + ' barks'; };

// __proto__ — internal link on every OBJECT (instance)
const rex = new Dog('Rex');
rex.__proto__ === Dog.prototype;           // true
rex.__proto__.__proto__ === Object.prototype; // true (chain ends here)
rex.__proto__.__proto__.__proto__ === null;   // true (end of chain)

// Object.create — creates object with specified prototype
const animal = { breathe() { return 'breathing'; } };
const cat = Object.create(animal);
cat.breathe(); // 'breathing' (inherited via prototype chain)
cat.__proto__ === animal; // true

// Summary:
// prototype   → exists on functions, shared by all instances made with 'new'
// __proto__   → exists on objects, points to constructor's prototype (use Object.getPrototypeOf)
// Object.create → manually sets __proto__ without using new/constructor

šŸ’” Interview Tips for Round 2:

  • Say complexity first: Before writing code, state the time and space complexity of your approach
  • DSA topics that repeat: Trees, matrices, arrays, and graphs — practice these heavily
  • JS output questions: Practice event loop, closures, hoisting, and this binding
  • Think out loud: Explain your thought process — they want to see how you reason
  • Behavioral (15 min): Use STAR format, keep answers under 2 minutes, use numbers

DSA is non-negotiable at Amazon. Trees, matrices, and graph problems come up in every single loop. Get structured DSA practice with interview patterns →

Round 3: Frontend System Design (60 mins)

On a Miro board. Component tree first, API second. They want to see you think at scale — not just build a page, but design a system that can handle millions of users, dynamic content, and real-time updates.

šŸ“Œ Design the Home Page of a News Site (like Times of India)

Difficulty: Hard | Time: 60 minutes

Step 1: Clarify Requirements
Functional:
• Multiple content types: articles, videos, ads
• Category-based sections (Top Stories, Sports, Tech, etc.)
• Infinite scroll / pagination
• Breaking news banner (real-time)
• Responsive layout

Non-Functional:
• Fast first load (LCP < 2.5s)
• Millions of users, high traffic spikes on breaking news
• SEO critical (news must be indexed)
• Ads must not block content rendering
Step 2: Component Architecture
// Component Tree
<HomePage>
  <BreakingNewsBanner />      // WebSocket/SSE for real-time
  <NavigationBar />
  <HeroSection />             // Top 3-5 stories, above the fold
  <ContentFeed>
    <FeedSection category="top-stories">
      <ContentCard type="article" />
      <ContentCard type="video" />
      <ContentCard type="ad" />     // Discriminator-based rendering
    </FeedSection>
    <FeedSection category="sports" />
    <FeedSection category="tech" />
    <InfiniteScrollTrigger />       // Intersection Observer
  </ContentFeed>
  <Sidebar>
    <TrendingWidget />
    <WeatherWidget />
  </Sidebar>
</HomePage>
Step 3: Card Schema with Discriminator Field
// Unified card schema — type field determines rendering
interface BaseCard {
  id: string;
  type: 'article' | 'video' | 'ad';   // Discriminator
  position: number;
  timestamp: string;
}

interface ArticleCard extends BaseCard {
  type: 'article';
  headline: string;
  summary: string;
  thumbnail: string;
  author: string;
  category: string;
  readTime: number;
}

interface VideoCard extends BaseCard {
  type: 'video';
  title: string;
  duration: number;
  thumbnailUrl: string;
  hlsUrl: string;
}

interface AdCard extends BaseCard {
  type: 'ad';
  adProvider: string;
  adSlotId: string;
  size: 'banner' | 'medium-rect' | 'native';
}

type FeedCard = ArticleCard | VideoCard | AdCard;

// Renderer uses discriminator to pick component
function CardRenderer({ card }: { card: FeedCard }) {
  switch (card.type) {
    case 'article': return <ArticleCardComponent data={card} />;
    case 'video': return <VideoCardComponent data={card} />;
    case 'ad': return <AdCardComponent data={card} />;
  }
}
Step 4: Cursor-Based Pagination + Infinite Scroll
// API Design — cursor-based (not offset-based)
// GET /api/feed?cursor=abc123&limit=20&category=top-stories

// Response:
{
  "items": [...FeedCard],
  "nextCursor": "xyz789",    // Opaque cursor for next page
  "hasMore": true
}

// Why cursor > offset:
// - Offset breaks when new items are inserted (duplicates/skips)
// - Cursor is stable even when feed changes
// - Better for real-time content where items are constantly added

// Client implementation with Intersection Observer
function useInfiniteScroll(fetchFn) {
  const [items, setItems] = useState([]);
  const [cursor, setCursor] = useState(null);
  const [hasMore, setHasMore] = useState(true);
  const observerRef = useRef(null);

  const loadMore = useCallback(async () => {
    const { items: newItems, nextCursor, hasMore } = await fetchFn(cursor);
    setItems(prev => [...prev, ...newItems]);
    setCursor(nextCursor);
    setHasMore(hasMore);
  }, [cursor]);

  // Intersection Observer for trigger element
  const lastItemRef = useCallback((node) => {
    if (observerRef.current) observerRef.current.disconnect();
    observerRef.current = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting && hasMore) loadMore();
    }, { rootMargin: '200px' }); // Pre-fetch 200px before visible
    if (node) observerRef.current.observe(node);
  }, [hasMore, loadMore]);

  return { items, lastItemRef, hasMore };
}
Step 5: SSR vs Client Rendering Decision
SSR (Server-Side Render):
• Above-the-fold content (hero, top stories) — SEO + fast FCP
• Article content pages — must be crawlable
• Meta tags and structured data

Client Render:
• Infinite scroll (subsequent pages) — loaded on demand
• Ads — loaded async, shouldn't block SSR
• Interactive widgets (weather, trending) — personalized
• Breaking news banner — WebSocket updates

Hybrid: SSR first page + client-side hydration + client fetch for pagination
Step 6: Breaking News Banner — Ship Within Seconds
// Architecture for real-time breaking news:

// Option 1: Server-Sent Events (SSE) — simpler, one-directional
const eventSource = new EventSource('/api/breaking-news/stream');
eventSource.onmessage = (event) => {
  const news = JSON.parse(event.data);
  showBreakingBanner(news);
};

// Option 2: WebSocket — bidirectional, if needed
const ws = new WebSocket('wss://api.example.com/breaking');
ws.onmessage = (event) => {
  const news = JSON.parse(event.data);
  showBreakingBanner(news);
};

// Backend flow:
// 1. Editor publishes breaking news via CMS
// 2. CMS triggers event to pub/sub (Redis/Kafka)
// 3. WebSocket server receives event, broadcasts to all connected clients
// 4. Client receives, shows banner with animation
// Total latency: < 2 seconds end-to-end

// Fallback for disconnected users:
// - Poll /api/breaking-news every 30s
// - Service Worker push notification
// - On reconnect, fetch latest breaking news
Lazy Loading Images:
// Native lazy loading (simplest)
<img src="article.jpg" loading="lazy" alt="..." />

// With blur-up placeholder pattern:
// 1. Serve tiny base64 thumbnail inline (< 1KB)
// 2. Use Intersection Observer to load full image
// 3. Crossfade from placeholder to full image

// Priority hints for above-the-fold:
<img src="hero.jpg" fetchpriority="high" alt="..." />    // Above fold
<img src="article.jpg" loading="lazy" alt="..." />        // Below fold

šŸ’” System Design Tips for Amazon:

  • Start with requirements: Functional → Non-functional → Constraints. Spend 5 minutes here.
  • Component tree first, API second:This is Amazon's preferred order. Show the visual hierarchy.
  • Think about scale: How does this work with 10M users? What breaks? Where do you cache?
  • SSR vs CSR:Always justify your choice. "SEO needs SSR, personalization needs CSR."
  • Performance budget: Mention LCP, FID, CLS. Show you think about Core Web Vitals.

Frontend System Design at Amazon is about thinking at scale — not just components, but architecture decisions that impact millions. Practice system design with expert feedback →

Round 4: Bar Raiser (60 mins)

Behavioral questions mapped to Amazon's 16 Leadership Principles, plus one DSA follow-up. The Bar Raiser is a senior interviewer from a different team whose job is to ensure the hiring bar stays high. This round is veto-capable — a "no" here overrides all other rounds.

1ļøāƒ£ Tell me about a time you disagreed with your tech lead

Leadership Principle: Have Backbone; Disagree and Commit

What they look for:
• You can respectfully challenge with data
• You don't just go along to avoid conflict
• Once a decision is made, you commit fully even if you disagree
• You focus on what's best for the customer/product
STAR structure:
Situation: What was being decided, stakes, your role
Task: Why you disagreed, what evidence you had
Action: How you raised it, what alternative you proposed, how the conversation went
Result: What was the outcome, what did you learn

2ļøāƒ£ A project where you delivered under a tight deadline

Leadership Principle: Deliver Results / Bias for Action

Key elements to include:
• What was the deadline and why was it tight?
• What trade-offs did you make? (scope, quality, approach)
• How did you prioritize?
• Did you cut corners or find a creative solution?
• Quantify: "Delivered 2 days early" or "Shipped to 500K users on day 1"
Avoid: Stories where you just worked overtime. They want to hear about smart decisions — what you chose NOT to do is often more interesting.

3ļøāƒ£ A time you took ownership outside your scope

Leadership Principle: Ownership

What makes a great answer:
• You noticed a problem nobody was solving
• You didn't wait for permission or assignment
• The impact was measurable
• It was genuinely outside your job description

Examples that work well:
• Fixed a production bug in a service you don't own
• Set up monitoring/alerting for the team
• Improved CI/CD pipeline that was slowing everyone down
• Mentored a struggling teammate without being asked

4ļøāƒ£ A launch that failed. What did you learn?

Leadership Principle: Learn and Be Curious / Invent and Simplify

Framework:
1. What launched and why it failed — be specific and honest
2. Your role in the failure — take genuine accountability
3. Root cause — what was the real reason (not just symptoms)
4. Learning — what changed in your approach after this
5. Prevention — what systems did you put in place
Pro Tip:Amazon wants genuine failure stories, not "I worked too hard" or "I was too detail-oriented." Real failures with real learnings show maturity and growth mindset.

5ļøāƒ£ Follow-up DSA: Lowest Common Ancestor in a Binary Tree (LC Medium)

Platform: LeetCode 236 | Difficulty: Medium | Time: 15 min

Problem: Given a binary tree and two nodes p and q, find their lowest common ancestor (the deepest node that is an ancestor of both).
function lowestCommonAncestor(root, p, q) {
  // Base cases
  if (!root) return null;
  if (root === p || root === q) return root;

  // Search in left and right subtrees
  const left = lowestCommonAncestor(root.left, p, q);
  const right = lowestCommonAncestor(root.right, p, q);

  // If both sides return non-null, current node is the LCA
  if (left && right) return root;

  // Otherwise, LCA is on whichever side returned non-null
  return left || right;
}

// How it works:
// 1. If current node IS p or q, return it
// 2. Recurse left and right
// 3. If BOTH sides found something → current node is the LCA
// 4. If only ONE side found → propagate that up (LCA is deeper)

// Time: O(n) — visit each node once
// Space: O(h) — recursion stack, h = height of tree

// Example:
//        3
//       / \
//      5   1
//     / \
//    6   2
//
// LCA(5, 1) = 3  (split at root)
// LCA(5, 6) = 5  (5 is ancestor of 6)
Why Amazon Asks This:
āœ“ Tests recursive thinking on trees
āœ“ Clean, concise solution shows clarity of thought
āœ“ Common follow-ups: BST version (easier), iterative with parent pointers

šŸ’” Bar Raiser Tips:

  • Prepare 8-10 stories: Map them to different Leadership Principles. One story can cover multiple LPs.
  • Use numbers in EVERY answer:"40% faster" beats "we improved it." "Saved 3 hours/week for 12 engineers" beats "improved process."
  • Keep answers under 2 minutes:They will ask follow-ups. Don't monologue.
  • "I" not "we": They want YOUR contribution. Be specific about what YOU did.
  • The DSA follow-up: Usually a medium-level tree/graph problem. Practice LCA, BST operations, and BFS/DFS.

The Bar Raiser has veto power. Your behavioral stories need to be as prepared as your code. Practice mock behavioral interviews with structured feedback →

Tips That Actually Help at Amazon

DSA is a must

Trees, matrices, and arrays come up in every loop. Practice at least 2 medium problems daily for 4 weeks.

Time yourself building components

60 minutes goes fast. Practice star rating, accordion, carousel in vanilla JS without any references.

Use numbers in every answer

"40 percent faster" beats "we improved it". Quantify impact in all behavioral stories.

In system design: requirements first

Start with requirements, then components, then API. Amazon loves structured thinking.

Say time/space complexity first

Before writing any code, state the complexity of your approach. This shows you think before you code.

Know the Leadership Principles

The Bar Raiser maps every question to an LP. Have 2 stories per principle ready to go.

Ready to Crack Your Amazon Interview?

Join our cohort and get structured preparation with 1-on-1 guidance from a Staff Engineer who has mentored 100+ developers.

Join Next CohortContact Us
← Back to Interview Experiences