Uber Software Engineer II(Frontend) Interview Experience

Understanding the Interview Structure

When developers prepare for Big Tech interviews, most focus on LeetCode grinding and system design patterns. While these are important, Uber’s SDE II process tests a broader set of skills that reflect what senior engineers actually do in production.

The interview consists of four distinct rounds, each evaluating different dimensions of engineering capability.

Round 1: Online Screening

Format: CodeSignal assessment
Components: 2 coding problems + 8 MCQs
Focus Areas: Arrays, graphs, JS quirks, web performance, browser behavior

Sample Question Types

JavaScript Quirks:

  • “What’s the difference between const and let hoisting behavior?"
  • “How does the event loop handle microtasks vs macrotasks?”
  • “Explain the behavior of this in arrow functions vs regular functions"

Web Performance:

  • “What triggers browser reflow and how can it be minimized?”
  • “Explain the difference between debouncing and throttling”
  • “What are the various strategies for optimizing bundle size?”

Browser Behavior:

  • “How does event delegation work and when should it be used?”
  • “Explain the browser’s critical rendering path”
  • “What’s the difference between localStorage, sessionStorage, and cookies?”

Why This Round Matters

Uber serves millions of users globally with strict performance requirements. Frontend engineers need to understand:

  • How their JavaScript code actually executes
  • What causes performance bottlenecks in the browser
  • How to optimize for real-world constraints

Basic React knowledge isn’t enough. Understanding browser fundamentals is essential.

Round 2: Machine Coding — Real-World Problem Solving

This round has two distinct parts, each testing different aspects of engineering maturity.

Part 1: Project Deep Dive

Format: Discussion about past work
Focus: Optimizations, performance fixes, engineering decisions

Questions Asked:

  • “Tell me about a performance issue you encountered and how you fixed it”
  • “How did you approach optimizing this component?”
  • “What was the biggest technical challenge in this project?”
  • “If you were to rebuild this, what would you do differently?”

What’s Being Evaluated:

This conversation goes beyond resume verification. Interviewers are assessing:

  • Depth of technical understanding
  • Ability to articulate complex problems clearly
  • Evidence of actually solving production issues
  • How candidates think about optimization and trade-offs

The key insight: Candidates who can deeply explain their engineering decisions demonstrate senior-level thinking. Those who give surface-level answers reveal limited real-world experience.

Part 2: Grid Light Box Challenge

The Problem: Build a grid of clickable lights in React. When a light is clicked, it activates. When another light is clicked, lights deactivate in reverse order of activation.

Why This Problem Is Brilliant:

At first glance, it seems simple. But it tests multiple critical skills:

State Management: How do candidates track activation order? Do they use arrays, sets, or other data structures? How do they manage state updates efficiently?

React Patterns: Do they understand hooks correctly? Are they using useCallback and useMemo appropriately? Do they avoid unnecessary re-renders?

Logic Implementation: Can they correctly implement reverse-order (LIFO) deactivation? Do they handle edge cases like clicking the same light twice?

Clarifying Requirements: The problem statement is intentionally ambiguous. Do candidates ask questions like:

  • “Should only one light be active at a time?”
  • “What happens if the same light is clicked repeatedly?”
  • “Should there be a maximum number of active lights?”

Implementation Approach:

function GridLightBox() {
  const [activeLights, setActiveLights] = useState([]);
  const handleLightClick = useCallback((id) => {
    setActiveLights(prev => {
      // Check if already active
      if (prev.includes(id)) {
        return prev.filter(light => light !== id);
      }
      // Add to activation stack
      return [...prev, id];
    });
  }, []);
  const deactivateLast = useCallback(() => {
    setActiveLights(prev => prev.slice(0, -1));
  }, []);
  return (
    <div>
      {/* Grid implementation */}
    </div>
  );
}

What Strong Candidates Do:

  • Ask clarifying questions before coding
  • Discuss trade-offs between different approaches
  • Consider performance implications
  • Handle edge cases explicitly
  • Communicate their thinking process

Round 3: JavaScript Deep Dive — Production Patterns

Challenge: Implement async memoization for a function with callbacks

Requirements:

  • Cache function results
  • Handle deep equality (not shallow comparison)
  • Manage parallel API calls correctly
  • Work with callback-based async patterns

Why This Tests Senior-Level Skills

Async memoization isn’t a theoretical exercise. It’s used in production for:

  • Preventing duplicate API requests
  • Caching expensive computations
  • Optimizing performance-critical paths
  • Managing complex async flows

Implementation Approach

Basic Version:

