5 Rounds: Coding, Frontend, Machine Coding, System Design, Behavioral
Staff Software Engineer @ Walmart Global Tech
Mentored 100+ frontend developers through successful interviews
Medium-Hard DSA problem. Focus: Clean code, optimal solution, communication.
Platform: LeetCode | Difficulty: Hard | Time: 35-40 min
LRUCache cache = new LRUCache(2);
cache.put(1, 1); // cache is {1=1}
cache.put(2, 2); // cache is {1=1, 2=2}
cache.get(1); // returns 1, cache is {2=2, 1=1} (1 is now most recent)
cache.put(3, 3); // capacity exceeded, evict key 2 (least recently used)
// cache is {1=1, 3=3}
cache.get(2); // returns -1 (not found)
π Why This is Hard:
class Node {
constructor(key, value) {
this.key = key;
this.value = value;
this.prev = null;
this.next = null;
}
}
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
// Dummy nodes for easy manipulation
this.head = new Node(0, 0);
this.tail = new Node(0, 0);
this.head.next = this.tail;
this.tail.prev = this.head;
}
addToHead(node) {
node.next = this.head.next;
node.prev = this.head;
this.head.next.prev = node;
this.head.next = node;
}
removeNode(node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
moveToHead(node) {
this.removeNode(node);
this.addToHead(node);
}
get(key) {
if (!this.cache.has(key)) return -1;
const node = this.cache.get(key);
this.moveToHead(node);
return node.value;
}
put(key, value) {
if (this.cache.has(key)) {
const node = this.cache.get(key);
node.value = value;
this.moveToHead(node);
} else {
const newNode = new Node(key, value);
this.cache.set(key, newNode);
this.addToHead(newNode);
if (this.cache.size > this.capacity) {
const leastUsed = this.tail.prev;
this.removeNode(leastUsed);
this.cache.delete(leastUsed.key);
}
}
}
}
// Time: O(1) for both get and put
// Space: O(capacity)
Why Uber Asks This:At Uber's scale, efficiency matters. Between you and this round is seeing patterns instantlyβwhen hash maps work, when graphs shine, when sorting matters. Learn to see like they do β
10+ questions covering React, JavaScript, performance, and browser concepts.
// β Memory leak
function MyComponent() {
const largeArray = new Array(1000000).fill(0);
window.myGlobalCallback = () => {
console.log(largeArray); // Closure holds reference
};
return <div>Component</div>;
}
// largeArray never gets GC'd until callback is removed
// β
Fixed
function MyComponent() {
const largeArray = new Array(1000000).fill(0);
useEffect(() => {
const callback = () => console.log(largeArray);
window.myGlobalCallback = callback;
return () => {
delete window.myGlobalCallback; // Cleanup
};
}, []);
}
Key Point: Closures keep variables in memory. Clean up event listeners, timers, and global references in useEffect cleanup.
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// β Child re-renders every time
function Parent() {
const config = { color: 'red' }; // New object each render
const handleClick = () => console.log('clicked'); // New function
return <Child config={config} onClick={handleClick} />;
}
const Child = React.memo(({ config, onClick }) => {
// config and onClick are "new" every time
// Props appear different to React, so re-render happens
return <button onClick={onClick}>Click</button>;
});
// β
Fixed with useMemo and useCallback
function Parent() {
const config = useMemo(() => ({ color: 'red' }), []);
const handleClick = useCallback(() => console.log('clicked'), []);
return <Child config={config} onClick={handleClick} />;
}
Key Point: React.memo compares props by reference, not value. Memoize objects and functions.
// β
Function declarations are hoisted
console.log(sum(2, 3)); // Works! Output: 5
function sum(a, b) { return a + b; }
// β Function expressions are NOT hoisted
console.log(add(2, 3)); // Error: add is not a function
const add = (a, b) => a + b;
// β Variables with let/const have temporal dead zone
console.log(x); // Error: Cannot access 'x'
let x = 5;
// β
var is hoisted (set to undefined initially)
console.log(y); // undefined
var y = 5;
Why It Matters in React: Affects callback order, hook dependencies, and debugging. Understand what's available when.
// Use case: Store private data on objects
const privateData = new WeakMap();
class User {
constructor(name) {
this.name = name;
privateData.set(this, { password: 'secret123' });
}
getPassword() {
return privateData.get(this);
}
}
let user = new User('Alice');
user.getPassword(); // { password: 'secret123' }
user = null; // When user is garbage collected,
// privateData entry is automatically removed too
// Real Uber use: Cache DOM nodes without preventing GC
const domCache = new WeakMap();
// Why not just use an object key?
// - Map would keep all objects in memory forever
// - WeakMap allows GC when object is no longer referenced
Key Benefit: Memory safety. Used in libraries for private properties and DOM caching.
// β Bad: No keys, position-based
{items.map((item, index) => (
<div key={index}>{item.name}</div>
))}
// Problem: Reordering breaks component state
// β
Good: Unique keys
{items.map(item => (
<div key={item.id}>{item.name}</div>
))}
// React matches elements by id, not position
// React compares:
// 1. Element type (div vs span = different)
// 2. Props (className, onClick changed = update)
// 3. Children (recursively)
Performance Impact: Bad keys = re-render 100 items instead of 1. Keys are critical for lists.
// Debounce: Wait 300ms after user stops typing
const debounce = (fn, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
};
// Throttle: Call at most once every 300ms
const throttle = (fn, delay) => {
let lastRun = 0;
return (...args) => {
const now = Date.now();
if (now - lastRun >= delay) {
fn(...args);
lastRun = now;
}
};
};
// In React:
const [searchTerm, setSearchTerm] = useState('');
const handleSearch = useMemo(
() => debounce(async (term) => {
const results = await fetch(`/search?q=${term}`);
// Update results
}, 300),
[]
);
return <input onChange={(e) => handleSearch(e.target.value)} />;
When to Use: Debounce for search/autocomplete, throttle for scroll/resize.
React isn't magic; it's philosophy. Understanding why Uber picks React, state patterns, and performance separates engineers who know the tool from those who master the craft. Master the craft with us β
Build a feature end-to-end with working UI and actual data processing.
Hard | Time: 90 min
Enter any two locations (pre-filled with real SF locations), select ride type, and click "Get Fare Estimate" to see the fare calculation in action. Use promo codes UBER10 or SAVE20 for discounts.
import React, { useState } from 'react';
// Mock location database
const LOCATIONS = {
'downtown sf': { lat: 37.7749, lng: -122.4194 },
'airport terminal 2': { lat: 37.6213, lng: -122.3790 },
'pier 39': { lat: 37.8087, lng: -122.4098 },
'golden gate': { lat: 37.8199, lng: -122.4783 }
};
const RIDE_TYPES = {
'UBER_X': { rate: 1.50, name: 'Uber X' },
'UBER_PREMIER': { rate: 2.50, name: 'Uber Premier' }
};
const PROMO_CODES = {
'UBER10': 0.10,
'SAVE20': 0.20
};
const calculateDistance = (loc1, loc2) => {
// Simplified: use Manhattan distance
const dx = Math.abs(loc1.lat - loc2.lat);
const dy = Math.abs(loc1.lng - loc2.lng);
// 1 degree β 111 km
return Math.sqrt(dx * dx + dy * dy) * 111;
};
function RideBooking() {
const [pickup, setPickup] = useState('Downtown SF');
const [dropoff, setDropoff] = useState('Airport Terminal 2');
const [rideType, setRideType] = useState('UBER_X');
const [promoCode, setPromoCode] = useState('');
const [fareData, setFareData] = useState(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const handleEstimateFare = () => {
// Validate inputs
if (!pickup.trim() || !dropoff.trim()) {
setError('Please enter both locations');
return;
}
if (pickup.toLowerCase() === dropoff.toLowerCase()) {
setError('Pickup and dropoff must be different');
return;
}
setLoading(true);
setError('');
// Simulate API call
setTimeout(() => {
const pickupKey = pickup.toLowerCase();
const dropoffKey = dropoff.toLowerCase();
const loc1 = LOCATIONS[pickupKey] || {
lat: 37.7749 + Math.random() * 0.5,
lng: -122.4194 + Math.random() * 0.5
};
const loc2 = LOCATIONS[dropoffKey] || {
lat: 37.7749 + Math.random() * 0.5,
lng: -122.4194 + Math.random() * 0.5
};
const distance = calculateDistance(loc1, loc2).toFixed(1);
const baseFare = 5;
const rideRate = RIDE_TYPES[rideType].rate;
const distanceCharge = (distance * rideRate).toFixed(2);
const subtotal = (parseFloat(baseFare) +
parseFloat(distanceCharge)).toFixed(2);
let discount = 0;
if (PROMO_CODES[promoCode.toUpperCase()]) {
discount = (subtotal *
PROMO_CODES[promoCode.toUpperCase()]).toFixed(2);
}
const finalPrice =
(parseFloat(subtotal) - parseFloat(discount)).toFixed(2);
setFareData({
distance,
baseFare,
distanceCharge,
subtotal,
discount,
finalPrice,
promoApplied: promoCode.toUpperCase()
});
setLoading(false);
}, 800);
};
const handleBookRide = () => {
if (!fareData) return;
setLoading(true);
// Simulate booking API
setTimeout(() => {
setError('');
setFareData(null);
setPickup('');
setDropoff('');
setPromoCode('');
alert(`β Ride booked! Total: $${fareData.finalPrice}`);
setLoading(false);
}, 600);
};
return (
<div>
<input value={pickup} onChange={(e) => setPickup(e.target.value)} />
<input value={dropoff}
onChange={(e) => setDropoff(e.target.value)} />
<select value={rideType}
onChange={(e) => setRideType(e.target.value)}>
{Object.entries(RIDE_TYPES).map(([key, val]) => (
<option key={key} value={key}>
{val.name} (${val.rate}/km)
</option>
))}
</select>
<input value={promoCode}
onChange={(e) => setPromoCode(e.target.value)}
placeholder="Promo code" />
<button onClick={handleEstimateFare} disabled={loading}>
{loading ? 'Estimating...' : 'Get Estimate'}
</button>
{error && <div style={{color: 'red'}}>{error}</div>}
{fareData && (
<>
<div>Distance: {fareData.distance} km</div>
<div>Base: ${fareData.baseFare}</div>
<div>Distance Charge: ${fareData.distanceCharge}</div>
{fareData.discount > 0 && (
<div>Discount: -${fareData.discount}</div>
)}
<div><strong>Total: ${fareData.finalPrice}</strong></div>
<button onClick={handleBookRide} disabled={loading}>
{loading ? 'Booking...' : 'Book Ride'}
</button>
</>
)}
</div>
);
}
export default RideBooking;
Building features is easy. Building the *right* features, the *right way*, at *Uber's scale*βthat's the skill. Architecture decisions under pressure are what they're watching for. Learn to architect like they think β
Deep-dive into architecture, scaling, and trade-offs at Uber scale.
Questions focused on frontend engineering, technical decisions, and team collaboration.
Between you and Uber's system design round sits caching strategies, trade-off thinking, and failure scenarios. They'll probe. Most stumble. Learn to answer with confidence β
From LRU cache design to global system architectureβthis is the complete Uber interview roadmap. But knowing what to expect and being able to deliver under pressure are two different things.
Our cohort has helped a few developers crack interviews at Uber, Microsoft, Atlassian, and Amazon. They didn't just learn the conceptsβthey learned to think like a Uber engineer.
What our cohort members get:
Cohort 2 starts June 2026. Limited to 25 seats. Early birds get exclusive pricing.
Join our cohort for structured prep, mock interviews, and personalized feedback.
Join Next Cohort