function memoizeAsync(fn) {
  const cache = new Map();

  return function(...args) {
      const key = JSON.stringify(args);
      if (cache.has(key)) {
        return Promise.resolve(cache.get(key));
      }
      const promise = fn.apply(this, args);
      cache.set(key, promise);
      return promise;
    };
}

Production-Ready Version (handles parallel requests):

function memoizeAsync(fn) {
  const cache = new Map();
  const pending = new Map();
  return function(...args) {
    const key = JSON.stringify(args);
    // Return cached result
    if (cache.has(key)) {
      return Promise.resolve(cache.get(key));
    }
    // Return pending promise if request in flight
    if (pending.has(key)) {
      return pending.get(key);
    }
    // Execute new request
    const promise = fn.apply(this, args)
      .then(result => {
        cache.set(key, result);
        pending.delete(key);
        return result;
      })
      .catch(error => {
        pending.delete(key);
        throw error;
      });
    pending.set(key, promise);
    return promise;
  };
}

The Deeper Evaluation

This round reveals whether candidates:

  • Have built production systems with complex async requirements
  • Understand JavaScript at a deep level (not just surface syntax)
  • Think about edge cases and failure modes
  • Can implement patterns they’ll actually use at Uber

Round 4: DSA — Algorithmic Thinking at Scale

Problem: “Zombie Spread in a Country”

Scenario: Grid-based world where some cells start infected (zombies). Infection spreads to adjacent cells each hour. Given starting positions and target time, determine which cells are infected.

Algorithm: Multi-source Breadth-First Search (BFS)

Why This Problem Matters

While this seems like a standard graph problem, it actually models real-world scenarios Uber deals with:

  • Disease/infection spread (similar to COVID tracking systems)
  • Service area expansion over time
  • Network propagation problems
  • Geographic coverage analysis

Solution Approach

function zombieSpread(grid, zombies, hours) {
  const rows = grid.length;
  const cols = grid[0].length;
  const queue = [];
  const infected = new Set();
  // Initialize with all zombie positions (multi-source BFS)
  for (const [r, c] of zombies) {
    queue.push([r, c, 0]);
    infected.add(`${r},${c}`);
  }
  const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];
  while (queue.length > 0) {
    const [row, col, time] = queue.shift();
    // Stop if we've exceeded the time limit
    if (time >= hours) continue;
    // Spread infection to adjacent cells
    for (const [dr, dc] of directions) {
      const newRow = row + dr;
      const newCol = col + dc;
      const key = `${newRow},${newCol}`;
      // Check boundaries and if already infected
      if (newRow >= 0 && newRow < rows && 
          newCol >= 0 && newCol < cols && 
          !infected.has(key)) {
        infected.add(key);
        queue.push([newRow, newCol, time + 1]);
      }
    }
  }
  return infected;
}

Key Takeaways

Before the Interview:

1. Build Real Projects Don’t just do tutorials. Build something with scale constraints:

  • Performance requirements
  • Complex async operations
  • State management challenges
  • Real user interactions

2. Understand Fundamentals Deeply Study:

  • How browsers actually work
  • JavaScript execution model
  • Web performance optimization
  • Common production patterns

3. Practice Articulation Be able to explain:

  • Why you made specific decisions
  • Trade-offs you considered
  • How you approached optimization
  • What you learned from failures

During the Interview:

1. Ask Questions Before solving, clarify:

  • Requirements and constraints
  • Expected edge cases
  • Performance expectations
  • User experience considerations

2. Communicate Thinking Don’t code silently. Explain:

  • Your approach and why
  • Alternatives you’re considering
  • Trade-offs you see
  • Assumptions you’re making

3. Handle Ambiguity When requirements are vague:

  • Make reasonable assumptions
  • State them explicitly
  • Ask if they align with expectations
  • Show you can work with uncertainty

After the Interview:

1. Reflect on Performance Identify:

  • Which rounds felt strong
  • Where you struggled
  • What knowledge gaps emerged
  • How to improve

2. Learn from Feedback If feedback is provided:

  • Take it seriously
  • Address specific weaknesses
  • Practice those areas
  • Apply lessons to future interviews

Final Thoughts

Big Tech interviews at the SDE II level aren’t just about coding ability. They’re comprehensive evaluations of:

  • Technical depth across multiple dimensions
  • Production problem-solving capability
  • Communication and collaboration skills
  • Ability to handle complexity and ambiguity

Understanding what each round actually tests helps candidates:

  • Prepare more effectively
  • Perform more confidently
  • Learn from the experience
  • Improve for future opportunities

The goal isn’t to “crack the interview.” It’s to develop the skills that make someone effective at building production systems at scale.

 

Anil Peddireddy

Written by Anil Peddireddy


Comments ...


No Comments Yet ...Add One